Skip to content

feat: block component deploy when the project is not deployed#677

Merged
VajiraPrabuddhaka merged 2 commits into
openchoreo:mainfrom
VajiraPrabuddhaka:feat/component-deploy-project-prereq
Jul 10, 2026
Merged

feat: block component deploy when the project is not deployed#677
VajiraPrabuddhaka merged 2 commits into
openchoreo:mainfrom
VajiraPrabuddhaka:feat/component-deploy-project-prereq

Conversation

@VajiraPrabuddhaka

@VajiraPrabuddhaka VajiraPrabuddhaka commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Purpose

Since project creation has an Auto Deploy option, a project can exist without being deployed to any environment. Deploying a component into such an environment used to fail asynchronously with a raw error (namespaces "dp-..." not found) that didn't tell the user the cause or the fix. This blocks the action up front and guides the user to deploy the project first.

Approach

  • Backend: the component environments response carries projectDeploymentStatus per env (ready / pending / not-deployed), derived from the project's ProjectReleaseBinding NamespaceReady condition. Fetched fail-open so a transient error never blocks a deploy.
  • Set up card: Deploy is disabled with a reason and a callout when the project isn't deployed to the first env; pending shows an info line instead of blocking.
  • Promote: disabled for a target env whose project isn't deployed there, with the same callout.
  • Failed bindings: a namespace-not-found failure is attributed to the missing project deployment — the panel and error dialog explain it and offer the fix.
  • The callout deep-links to the project's Deploy tab in a new tab (?env=&intent=deploy), which pre-selects that env and shows a hint; returning to the component tab refetches and unblocks.

Related Issues

Quick Demo

Without auto-deploy for component

Screen.Recording.2026-07-10.at.10.44.36.mov

With auto-deploy enabled for component

Screen.Recording.2026-07-10.at.10.50.29.mov

Checklist

  • Tests added or updated (unit, integration, etc.)
  • Samples updated (if applicable)

Remarks

Ships after the Auto Deploy option (#668). The controller reporting a first-class ProjectNotDeployed reason is a follow-up; the UI works today on a heuristic.

Summary by CodeRabbit

  • New Features
    • Added per-environment “project deployment status” (ready, pending, not deployed) and fail-open behavior when status can’t be determined.
    • Enhanced environments UX with deploy deep-link “arrival” hinting and dismissible guidance.
    • Introduced “Project not deployed” callouts plus deploy remediation links, including promotion-target blocking with clear disabled reasons.
  • Bug Fixes
    • Refresh environments/deployments automatically when the tab/window becomes visible again (focus/visibility events).
    • Improved messaging/tooltips for disabled deployment and promotion actions to explain the “why.”

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@VajiraPrabuddhaka, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 20 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 918a1ae7-f6e2-4d3d-b4a2-ba5d073cc104

📥 Commits

Reviewing files that changed from the base of the PR and between dd671d6 and db3792c.

📒 Files selected for processing (27)
  • .changeset/component-deploy-project-prereq.md
  • plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.test.ts
  • plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts
  • plugins/openchoreo-backend/src/services/transformers/project-release-binding.test.ts
  • plugins/openchoreo-backend/src/services/transformers/project-release-binding.ts
  • plugins/openchoreo-backend/src/types.ts
  • plugins/openchoreo/src/components/Environments/Environments.tsx
  • plugins/openchoreo/src/components/Environments/PipelineDAG/DeployFlowCanvas.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentErrorDetailsDialog.test.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentErrorDetailsDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentFailureBanner.test.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentFailureBanner.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.tsx
  • plugins/openchoreo/src/components/Environments/components/ProjectNotDeployedCallout.test.tsx
  • plugins/openchoreo/src/components/Environments/components/ProjectNotDeployedCallout.tsx
  • plugins/openchoreo/src/components/Environments/components/PromotePrimaryAction.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx
  • plugins/openchoreo/src/components/Environments/hooks/useEnvironmentData.ts
  • plugins/openchoreo/src/components/Environments/hooks/usePromotionAction.test.ts
  • plugins/openchoreo/src/components/Environments/hooks/usePromotionAction.ts
  • plugins/openchoreo/src/components/Environments/utils/projectDeployment.test.ts
  • plugins/openchoreo/src/components/Environments/utils/projectDeployment.ts
  • plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.test.tsx
  • plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.tsx
📝 Walkthrough

Walkthrough

Adds derived projectDeploymentStatus from project release binding readiness, propagates it through environment and promotion flows, surfaces project-not-deployed remediation UI, and adds deep-link arrival handling plus refetch-on-focus behavior.

Changes

Project Deployment Status Feature

Layer / File(s) Summary
Backend status derivation and environment enrichment
plugins/openchoreo-backend/src/services/transformers/..., plugins/openchoreo-backend/src/services/EnvironmentService/..., plugins/openchoreo-backend/src/types.ts
Derives project status from NamespaceReady, fetches project bindings, and exposes per-environment status with fail-open handling.
Frontend status utilities
plugins/openchoreo/src/components/Environments/utils/..., .../hooks/useEnvironmentData.ts
Adds blocking, pending, target-resolution, and failure-attribution helpers.
Promotion target blocking
plugins/openchoreo/src/components/Environments/hooks/..., .../PromotePrimaryAction.tsx, .../MiniEnvironmentNode.tsx, .../PipelineDAG/..., .../EnvironmentDetailPanel.tsx
Disables promotion targets whose projects are not deployed and surfaces blocked reasons.
Project-not-deployed remediation UI
plugins/openchoreo/src/components/Environments/components/ProjectNotDeployedCallout.tsx, .../DeploymentErrorDetailsDialog.tsx, .../DeploymentFailureBanner.tsx
Adds variant-specific remediation callouts and deploy deep links for setup, promotion, and failure flows.
Setup deployment gating
plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx
Disables deployment for blocked projects and displays blocked or pending status guidance.
Deep-link arrival and refresh behavior
plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.tsx, plugins/openchoreo/src/components/Environments/Environments.tsx
Preselects environments from query parameters, shows an arrival hint, and refetches on focus or visibility changes.
Changeset entry
.changeset/component-deploy-project-prereq.md
Records minor package bumps and the project-before-component deployment message.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EnvironmentInfoService
  participant ProjectReleaseBindingAPI
  participant deriveProjectDeploymentStatus
  participant Environment
  EnvironmentInfoService->>ProjectReleaseBindingAPI: fetch project release bindings
  ProjectReleaseBindingAPI-->>EnvironmentInfoService: bindings or fail-open null
  EnvironmentInfoService->>deriveProjectDeploymentStatus: derive status per environment
  deriveProjectDeploymentStatus-->>EnvironmentInfoService: ready, pending, or not-deployed
  EnvironmentInfoService->>Environment: populate projectDeploymentStatus
Loading
sequenceDiagram
  participant User
  participant ProjectEnvironmentsList
  participant EnvironmentDetailPanel
  participant usePromotionAction
  participant ProjectNotDeployedCallout
  User->>ProjectEnvironmentsList: open deploy deep link
  ProjectEnvironmentsList->>ProjectEnvironmentsList: select environment and show arrival hint
  User->>EnvironmentDetailPanel: request promotion
  EnvironmentDetailPanel->>usePromotionAction: resolve target project status
  usePromotionAction-->>EnvironmentDetailPanel: disabled target and blockedReason
  EnvironmentDetailPanel->>ProjectNotDeployedCallout: render deploy-project remediation
Loading

Possibly related PRs

Suggested reviewers: sameerajayasoma, stefinie123, Mirage20, kaviththiranga, LakshanSS

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description covers purpose and approach, but omits many required template sections like Goals, Release note, Documentation, and test environment. Add the missing template sections: Goals, User stories, Release note, Documentation, Training, Certification, Automation tests, Security checks, and Test environment.
✅ Passed checks (3 passed)
Check name Status Explanation
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.
Title check ✅ Passed The title clearly summarizes the main change: blocking component deploys when the project is not deployed.
✨ 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.

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

@VajiraPrabuddhaka VajiraPrabuddhaka marked this pull request as ready for review July 9, 2026 08:33

@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: 1

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

94-108: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value

Potential double refetch when returning to the tab.

Both window.focus and document.visibilitychange fire when switching back to the browser tab. Since onVisible calls refetch() for both events, the function executes twice in quick succession. Additionally, window.focus fires when regaining focus from another application window (not just tab switches), which may trigger unnecessary refetches.

Consider either dropping the focus listener (since visibilitychange already covers tab returns) or guarding with a short debounce/dedup to avoid redundant network calls.

♻️ Optional: rely on visibilitychange only
   useEffect(() => {
     const onVisible = () => {
       if (document.visibilityState === 'visible') refetch();
     };
-    window.addEventListener('focus', onVisible);
     document.addEventListener('visibilitychange', onVisible);
     return () => {
-      window.removeEventListener('focus', onVisible);
       document.removeEventListener('visibilitychange', onVisible);
     };
   }, [refetch]);

If focus is needed for cases where the tab is visible but the window loses focus to another app, a simple dedup guard works:

   useEffect(() => {
+    let lastFetch = 0;
     const onVisible = () => {
-      if (document.visibilityState === 'visible') refetch();
+      if (document.visibilityState === 'visible') {
+        const now = Date.now();
+        if (now - lastFetch > 2000) {
+          lastFetch = now;
+          refetch();
+        }
+      }
     };
     window.addEventListener('focus', onVisible);
     document.addEventListener('visibilitychange', onVisible);
     return () => {
       window.removeEventListener('focus', onVisible);
       document.removeEventListener('visibilitychange', onVisible);
     };
   }, [refetch]);
🤖 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/Environments.tsx` around lines
94 - 108, The refetch logic in Environments.tsx can fire twice because both the
focus listener and visibilitychange listener call onVisible, so update the
effect to avoid redundant refetch calls. Prefer keeping only
document.visibilitychange for tab վերադարձ handling, or add a short
dedup/debounce guard inside onVisible so refetch runs once per return; use the
existing useEffect, onVisible, and refetch symbols to locate the change.
plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.test.tsx (1)

137-168: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider adding a test for hint dismissal.

The tests cover preselection and hint visibility well, but the onClose dismiss behavior (clicking the alert's close button hides it permanently) is untested. A simple test rendering with intent=deploy, asserting the hint, clicking close, and asserting it disappears would guard against regressions.

🤖 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/ProjectEnvironments/ProjectEnvironmentsList.test.tsx`
around lines 137 - 168, Add a test in ProjectEnvironmentsList.test.tsx to cover
the hint dismissal flow for the arrival alert. Use ProjectEnvironmentsList with
mockSearchParams including env and intent=deploy, assert the “return to your
component tab to continue” hint is shown, click the alert’s close control, and
verify the hint disappears and stays hidden. Reuse the existing deep-link setup
in the ProjectEnvironmentsList / alert rendering path so the new test validates
the onClose behavior.
plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts (1)

273-332: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Serial project-bindings fetch adds latency to every environment-info request.

fetchProjectBindingsForStatus only needs namespaceName/projectName, both known upfront, yet it's awaited after the Promise.all([environmentsPromise, bindingsPromise, pipelinePromise]) batch instead of inside it. This adds one full network round-trip to every fetchDeploymentInfo call (a hot path rendering the environments/component page), even though the fetch is fail-open and independent of the other three.

Folding it into the existing Promise.all would remove that added latency in the common case. Trade-off: it would also fire this request in the rare case where deploymentPipeline turns out to be missing (currently skipped via the early PipelineUnavailableError throw) — likely an acceptable cost for the latency win. Note existing tests mock GETs in strict sequential order, so parallelizing would require adjusting EnvironmentInfoService.test.ts's mock queue order/expectations.

♻️ Illustrative refactor sketch
+      const projectBindingsPromise = this.fetchProjectBindingsForStatus(
+        client,
+        request.namespaceName,
+        request.projectName,
+      );
+
       const fetchStart = Date.now();
-      const [environmentsResult, bindingsResult, pipelineResult] =
-        await Promise.all([
-          environmentsPromise,
-          bindingsPromise,
-          pipelinePromise,
-        ]);
+      const [
+        environmentsResult,
+        bindingsResult,
+        pipelineResult,
+        projectBindings,
+      ] = await Promise.all([
+        environmentsPromise,
+        bindingsPromise,
+        pipelinePromise,
+        projectBindingsPromise,
+      ]);

Then drop the later standalone await this.fetchProjectBindingsForStatus(...) call and pass projectBindings straight through.

🤖 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-backend/src/services/EnvironmentService/EnvironmentInfoService.ts`
around lines 273 - 332, The `fetchDeploymentInfo` flow in
`EnvironmentInfoService` is doing `fetchProjectBindingsForStatus` as a separate
await after the main `Promise.all`, which adds an unnecessary round-trip on the
hot path. Move `fetchProjectBindingsForStatus(client, request.namespaceName,
request.projectName)` into the existing parallel batch alongside the other
promises, then use the returned `projectBindings` directly in
`transformEnvironmentDataWithBindings`. Update `EnvironmentInfoService.test.ts`
mocks/expectations to match the new parallel request order.
🤖 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/utils/projectDeployment.ts`:
- Around line 62-71: Update the explanatory comment in
attributeToProjectNotDeployed to match the actual fail-open behavior: it should
state that a ResourceApplyFailed plus namespace-not-found match is sufficient
even when env.projectDeploymentStatus is absent, not only when the project is
explicitly known to be not deployed or pending. Keep the implementation
unchanged and adjust the wording near the attributeToProjectNotDeployed logic so
future readers understand that undefined status is intentionally treated as
eligible for attribution.

---

Nitpick comments:
In
`@plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts`:
- Around line 273-332: The `fetchDeploymentInfo` flow in
`EnvironmentInfoService` is doing `fetchProjectBindingsForStatus` as a separate
await after the main `Promise.all`, which adds an unnecessary round-trip on the
hot path. Move `fetchProjectBindingsForStatus(client, request.namespaceName,
request.projectName)` into the existing parallel batch alongside the other
promises, then use the returned `projectBindings` directly in
`transformEnvironmentDataWithBindings`. Update `EnvironmentInfoService.test.ts`
mocks/expectations to match the new parallel request order.

In `@plugins/openchoreo/src/components/Environments/Environments.tsx`:
- Around line 94-108: The refetch logic in Environments.tsx can fire twice
because both the focus listener and visibilitychange listener call onVisible, so
update the effect to avoid redundant refetch calls. Prefer keeping only
document.visibilitychange for tab վերադարձ handling, or add a short
dedup/debounce guard inside onVisible so refetch runs once per return; use the
existing useEffect, onVisible, and refetch symbols to locate the change.

In
`@plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.test.tsx`:
- Around line 137-168: Add a test in ProjectEnvironmentsList.test.tsx to cover
the hint dismissal flow for the arrival alert. Use ProjectEnvironmentsList with
mockSearchParams including env and intent=deploy, assert the “return to your
component tab to continue” hint is shown, click the alert’s close control, and
verify the hint disappears and stays hidden. Reuse the existing deep-link setup
in the ProjectEnvironmentsList / alert rendering path so the new test validates
the onClose behavior.
🪄 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: 63964b20-88bb-41cf-8ff9-2ae4d3f95f21

📥 Commits

Reviewing files that changed from the base of the PR and between 14f1052 and 75251c3.

📒 Files selected for processing (27)
  • .changeset/component-deploy-project-prereq.md
  • plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.test.ts
  • plugins/openchoreo-backend/src/services/EnvironmentService/EnvironmentInfoService.ts
  • plugins/openchoreo-backend/src/services/transformers/project-release-binding.test.ts
  • plugins/openchoreo-backend/src/services/transformers/project-release-binding.ts
  • plugins/openchoreo-backend/src/types.ts
  • plugins/openchoreo/src/components/Environments/Environments.tsx
  • plugins/openchoreo/src/components/Environments/PipelineDAG/DeployFlowCanvas.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentErrorDetailsDialog.test.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentErrorDetailsDialog.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentFailureBanner.test.tsx
  • plugins/openchoreo/src/components/Environments/components/DeploymentFailureBanner.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.tsx
  • plugins/openchoreo/src/components/Environments/components/ProjectNotDeployedCallout.test.tsx
  • plugins/openchoreo/src/components/Environments/components/ProjectNotDeployedCallout.tsx
  • plugins/openchoreo/src/components/Environments/components/PromotePrimaryAction.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.test.tsx
  • plugins/openchoreo/src/components/Environments/components/SetupDetailPane.tsx
  • plugins/openchoreo/src/components/Environments/hooks/useEnvironmentData.ts
  • plugins/openchoreo/src/components/Environments/hooks/usePromotionAction.test.ts
  • plugins/openchoreo/src/components/Environments/hooks/usePromotionAction.ts
  • plugins/openchoreo/src/components/Environments/utils/projectDeployment.test.ts
  • plugins/openchoreo/src/components/Environments/utils/projectDeployment.ts
  • plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.test.tsx
  • plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.tsx

@VajiraPrabuddhaka VajiraPrabuddhaka force-pushed the feat/component-deploy-project-prereq branch 2 times, most recently from 9de70c4 to dd671d6 Compare July 10, 2026 05:12
Signed-off-by: VajiraPrabuddhaka <vajiraprabuddhaka@gmail.com>
@VajiraPrabuddhaka VajiraPrabuddhaka force-pushed the feat/component-deploy-project-prereq branch from dd671d6 to fe1119a Compare July 10, 2026 05:43
Signed-off-by: VajiraPrabuddhaka <vajiraprabuddhaka@gmail.com>
@VajiraPrabuddhaka VajiraPrabuddhaka force-pushed the feat/component-deploy-project-prereq branch from fe1119a to db3792c Compare July 10, 2026 05:51

@LakshanSS LakshanSS left a comment

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.

LGTM

@VajiraPrabuddhaka VajiraPrabuddhaka merged commit f126bca into openchoreo:main Jul 10, 2026
8 checks passed
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.

3 participants