Skip to content

OSAC-3781: Add lifecycle and delete row actions - #134

Merged
openshift-merge-bot[bot] merged 8 commits into
osac-project:mainfrom
batzionb:feature/OSAC-3781
Aug 11, 2026
Merged

OSAC-3781: Add lifecycle and delete row actions#134
openshift-merge-bot[bot] merged 8 commits into
osac-project:mainfrom
batzionb:feature/OSAC-3781

Conversation

@batzionb

@batzionb batzionb commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

OSAC-3781: Add lifecycle and delete row actions

Jira: OSAC-3781
Story type: [UI]

Depends on #129 (OSAC-3780) — already merged, so this PR
targets main directly.

Summary

Adds per-row lifecycle actions (Deprecate, Obsolete, Reactivate) and a
state-gated Delete action to the provider-admin instance type list page,
following the same state-machine and error-handling contracts as the VM
power-action and delete precedents already in the codebase.

Changes

  • API hooks (libs/ui-components/src/api/v1/private/instance-type.ts): added InstanceTypeLifecycleAction union, useUpdateInstanceTypeState (single mutation parameterized by action, mirroring usePatchComputeInstance), useDeleteInstanceType, and a shared invalidateInstanceTypesQueries helper.
  • Row actions UI (libs/ui-components/src/components/InstanceType/): new AdminInstanceTypeActionsMenu (kebab menu, action availability computed from current state), InstanceTypeDeleteConfirmModal (delete confirmation with inline error alert), useInstanceTypeLifecycleAction + instanceTypeLifecycleErrorTitle (toast-based failure surfacing for lifecycle actions, mirroring useVmPowerAction).
  • Table wiring (AdminInstanceTypeTable.tsx): added an Actions column rendering the new per-row menu.
  • Test infra (libs/ui-components/src/test-utils/createMockConnectTransport.ts): added update/delete/list override support for the private InstanceTypes mock service.
  • i18n: new translation keys for action labels and the four locked failure-alert titles.

Testing

  • Unit tests: mutation-hook tests for lifecycle updates and delete; row-action availability tests for ACTIVE, DEPRECATED, OBSOLETE, and unset state; failure-title and toast/inline-alert delivery tests.
  • Integration tests: page-level tests verifying the correct update/delete request is sent and the list re-fetches after success.
  • E2E: manual verification only, per the story's testing approach — no new persisted browser E2E.
  • Coverage: comprehensive through public interfaces; 552/552 unit tests passing; full validation report in the implementation branch's .artifacts/implement/OSAC-3781/05-validation-report.md.

Acceptance Criteria

  • AC-1: Each row exposes Deprecate, Obsolete, and Reactivate only when the current state allows that action.
  • AC-2: Delete is shown only for OBSOLETE instance types, never for ACTIVE or DEPRECATED.
  • AC-3: Lifecycle and delete actions call the documented private API behavior and refresh the list on success.
  • AC-4: Lifecycle and delete failures render the documented alerts, including "Failed to delete instance type" for delete failures. (Lifecycle failures use the existing toast system, merged into main after this story's design doc was written, for consistency with VM power actions; delete failures use an inline alert in the confirm modal with the exact required title.)

Video

video.webm

Summary by CodeRabbit

  • New Features
    • Added instance-type lifecycle actions: deprecate, mark obsolete, and reactivate.
    • Added permanent deletion with a confirmation dialog and inline error handling.
    • Added row-level action menus with options based on the instance type’s current state.
    • Instance-type lists now refresh automatically after updates or deletions.
  • Localization
    • Added messages for lifecycle actions, outcomes, and deletion confirmation.
  • Tests
    • Expanded coverage for lifecycle transitions, deletion, error handling, and list refresh behavior.

@openshift-ci-robot

openshift-ci-robot commented Aug 10, 2026

Copy link
Copy Markdown

@batzionb: This pull request references OSAC-3781 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set.

Details

In response to this:

OSAC-3781: Add lifecycle and delete row actions

Jira: OSAC-3781
Story type: [UI]

Depends on #129 (OSAC-3780) — already merged, so this PR
targets main directly.

Summary

Adds per-row lifecycle actions (Deprecate, Obsolete, Reactivate) and a
state-gated Delete action to the provider-admin instance type list page,
following the same state-machine and error-handling contracts as the VM
power-action and delete precedents already in the codebase.

Changes

  • API hooks (libs/ui-components/src/api/v1/private/instance-type.ts): added InstanceTypeLifecycleAction union, useUpdateInstanceTypeState (single mutation parameterized by action, mirroring usePatchComputeInstance), useDeleteInstanceType, and a shared invalidateInstanceTypesQueries helper.
  • Row actions UI (libs/ui-components/src/components/InstanceType/): new AdminInstanceTypeActionsMenu (kebab menu, action availability computed from current state), InstanceTypeDeleteConfirmModal (delete confirmation with inline error alert), useInstanceTypeLifecycleAction + instanceTypeLifecycleErrorTitle (toast-based failure surfacing for lifecycle actions, mirroring useVmPowerAction).
  • Table wiring (AdminInstanceTypeTable.tsx): added an Actions column rendering the new per-row menu.
  • Test infra (libs/ui-components/src/test-utils/createMockConnectTransport.ts): added update/delete/list override support for the private InstanceTypes mock service.
  • i18n: new translation keys for action labels and the four locked failure-alert titles.

Testing

  • Unit tests: mutation-hook tests for lifecycle updates and delete; row-action availability tests for ACTIVE, DEPRECATED, OBSOLETE, and unset state; failure-title and toast/inline-alert delivery tests.
  • Integration tests: page-level tests verifying the correct update/delete request is sent and the list re-fetches after success.
  • E2E: manual verification only, per the story's testing approach — no new persisted browser E2E.
  • Coverage: comprehensive through public interfaces; 552/552 unit tests passing; full validation report in the implementation branch's .artifacts/implement/OSAC-3781/05-validation-report.md.

Acceptance Criteria

  • AC-1: Each row exposes Deprecate, Obsolete, and Reactivate only when the current state allows that action.
  • AC-2: Delete is shown only for OBSOLETE instance types, never for ACTIVE or DEPRECATED.
  • AC-3: Lifecycle and delete actions call the documented private API behavior and refresh the list on success.
  • AC-4: Lifecycle and delete failures render the documented alerts, including "Failed to delete instance type" for delete failures. (Lifecycle failures use the existing toast system, merged into main after this story's design doc was written, for consistency with VM power actions; delete failures use an inline alert in the confirm modal with the exact required title.)

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a13b8de7-3b53-4a6c-821a-c971b0f7bf9e

📥 Commits

Reviewing files that changed from the base of the PR and between 49cec87 and f25d7b8.

📒 Files selected for processing (4)
  • libs/i18n/locales/en/translation.json
  • libs/ui-components/src/components/InstanceType/AdminInstanceTypeActionsMenu.tsx
  • libs/ui-components/src/components/InstanceType/useInstanceTypeLifecycleAction.ts
  • libs/ui-components/src/test-utils/createMockConnectTransport.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • libs/i18n/locales/en/translation.json
  • libs/ui-components/src/components/InstanceType/AdminInstanceTypeActionsMenu.tsx
  • libs/ui-components/src/test-utils/createMockConnectTransport.ts

Walkthrough

Instance-type administration now supports lifecycle state changes and deletion through row action menus, confirmation dialogs, API mutations, query invalidation, localized errors, and integration tests.

Changes

Instance-type management

Layer / File(s) Summary
API mutations and test transport
libs/ui-components/src/api/v1/private/instance-type.ts, libs/ui-components/src/api/v1/private/instance-type.test.ts, libs/ui-components/src/test-utils/createMockConnectTransport.ts
Added update and delete mutations, update-mask generation, response validation, query invalidation, and configurable mock handlers.
Admin lifecycle and deletion actions
libs/ui-components/src/components/InstanceType/AdminInstanceTypeActionsMenu.tsx, libs/ui-components/src/components/InstanceType/InstanceTypeDeleteConfirmModal.tsx, libs/ui-components/src/components/InstanceType/useInstanceTypeLifecycleAction.ts, libs/i18n/locales/en/translation.json, libs/ui-components/src/components/InstanceType/AdminInstanceTypeActionsMenu.test.tsx
Added state-dependent lifecycle actions, deletion confirmation, localized failure handling, and component tests.
List table integration and refresh validation
libs/ui-components/src/components/InstanceType/AdminInstanceTypeTable.tsx, libs/ui-components/src/components/InstanceType/AdminInstanceTypeListPage.test.tsx
Added the Actions column and row menus. Tests verify lifecycle updates, deletion, list refresh, row removal, and the empty state.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Admin as AdminInstanceTypeActionsMenu
  participant Lifecycle as useInstanceTypeLifecycleAction
  participant Update as useUpdateInstanceType
  participant Query as InstanceTypes query
  Admin->>Lifecycle: Select lifecycle action
  Lifecycle->>Update: Submit target state
  Update->>Query: Invalidate instance-type queries
  Query-->>Admin: Refresh instance-type list
Loading

Possibly related PRs

Suggested reviewers: jhernand, rccrdpccl

🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding lifecycle and delete actions to instance-type rows.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No-Hardcoded-Secrets ✅ Passed The full PR diff adds no API keys, tokens, passwords, embedded URL credentials, private keys, or base64/hex blobs over 32 characters; the mock password predates the PR.
No-Weak-Crypto ✅ Passed The full origin/main...HEAD diff adds no MD5, SHA1, DES, RC4, 3DES, Blowfish, ECB, crypto APIs, or secret comparisons; changed code contains only API, state, and UI logic.
No-Injection-Vectors ✅ Passed PR changes contain no eval/exec, pickle.loads, yaml.load, os.system, shell=True, or dangerouslySetInnerHTML; API calls use typed Connect RPC, and user text uses normal React rendering.
Container-Privileges ✅ Passed The PR changes no container or Kubernetes manifests; no flagged privilege keys exist, and the production Containerfile runs as USER 1001 while root is limited to build stages.
No-Sensitive-Data-In-Logs ✅ Passed The PR adds no console, logger, print, trace, or audit calls; backend errors appear only in intended UI toast/inline alert paths, and the password fixture is pre-existing.
Ai-Attribution ✅ Passed Claude Code is credited with an Assisted-by trailer on all 8 PR commits; no AI-related Co-Authored-By trailer is present.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@batzionb
batzionb marked this pull request as ready for review August 10, 2026 19:05
@openshift-ci
openshift-ci Bot requested review from jhernand and rccrdpccl August 10, 2026 19:06

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@libs/ui-components/src/api/v1/private/instance-type.test.ts`:
- Line 113: Remove the duplicate object declarations in the affected tests,
keeping exactly one declaration at each scope around the captured object
assertions. Preserve the existing type annotation and usages while resolving the
block-scoped redeclaration errors.

In
`@libs/ui-components/src/components/InstanceType/AdminInstanceTypeListPage.test.tsx`:
- Line 204: In the test scope containing the captured object assertion, remove
the duplicate declarations of object and retain a single typed declaration for
the captured object, avoiding the block-scoped redeclaration error.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 7eb9d07c-3ad2-4ec2-b10f-0a7927e54de6

📥 Commits

Reviewing files that changed from the base of the PR and between d0cbc5a and 509e446.

📒 Files selected for processing (12)
  • libs/i18n/locales/en/translation.json
  • libs/ui-components/src/api/v1/private/instance-type.test.ts
  • libs/ui-components/src/api/v1/private/instance-type.ts
  • libs/ui-components/src/components/InstanceType/AdminInstanceTypeActionsMenu.test.tsx
  • libs/ui-components/src/components/InstanceType/AdminInstanceTypeActionsMenu.tsx
  • libs/ui-components/src/components/InstanceType/AdminInstanceTypeListPage.test.tsx
  • libs/ui-components/src/components/InstanceType/AdminInstanceTypeTable.tsx
  • libs/ui-components/src/components/InstanceType/InstanceTypeDeleteConfirmModal.tsx
  • libs/ui-components/src/components/InstanceType/instanceTypeLifecycleErrorTitle.test.ts
  • libs/ui-components/src/components/InstanceType/instanceTypeLifecycleErrorTitle.ts
  • libs/ui-components/src/components/InstanceType/useInstanceTypeLifecycleAction.ts
  • libs/ui-components/src/test-utils/createMockConnectTransport.ts

Comment thread libs/ui-components/src/api/v1/private/instance-type.test.ts
reactivate: InstanceTypeState.ACTIVE,
};

const buildLifecycleStateBody = (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function doesnt contain any logic

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — this collapses once the hook takes a body directly (see the reply on the next comment).

action: InstanceTypeLifecycleAction;
};

export const useUpdateInstanceTypeState = () => {

@rawagner rawagner Aug 11, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of having a hook that handles single type of update (spec.status), i'd prefer to have a hook that handles updating the whole spec - ie useUpdateInstanceType that accepts

{
  id: string;
  body: MessageInitShape<typeof InstanceTypeSchema>;
}

The caller that passes the body that it wants to update. This should be a general pattern in our api hooks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed — checked the other hooks and the generic { id, body } shape is actually the dominant pattern already (useUpdateIdentityProvider, useUpdateSecurityGroup, useUpdateStorageTier, useUpdateStorageBackend). Only usePatchComputeInstance uses the action-parameterized style this PR had mirrored. Switched useUpdateInstanceTypeState to a generic useUpdateInstanceType({ id, body }); the action→state mapping now lives in useInstanceTypeLifecycleAction, its only caller.


import type { InstanceTypeLifecycleAction } from '../../api/v1/private/instance-type';

export const getInstanceTypeLifecycleErrorTitle = (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we move this into useInstanceTypeLifecycleAction ? I dont think there will be any other consumer to justify having this function exported

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed, no other consumer — moved it into useInstanceTypeLifecycleAction.ts as a local (unexported) helper. Deleted instanceTypeLifecycleErrorTitle.ts and its dedicated test, and added an equivalent behavioral test (obsolete-failure toast title) to AdminInstanceTypeActionsMenu.test.tsx so all three lifecycle failure titles stay covered through the public interface.

const { addToast } = useToast();
const updateInstanceType = useUpdateInstanceType();

const runLifecycleAction = (instanceTypeId: string, action: InstanceTypeLifecycleAction) => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

one more question, why not simply

Suggested change
const runLifecycleAction = (instanceTypeId: string, action: InstanceTypeLifecycleAction) => {
const runLifecycleAction = (instanceTypeId: string, action: InstanceTypeState) => {

do we need custom InstanceTypeLifecycleAction ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call — switched to InstanceTypeState directly: InstanceTypeLifecycleAction is now Exclude<InstanceTypeState, InstanceTypeState.UNSPECIFIED>, so it stays narrower than the raw enum (UNSPECIFIED still isn't a valid action) while dropping the LIFECYCLE_ACTION_STATE lookup table entirely, since the action is the target state now.

Add useUpdateInstanceTypeState and useDeleteInstanceType, parameterized
by an InstanceTypeLifecycleAction union mirroring usePatchComputeInstance,
plus mock transport support for the InstanceTypes Update/Delete RPCs.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
…mation

Add AdminInstanceTypeActionsMenu with state-gated Deprecate/Obsolete/
Reactivate/Delete row actions: lifecycle transitions mutate directly and
surface failures via toast (mirroring useVmPowerAction), while Delete is
gated behind a confirm modal with an inline error (mirroring
VmDeleteConfirmModal).

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
…pe table

Add an Actions column rendering AdminInstanceTypeActionsMenu per row,
and add integration tests verifying the update/delete request sent from
the row menu and that the admin instance types list re-fetches after a
successful mutation.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
Treat an unset (UNSPECIFIED) instance type state the same as ACTIVE
when gating row actions, matching the backend, which always defaults
state to ACTIVE on creation.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
Replace the action-parameterized useUpdateInstanceTypeState with a
generic useUpdateInstanceType({ id, body }), matching the dominant
existing pattern (useUpdateIdentityProvider, useUpdateSecurityGroup,
useUpdateStorageTier, useUpdateStorageBackend) instead of the
compute-instance power-action outlier this PR had mirrored. The
action->state mapping and error-title lookup move into
useInstanceTypeLifecycleAction, the hook's only consumer, removing
the now-pointless single-line buildLifecycleStateBody wrapper and the
separately exported instanceTypeLifecycleErrorTitle module.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
Completes the previous commit — the source changes for the
useUpdateInstanceType generalization were left unstaged.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
Drop the string-literal InstanceTypeLifecycleAction union in favor of
Exclude<InstanceTypeState, InstanceTypeState.UNSPECIFIED>, removing
the LIFECYCLE_ACTION_STATE lookup table entirely — the action is the
target state. Excluding UNSPECIFIED keeps the type narrower than the
raw enum, so it can't represent a non-action, and getLifecycleErrorTitle's
switch stays exhaustively checked.

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: batzionb <brotman@redhat.com>
@openshift-ci

openshift-ci Bot commented Aug 11, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: batzionb, rawagner

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-bot
openshift-merge-bot Bot merged commit d968bbc into osac-project:main Aug 11, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants