Skip to content

Deploy view UX rework: separate release creation from deployment, add compare, polish#533

Open
kaviththiranga wants to merge 16 commits into
openchoreo:mainfrom
kaviththiranga:release-ux-reabsed
Open

Deploy view UX rework: separate release creation from deployment, add compare, polish#533
kaviththiranga wants to merge 16 commits into
openchoreo:mainfrom
kaviththiranga:release-ux-reabsed

Conversation

@kaviththiranga
Copy link
Copy Markdown
Contributor

@kaviththiranga kaviththiranga commented May 13, 2026

Reworks the deploy view UX around a clearer release-then-deploy mental model and adds a release
compare experience.

Setup card: split creation from deployment

Splits the old combined "create release & deploy" into two distinct stories — Release (component
config → snapshot) and Deploy (pick from existing releases → deploy to lowest env). The Setup
detail pane now branches on autoDeploy:

  • Auto-deploy ON: single Configure component button + read-only latest release row. Manual
    edits no longer fight the controller, which auto-creates releases and reverts manual ReleaseBinding
    edits anyway.
  • Auto-deploy OFF: today's two-story view, with caption-above-button rhythm matching the rest of
    the pane.

autoDeploy is hoisted to EnvironmentsContext via a new useAutoDeploy hook, eliminating flicker
between the Setup card and the Workload page (each previously fetched independently with false
defaults).

Release picker → full-featured browser

Replaces the cramped MUI Autocomplete in the Deploy section with a modal: searchable left list +
right details pane with the manifest YAML. A tinted background panel groups the selected-release
summary so name, meta chips, and the Change button read as one unit even with multi-env "current in
X" chips wrapping.

Release compare mode

New View/Compare toggle in the browser's right pane. In Compare mode the user picks any reference
release from a grouped Autocomplete (current-in-env bindings first, then any other release) and the
right pane renders a side-by-side YamlDiffViewer. When opened with an environmentName, pre-fills
the comparison target with that env's current release so the common "is this release different from
what's deployed?" question resolves in zero clicks.

Configure-overrides page

  • Action-aware title/subtitle (Deploy to {env} / Promote to {env} / Required overrides for {env}) instead of the misleading generic header.
  • New "Not in workload" section surfaces overrides on env vars/files that don't exist in the
    release's current workload (previously labeled "{env} Specific" and hidden under the wrong group).
    Session-added rows get a NEW chip.
  • "View release diff" button (formerly "View diff") opens an inline diff dialog. Diff orientation
    flipped to the conventional before-on-left (target env's current release) / after-on-right
    (incoming release).

Deploy canvas

  • Setup tile differentiated from env tiles: narrower (180×96 vs 240×140), dashed border,
    primary-tinted Start chip in the top-left.
  • Connector geometry handled automatically by dagre; no other layout changes.

Inner-page polish (DetailPageLayout)

  • Esc keyboard shortcut closes inner pages via the same onBack path (so unsaved-changes dialogs
    still fire). Visible Esc chip stacked under the back arrow.
  • Height contract: calc(100vh − 200px) with min-height: 480 + overflow: hidden. Matches the
    deploy list view's splitContainer pattern so the inner content scroll region works correctly and
    the page never pushes Backstage's outer <Page> into external scroll.

Bug fixes along the way

  • YamlDiffViewer: scroll now bounded correctly. Per CodeMirror docs, the .cm-mergeView itself is
    the intended scroller — applying height + overflow: auto there makes both panes scroll together as
    one unit, line-aligned.
  • extractImage: was reading release.spec.workload.spec.container.image (one .spec too deep).
    Search by image silently matched nothing and the img: line never rendered. Fixed in both
    ReleasePicker and ReleaseBrowserDialog.
  • DeployReleasePanel: Deploy button disabled when the selected release is already current in the
    target env (case-insensitive env-name match to handle Development vs development).

Copy

Auto-deploy tooltip now matches the confirmation dialog. Both reference "lowest environment" instead
of "default environment".

Test plan

  • yarn tsc clean.
  • yarn workspace @openchoreo/backstage-plugin test --watch=false green.
  • yarn workspace @openchoreo/backstage-plugin-react test --watch=false green.
  • Auto-deploy OFF: Setup → Create release routes to workload page; saving snapshots a release.
    Picking a release → Deploy disabled when the release is already current in target env; otherwise
    navigates to overrides.
  • Auto-deploy ON: Setup shows Configure component + read-only Latest release; no flicker on first
    render.
  • Release browser: search filters by name, image, and env. Compare mode pre-fills with
    current-in-env. Switching compare target re-renders the diff. View ↔ Compare round-trip is free
    (cached).
  • Overrides page: title flips to action-aware copy. "Not in workload" section shows extra/new
    overrides correctly. View release diff opens with target on LHS, upstream on RHS.
  • Inner pages: Esc closes them. Pages fit viewport without external scroll on the entity tab.
  • Deploy canvas: setup tile is visibly smaller than env tiles with a START chip; connectors land
    cleanly.

Summary by CodeRabbit

  • New Features

    • Browse, filter, compare, and select component releases via a new release browser and picker
    • Create component releases with a new release creation dialog
    • Fetch/list component releases and release hooks for UI consumption
    • Deploy panel to pick and deploy releases
  • UI/UX Improvements

    • Escape-key shortcut to go back on detail pages
    • Clearer release diff orientation and "View release diff" labels
    • "NEW" chips and new "extra"/"new" statuses to distinguish persisted vs. session-added overrides
    • Compact setup card and streamlined setup/detail panels

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Warning

Rate limit exceeded

@kaviththiranga has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 53 minutes and 7 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 16121f70-e3fb-4dd4-ba65-72a2b4451364

📥 Commits

Reviewing files that changed from the base of the PR and between c3fabfc and dfa4c34.

📒 Files selected for processing (45)
  • plugins/openchoreo-backend/src/router.ts
  • plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts
  • plugins/openchoreo-react/src/components/DetailPageLayout/DetailPageLayout.test.tsx
  • plugins/openchoreo-react/src/components/DetailPageLayout/DetailPageLayout.tsx
  • plugins/openchoreo-react/src/components/EnvVarStatusBadge/EnvVarStatusBadge.tsx
  • plugins/openchoreo-react/src/components/FileVarStatusBadge/FileVarStatusBadge.tsx
  • plugins/openchoreo-react/src/components/GroupedSection/GroupedSection.tsx
  • plugins/openchoreo-react/src/components/OverrideEnvVarList/OverrideEnvVarList.tsx
  • plugins/openchoreo-react/src/components/OverrideFileVarList/OverrideFileVarList.tsx
  • plugins/openchoreo-react/src/components/PipelineFlowVisualization/dag/pipelineLayoutUtils.ts
  • plugins/openchoreo-react/src/components/YamlDiffViewer/YamlDiffViewer.tsx
  • plugins/openchoreo-react/src/utils/envVarUtils.test.ts
  • plugins/openchoreo-react/src/utils/envVarUtils.ts
  • plugins/openchoreo-react/src/utils/fileVarUtils.test.ts
  • plugins/openchoreo-react/src/utils/fileVarUtils.ts
  • plugins/openchoreo-react/src/utils/overrideGroupUtils.test.ts
  • plugins/openchoreo-react/src/utils/overrideGroupUtils.ts
  • plugins/openchoreo/src/api/OpenChoreoClient.ts
  • plugins/openchoreo/src/api/OpenChoreoClientApi.ts
  • plugins/openchoreo/src/components/Environments/EnvironmentOverridesPage.tsx
  • plugins/openchoreo/src/components/Environments/Environments.test.tsx
  • plugins/openchoreo/src/components/Environments/Environments.tsx
  • plugins/openchoreo/src/components/Environments/EnvironmentsContext.tsx
  • plugins/openchoreo/src/components/Environments/Workload/WorkloadConfigPage.tsx
  • plugins/openchoreo/src/components/Environments/Workload/WorkloadEditor/ContainerContent.tsx
  • plugins/openchoreo/src/components/Environments/components/AutoDeployConfirmationDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/ComponentReleaseDiffDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/CreateReleaseDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/DeployReleasePanel.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.tsx
  • plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.test.tsx
  • plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/ReleasePicker.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx
  • plugins/openchoreo/src/components/Environments/hooks/index.ts
  • plugins/openchoreo/src/components/Environments/hooks/useAutoDeploy.ts
  • plugins/openchoreo/src/components/Environments/hooks/useReleaseReadiness.ts
  • plugins/openchoreo/src/components/Environments/hooks/useReleases.ts
  • plugins/openchoreo/src/components/Environments/styles.ts
  • plugins/openchoreo/src/components/Environments/wrappers/OverridesWrapper.tsx
  • plugins/openchoreo/src/components/Environments/wrappers/WorkloadConfigWrapper.tsx
📝 Walkthrough

Walkthrough

Adds backend and client APIs to list component releases, implements release browser/picker/create UIs with manifest fetching and compare mode, extends override/file/env var statuses with an "extra" category and initial-snapshot support, refactors setup/deploy flows to use hooks/context, and includes various UI/UX and test updates.

Changes

Release Management & Override Status System

Layer / File(s) Summary
Backend releases API
plugins/openchoreo-backend/src/router.ts, plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts
GET /component-releases endpoint with componentName and namespaceName query params; service method calls OpenChoreo API and returns data.items.
Frontend API client and response types
plugins/openchoreo/src/api/OpenChoreoClient.ts, plugins/openchoreo/src/api/OpenChoreoClientApi.ts
Adds COMPONENT_RELEASES endpoint, ComponentReleasesResponse type, and OpenChoreoClient.listComponentReleases(entity) method.
Override status types and utilities
plugins/openchoreo-react/src/utils/envVarUtils.ts, plugins/openchoreo-react/src/utils/fileVarUtils.ts, plugins/openchoreo-react/src/utils/overrideGroupUtils.ts
Adds extra status to EnvVar/FileVar unions; merge*WithStatus accept optional initial snapshots to distinguish extra vs new; grouping and counting utilities updated to include extra.
Status and grouping utility tests
plugins/openchoreo-react/src/utils/*.test.ts
Adds and adjusts tests verifying legacy and initial-snapshot behaviors for extra/new statuses and grouping/counting results.
Badge components for extra status
plugins/openchoreo-react/src/components/EnvVarStatusBadge/EnvVarStatusBadge.tsx, plugins/openchoreo-react/src/components/FileVarStatusBadge/FileVarStatusBadge.tsx
Adds extra visual variant and statusConfig entries to render "Extra" badge/tooltip.
Override lists with initial data and new status chips
plugins/openchoreo-react/src/components/OverrideEnvVarList/OverrideEnvVarList.tsx, plugins/openchoreo-react/src/components/OverrideFileVarList/OverrideFileVarList.tsx, plugins/openchoreo/src/components/Environments/Workload/WorkloadEditor/ContainerContent.tsx
Override lists accept optional initialEnvVars/initialFileVars, pass them into merge utils, render "NEW" chips for status==='new', and consolidate "Not in workload" sections combining extra and new.
Release browser dialog, picker, and create dialog
plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.tsx, .../ReleaseBrowserDialog.test.tsx, ReleasePicker.tsx, CreateReleaseDialog.tsx
Implements release browsing with search/filter, manifest fetch + caching, compare (diff) mode; ReleasePicker UI; CreateReleaseDialog with DNS-1123 validation and uniqueness checks.
Release management hooks
plugins/openchoreo/src/components/Environments/hooks/*
Adds useReleases (fetch/sort releases), useAutoDeploy (read auto-deploy flag + refetch), and useReleaseReadiness (determine readiness for creating releases) and re-exports.
WorkloadConfigPage & ContainerContent integration
plugins/openchoreo/src/components/Environments/Workload/WorkloadConfigPage.tsx, .../ContainerContent.tsx
Refactors primary save flow to handleSave and onReleaseCreated callback; integrates auto-deploy state and renders CreateReleaseDialog; ContainerContent passes initialWorkloadData into override lists.
Deploy release panel & picker wiring
plugins/openchoreo/src/components/Environments/components/DeployReleasePanel.tsx, ReleasePicker.tsx
Adds DeployReleasePanel to select and deploy releases, auto-select newest release, compute eligibility and navigate to overrides.
Setup and SetupDetailPane refactors
plugins/openchoreo/src/components/Environments/components/SetupCard.tsx, SetupDetailPane.tsx, tests
Simplifies SetupCard to a compact tile; SetupDetailPane now uses shared hooks/context for auto-deploy and releases, adds LatestReleaseRow, confirmation flows, and refetch logic; tests updated/added.
Environment UI and diff behavior
plugins/openchoreo/src/components/Environments/*, YamlDiffViewer.tsx, pipelineLayoutUtils.ts
Swaps diff orientation in ComponentReleaseDiffDialog, updates labels (e.g., "View release diff"), adjusts YamlDiffViewer scrolling rules, reduces mini setup-node dimensions, and tweaks drift/badge styling and icons.
GroupedSection and DetailPageLayout UX
plugins/openchoreo-react/src/components/GroupedSection/GroupedSection.tsx, DetailPageLayout.tsx, tests
Adds optional titleTooltip with help icon; adds Escape-to-go-back handler and "Esc" kbd hint in DetailPageLayout; title prop now accepts ReactNode; tests added/updated.
Routing and wrappers simplification
plugins/openchoreo/src/components/Environments/wrappers/*
Simplifies wrappers to use navigateToList, removes prior PendingAction->navigateToOverrides flow, and wires onReleaseCreated/onBack to list navigation.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested reviewers

  • sameerajayasoma
  • stefinie123

Poem

🐰 A rabbit hops through release trails,
With dialogs bright and deploy details,
Extra statuses now shine so clear,
From "new" to "extra" the overrides steer,
Setup flows smoothly, no more delays—
Component releases brighten our days! 🚀

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.tsx (1)

181-213: ⚡ Quick win

Extract shared utilities to avoid code duplication.

The helper functions formatRelativeTime, extractImage, and shortenImage are duplicated between ReleaseBrowserDialog.tsx and ReleasePicker.tsx. Consider extracting them to a shared utility module (e.g., releaseUtils.ts) to improve maintainability.

🤖 Prompt for 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.

In
`@plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.tsx`
around lines 181 - 213, The helper functions formatRelativeTime,
formatAbsoluteTime, extractImage, and shortenImage are duplicated; extract them
into a new shared utility module (e.g., export functions from releaseUtils.ts)
and replace the local definitions in ReleaseBrowserDialog.tsx and
ReleasePicker.tsx with imports from that module; ensure the new module exports
the exact named functions (formatRelativeTime, formatAbsoluteTime, extractImage,
shortenImage) and update any call sites to import them, keeping the same
signatures and behavior (including handling undefined/invalid ISO strings and
the specific image extraction shape).
plugins/openchoreo/src/components/Environments/hooks/useReleaseReadiness.ts (1)

75-81: ⚡ Quick win

Consider using URLSearchParams for query string construction.

The current string interpolation works but is harder to maintain. Using URLSearchParams would be more idiomatic and handle edge cases automatically.

🔄 Suggested refactor
+        const params = new URLSearchParams({
+          componentName,
+          projectName,
+          namespaceName,
+        });
         const response = await fetchApi.fetch(
-          `${baseUrl}/builds?componentName=${encodeURIComponent(
-            componentName,
-          )}&projectName=${encodeURIComponent(
-            projectName,
-          )}&namespaceName=${encodeURIComponent(namespaceName)}`,
+          `${baseUrl}/builds?${params.toString()}`,
         );
🤖 Prompt for 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.

In `@plugins/openchoreo/src/components/Environments/hooks/useReleaseReadiness.ts`
around lines 75 - 81, Replace the manual string interpolation used to build the
query in useReleaseReadiness.ts (the fetchApi.fetch call that composes
`${baseUrl}/builds?componentName=...&projectName=...&namespaceName=...`) with a
URLSearchParams instance: create a params object, append componentName,
projectName, and namespaceName, and call
fetchApi.fetch(`${baseUrl}/builds?${params.toString()}`) so encoding and edge
cases are handled automatically.
🤖 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
`@plugins/openchoreo/src/components/Environments/components/CreateReleaseDialog.tsx`:
- Around line 96-115: In handleSubmit, validate response.data.success before
assuming creation succeeded: after receiving response from
client.createComponentRelease check if response.data?.success === false and if
so call setSubmitError(response.data?.error ?? getErrorMessage(new
Error('Release creation failed'))) and setSubmitting(false); only when success
is true proceed to read response.data?.name and call onCreated(created), and if
name is missing throw or setSubmitError accordingly; ensure setSubmitting(false)
is called on all failure paths.

---

Nitpick comments:
In
`@plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.tsx`:
- Around line 181-213: The helper functions formatRelativeTime,
formatAbsoluteTime, extractImage, and shortenImage are duplicated; extract them
into a new shared utility module (e.g., export functions from releaseUtils.ts)
and replace the local definitions in ReleaseBrowserDialog.tsx and
ReleasePicker.tsx with imports from that module; ensure the new module exports
the exact named functions (formatRelativeTime, formatAbsoluteTime, extractImage,
shortenImage) and update any call sites to import them, keeping the same
signatures and behavior (including handling undefined/invalid ISO strings and
the specific image extraction shape).

In `@plugins/openchoreo/src/components/Environments/hooks/useReleaseReadiness.ts`:
- Around line 75-81: Replace the manual string interpolation used to build the
query in useReleaseReadiness.ts (the fetchApi.fetch call that composes
`${baseUrl}/builds?componentName=...&projectName=...&namespaceName=...`) with a
URLSearchParams instance: create a params object, append componentName,
projectName, and namespaceName, and call
fetchApi.fetch(`${baseUrl}/builds?${params.toString()}`) so encoding and edge
cases are handled automatically.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8e305fe1-4543-46b3-985b-120fcee1fd0c

📥 Commits

Reviewing files that changed from the base of the PR and between f5ab097 and 879722a.

📒 Files selected for processing (45)
  • plugins/openchoreo-backend/src/router.ts
  • plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts
  • plugins/openchoreo-react/src/components/DetailPageLayout/DetailPageLayout.test.tsx
  • plugins/openchoreo-react/src/components/DetailPageLayout/DetailPageLayout.tsx
  • plugins/openchoreo-react/src/components/EnvVarStatusBadge/EnvVarStatusBadge.tsx
  • plugins/openchoreo-react/src/components/FileVarStatusBadge/FileVarStatusBadge.tsx
  • plugins/openchoreo-react/src/components/GroupedSection/GroupedSection.tsx
  • plugins/openchoreo-react/src/components/OverrideEnvVarList/OverrideEnvVarList.tsx
  • plugins/openchoreo-react/src/components/OverrideFileVarList/OverrideFileVarList.tsx
  • plugins/openchoreo-react/src/components/PipelineFlowVisualization/dag/pipelineLayoutUtils.ts
  • plugins/openchoreo-react/src/components/YamlDiffViewer/YamlDiffViewer.tsx
  • plugins/openchoreo-react/src/utils/envVarUtils.test.ts
  • plugins/openchoreo-react/src/utils/envVarUtils.ts
  • plugins/openchoreo-react/src/utils/fileVarUtils.test.ts
  • plugins/openchoreo-react/src/utils/fileVarUtils.ts
  • plugins/openchoreo-react/src/utils/overrideGroupUtils.test.ts
  • plugins/openchoreo-react/src/utils/overrideGroupUtils.ts
  • plugins/openchoreo/src/api/OpenChoreoClient.ts
  • plugins/openchoreo/src/api/OpenChoreoClientApi.ts
  • plugins/openchoreo/src/components/Environments/EnvironmentOverridesPage.tsx
  • plugins/openchoreo/src/components/Environments/Environments.test.tsx
  • plugins/openchoreo/src/components/Environments/Environments.tsx
  • plugins/openchoreo/src/components/Environments/EnvironmentsContext.tsx
  • plugins/openchoreo/src/components/Environments/Workload/WorkloadConfigPage.tsx
  • plugins/openchoreo/src/components/Environments/Workload/WorkloadEditor/ContainerContent.tsx
  • plugins/openchoreo/src/components/Environments/components/AutoDeployConfirmationDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/ComponentReleaseDiffDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/CreateReleaseDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/DeployReleasePanel.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.tsx
  • plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.test.tsx
  • plugins/openchoreo/src/components/Environments/components/ReleaseBrowserDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/ReleasePicker.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupCard.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx
  • plugins/openchoreo/src/components/Environments/hooks/index.ts
  • plugins/openchoreo/src/components/Environments/hooks/useAutoDeploy.ts
  • plugins/openchoreo/src/components/Environments/hooks/useReleaseReadiness.ts
  • plugins/openchoreo/src/components/Environments/hooks/useReleases.ts
  • plugins/openchoreo/src/components/Environments/styles.ts
  • plugins/openchoreo/src/components/Environments/wrappers/OverridesWrapper.tsx
  • plugins/openchoreo/src/components/Environments/wrappers/WorkloadConfigWrapper.tsx

Comment on lines +96 to +115
const handleSubmit = async () => {
if (validationError) return;
setSubmitting(true);
setSubmitError(null);
try {
const trimmed = name.trim();
const response = await client.createComponentRelease(
entity,
trimmed || undefined,
);
const created = response.data?.name;
if (!created) {
throw new Error('Release was created but no name was returned.');
}
onCreated(created);
} catch (e: unknown) {
setSubmitError(getErrorMessage(e));
setSubmitting(false);
}
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Description: Verify createComponentRelease API response structure

# Search for the createComponentRelease implementation in the backend
rg -nP 'createComponentRelease' --type=ts -A 10 -B 2

# Also check the client API definition
rg -nP 'createComponentRelease.*\{' --type=ts -A 15

Repository: openchoreo/backstage-plugins

Length of output: 7182


🏁 Script executed:

# Search for CreateReleaseResponse type definition
rg -nP 'type CreateReleaseResponse|interface CreateReleaseResponse' --type=ts -A 5

Repository: openchoreo/backstage-plugins

Length of output: 493


🏁 Script executed:

# Check the backend createComponentRelease implementation for its return structure
rg -nP 'async createComponentRelease' --type=ts -A 30 plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts

Repository: openchoreo/backstage-plugins

Length of output: 1063


🏁 Script executed:

# Get the full createComponentRelease implementation (more lines)
rg -nP 'async createComponentRelease' --type=ts -A 50 plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts | head -60

Repository: openchoreo/backstage-plugins

Length of output: 1751


🏁 Script executed:

# Get more lines to see the full return statement
sed -n '1020,1040p' plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts

Repository: openchoreo/backstage-plugins

Length of output: 634


Validate the success field and pass backend error messages to the user.

The frontend correctly accesses response.data?.name, but it doesn't validate the response.success field. When the backend returns { success: false, error: "..." }, the frontend will incorrectly throw "Release was created but no name was returned" instead of passing the backend's actual error message. Check the success field and use the error message when available.

🤖 Prompt for 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.

In
`@plugins/openchoreo/src/components/Environments/components/CreateReleaseDialog.tsx`
around lines 96 - 115, In handleSubmit, validate response.data.success before
assuming creation succeeded: after receiving response from
client.createComponentRelease check if response.data?.success === false and if
so call setSubmitError(response.data?.error ?? getErrorMessage(new
Error('Release creation failed'))) and setSubmitting(false); only when success
is true proceed to read response.data?.name and call onCreated(created), and if
name is missing throw or setSubmitError accordingly; ensure setSubmitting(false)
is called on all failure paths.

  Foundation for the Setup card revamp that splits release creation from
  deployment. Adds list-releases support end-to-end and extracts the
  release-readiness gating logic into a shared hook.

  - backend: new GET /component-releases route + listComponentReleases
    service method, calling the platform API at
    /api/v1/namespaces/{ns}/componentreleases?component={name}
  - client: new ComponentReleasesResponse type + listComponentReleases
    method on OpenChoreoClientApi
  - hooks: new useReleases (fetch + sort newest-first + refetch) and
    useReleaseReadiness (extracted from WorkloadButton gating)

  No user-visible changes yet — these are consumed by the new Setup card
  components in follow-up commits

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  The workload config page used to apply workload changes, create a
  release, and then navigate to environment overrides for the first env
  — a single "Save & Next" button doing three jobs. With the upcoming
  Setup card revamp, release creation and deployment are owned by the
  Setup card, so this page should only edit and save workload + traits +
  parameters.

  - WorkloadConfigPage: handleNext → handleSave. Drops the
    createComponentRelease call and the navigate-to-overrides step.
    Renames onNext(releaseName, env) to onSaved(). Removes the unused
    lowestEnvironment prop. Buttons relabeled to "Save workload" /
    "Saving..." / "Done"; in-page alert points users back to the Set up
    panel for release creation.
  - WorkloadConfigWrapper: wires onSaved and onBack to navigateToList;
    no longer constructs a deploy PendingAction.

  The Environments.tsx pending-action handler is unchanged because the
  Promote/Redeploy paths on EnvironmentDetailPanel still use it.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  Replaces the single "Configure & Deploy" button with two clear stories
  on the deploy page Set up panel:

  - Create release: dialog with optional name (DNS-1123 + uniqueness
    validated), snapshots current workload/traits/parameters. Surfaces
    an Auto Deploy notice when the controller will auto-bind.
  - Deploy a release: searchable picker over existing releases showing
    timestamp, image, "current in <env>" badges, and view-YAML. "Deploy
    now" uses release defaults; "Configure overrides" deep-links to the
    existing overrides page.

  Edit workload stays as a separate entry; the underlying
  WorkloadConfigPage was decoupled from release creation in a prior
  commit. SetupCard pruned to a passive canvas tile.

  Tests rewritten for the new contract; all Environments tests pass.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
…fy Deploy

  Per UX feedback:

  - Create release now starts on the workload config page. The Set up
    panel's Create release button navigates there; on Save the page
    prompts for an optional release name and creates the snapshot,
    then returns to the deploy list. The standalone "Edit workload"
    button is gone — workload editing is part of the release flow.
  - Deploy is now a single button that always goes through the
    existing /overrides/<env> step. The inline "Deploy now" shortcut
    and direct updateReleaseBinding call are removed.

  WorkloadConfigPage owns the CreateReleaseDialog mount; SetupDetailPane
  no longer renders it. Tests updated accordingly — 226 Environments
  tests pass.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
… modal

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  - New `extra` status alongside `new`: keys not in base are `extra` if
    already on the binding, `new` if added in this session
  - Unified "Not in workload" section with help-icon tooltip; NEW chip
    on session-added rows
  - GroupedSection gains optional `titleTooltip` prop

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  - Auto-deploy on: hide Create/Deploy stories; show Configure component
    + read-only Latest release row.
  - Skip CreateReleaseDialog on save under auto-deploy; show toast instead.
  - Hoist autoDeploy into EnvironmentsContext so Setup card and workload
    page share one fetch and render a skeleton until it loads (no flicker).
  - ReleaseBrowserDialog: optional readOnly mode (no Select button).
  - DetailPageLayout title accepts ReactNode.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  - Deploy / promote flows show "Deploy to {env}" / "Promote to {env}"
    instead of generic "Configure Environment Overrides".
  - Subtitles call out target env and (for promote) source env.
  - Direct binding edits keep today's "Configure overrides" wording.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  Bound height to calc(100vh - 200px) so inner pages scroll internally
  instead of overflowing Backstage's page-level scroll. Esc closes via
  the same path as the back arrow with a visible kbd chip under the icon.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  - Order section caption above action button in setup card (Release and
    Component sections) to match Deploy section rhythm
  - Add caption under Create release explaining what it does
  - Rename Deploy section header from "Deploy to {env}" to "Deploy" with
    a descriptive subtitle
  - Disable Deploy button when the selected release is already current
    in the target env, with explanatory tooltip
  - Wrap selected-release summary in a tinted panel so name, meta, and
    Change button read as one group; stack name+Change on top line and
    meta chips below so the layout no longer breaks for multi-env releases

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  - Add "Start" badge to the setup card to mark it as the pipeline entry
  - Shrink setup node dimensions to 180×96 (env tiles stay 240×140) so it
    reads as a smaller configuration node rather than another env

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  Scrolling didn't work for tall diffs because overflow was set on the
  outer wrapper, not on .cm-mergeView itself. Per CodeMirror's docs the
  .cm-mergeView is the intended scroller — applying height + overflow
  auto there makes both panes scroll together as one unit, keeping
  left/right aligned line-by-line.

  Also flip the diff orientation: LHS now shows the target env's current
  release (before) and RHS shows the incoming upstream release (after),
  matching the conventional before-on-left convention.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  extractImage() read release.spec.workload.spec.container.image, but the
  API returns the image at release.spec.workload.container.image (no inner
  .spec wrapper). The "img: ..." line never appeared in rows and search by
  image silently matched nothing.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  - Auto-deploy tooltip now matches the confirmation dialog wording
  - Both reference "lowest environment" instead of "default environment"
  - Rename "View diff" to "View release diff" on the overrides page and
    env detail drift banner for clarity

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
  Adds a View/Compare toggle to the right pane. In Compare mode the user
  picks a reference release from a grouped Autocomplete (current-in-env
  bindings first, then any other release) and the right pane renders a
  side-by-side YamlDiffViewer of that reference vs the highlighted
  release. When opened with an environmentName, pre-fills the comparison
  target with that env's current release so the common "is this release
  different from what's deployed?" question resolves with zero clicks.

  Manifests are fetched on demand and cached, so toggling and switching
  targets are free. Existing view-mode behavior, search, and selection
  flow are unchanged.

Signed-off-by: Kavith Lokuhewage <kaviththiranga@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

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
`@plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.tsx`:
- Around line 303-307: The caption in EnvironmentDetailPanel currently shows
only aheadUpstreams[0] which misrepresents drift when multiple upstreams exist;
update the Typography inside the driftLabel (where driftInfo.aheadUpstreams is
used) to render a neutral or pluralized summary — e.g., display "Behind
upstream" when one upstream, "Behind 2 upstreams" (using aheadUpstreams.length)
when many, or join and display multiple names (e.g.,
aheadUpstreams.map(...).join(", ")) so the visible label accurately reflects
driftInfo.aheadUpstreams rather than always using aheadUpstreams[0].

In
`@plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx`:
- Around line 77-94: The interactive latest-release row (Box with onClick that
calls setBrowserOpen) needs proper keyboard and focus semantics: replace the
clickable div-like Box with a focusable interactive element (e.g., MUI
ButtonBase or an actual <button>/<a>) or add role="button", tabIndex={0}, and an
onKeyDown handler to call setBrowserOpen on Enter/Space. Update the element that
renders {latest.metadata?.name} and ChevronRightIcon so it is focusable and
announces itself; ensure the click handler remains wired to setBrowserOpen and
keep the conditional deployment caption (uses deployments,
latest.metadata?.name, firstEnvironmentName) unchanged.
🪄 Autofix (Beta)

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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3cc0654d-8638-4ee2-b2f8-daff7c5beed2

📥 Commits

Reviewing files that changed from the base of the PR and between 879722a and c3fabfc.

📒 Files selected for processing (8)
  • plugins/openchoreo/src/components/Environments/PipelineDAG/DeployFlowCanvas.tsx
  • plugins/openchoreo/src/components/Environments/PipelineDAG/PipelineCanvas.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.test.tsx
  • plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.tsx
  • plugins/openchoreo/src/components/Environments/components/MiniEnvironmentNode.test.tsx
  • plugins/openchoreo/src/components/Environments/components/MiniEnvironmentNode.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx
  • plugins/openchoreo/src/components/Environments/styles.ts
💤 Files with no reviewable changes (4)
  • plugins/openchoreo/src/components/Environments/PipelineDAG/PipelineCanvas.tsx
  • plugins/openchoreo/src/components/Environments/components/MiniEnvironmentNode.tsx
  • plugins/openchoreo/src/components/Environments/PipelineDAG/DeployFlowCanvas.tsx
  • plugins/openchoreo/src/components/Environments/components/MiniEnvironmentNode.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.test.tsx

Comment on lines +303 to +307
<Box className={classes.driftLabel}>
<ReportProblemOutlinedIcon fontSize="small" />
<Typography variant="caption">Behind upstream</Typography>
<InfoOutlinedIcon fontSize="small" />
<Typography variant="caption">
Behind {driftInfo.aheadUpstreams[0]?.envName}
</Typography>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Don't summarize drift with only the first upstream.

The tooltip already treats driftInfo.aheadUpstreams as a list, but this caption only names aheadUpstreams[0]. When multiple upstreams are ahead, the visible summary becomes misleading. A neutral label or a pluralized summary would avoid reporting the wrong source of drift.

🤖 Prompt for 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.

In
`@plugins/openchoreo/src/components/Environments/components/EnvironmentDetailPanel.tsx`
around lines 303 - 307, The caption in EnvironmentDetailPanel currently shows
only aheadUpstreams[0] which misrepresents drift when multiple upstreams exist;
update the Typography inside the driftLabel (where driftInfo.aheadUpstreams is
used) to render a neutral or pluralized summary — e.g., display "Behind
upstream" when one upstream, "Behind 2 upstreams" (using aheadUpstreams.length)
when many, or join and display multiple names (e.g.,
aheadUpstreams.map(...).join(", ")) so the visible label accurately reflects
driftInfo.aheadUpstreams rather than always using aheadUpstreams[0].

Comment on lines +77 to +94
<Box
onClick={() => setBrowserOpen(true)}
display="flex"
alignItems="center"
style={{ cursor: 'pointer', gap: 8 }}
>
<Typography variant="body2" style={{ fontWeight: 500 }}>
{latest.metadata?.name}
</Typography>
{(deployments[latest.metadata?.name ?? ''] ?? []).includes(
firstEnvironmentName,
) && (
<Typography variant="caption" color="primary">
current in {firstEnvironmentName}
</Typography>
)}
<ChevronRightIcon fontSize="small" color="action" />
</Box>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Give the latest-release row real button semantics.

This row is interactive, but it renders as a plain div with onClick, so keyboard users can't focus it or open the read-only browser. Please make it a real button/link or add the missing focus and keyboard handling.

🤖 Prompt for 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.

In
`@plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx`
around lines 77 - 94, The interactive latest-release row (Box with onClick that
calls setBrowserOpen) needs proper keyboard and focus semantics: replace the
clickable div-like Box with a focusable interactive element (e.g., MUI
ButtonBase or an actual <button>/<a>) or add role="button", tabIndex={0}, and an
onKeyDown handler to call setBrowserOpen on Enter/Space. Update the element that
renders {latest.metadata?.name} and ChevronRightIcon so it is focusable and
announces itself; ensure the click handler remains wired to setBrowserOpen and
keep the conditional deployment caption (uses deployments,
latest.metadata?.name, firstEnvironmentName) unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant