Skip to content

feat: add emptyState pages and cause-specific messaging when a project has no environments#678

Merged
akila-i merged 3 commits into
openchoreo:mainfrom
akila-i:improve-observability-env-messages
Jul 10, 2026
Merged

feat: add emptyState pages and cause-specific messaging when a project has no environments#678
akila-i merged 3 commits into
openchoreo:mainfrom
akila-i:improve-observability-env-messages

Conversation

@akila-i

@akila-i akila-i commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Purpose

Related: openchoreo/openchoreo#4073

This pull request introduces improved empty and error state handling for the Deploy and Observability tabs by standardizing on Backstage's EmptyState component and providing more specific, actionable messaging. The changes affect both frontend and backend, ensuring consistent user experience and better error reporting across the app.

User Experience Improvements:

  • The Deploy tab and all Observability pages now use the standard Backstage EmptyState for empty and error states, replacing custom cards and alerts for a more unified look and feel. [1] [2]
  • Observability pages (Logs, Events, Alerts, Metrics, Traces, Incidents, Cost Analysis, RCA) now display cause-specific messages when environments are missing, forbidden, or unavailable, using a new discriminated status from useProjectEnvironments and a shared EnvironmentsStatusNotice component. [1] [2] [3] [4]

Backend and Error Handling:

  • The backend now returns a clean 404 (NotFoundError) when a project is missing a deployment pipeline reference, instead of a generic 500 error. [1] [2]
  • Tests have been updated to expect the new error handling and status codes, ensuring correct behavior and messaging in all edge cases. [1] [2] [3]

Code and API Changes:

  • The useProjectEnvironments hook now returns a discriminated status (ok, empty-pipeline, forbidden, unavailable), which is used throughout the Observability UI to determine which empty/error state to display. [1] [2] [3] [4]
  • Legacy alert and error UI code has been removed in favor of the new standardized approach, simplifying page components and improving maintainability. [1] [2] [3]

These changes ensure users receive clear, actionable feedback when environments are missing or misconfigured, and that the UI is consistent across all relevant parts of the application.

Goals

Describe the solutions that this feature/fix will introduce to resolve the problems described above

Approach

Screenshots:
Deploy page -
image

Few Observability Pages (similar behaviour in logs/metrics/traces/alerts/incidents/RCA reports/cost analysis reports/wirelogs) -
image

image

User stories

Summary of user stories addressed by this change>

Release note

Brief description of the new feature or bug fix as it will appear in the release notes

Documentation

Link(s) to product documentation that addresses the changes of this PR. If no doc impact, enter “N/A” plus brief explanation of why there’s no doc impact

Training

Link to the PR for changes to the training content in https://github.com/wso2/WSO2-Training, if applicable

Certification

Type “Sent” when you have provided new/updated certification questions, plus four answers for each question (correct answer highlighted in bold), based on this change. Certification questions/answers should be sent to certification@wso2.com and NOT pasted in this PR. If there is no impact on certification exams, type “N/A” and explain why.

Marketing

Link to drafts of marketing content that will describe and promote this feature, including product page changes, technical articles, blog posts, videos, etc., if applicable

Automation tests

  • Unit tests

    Code coverage information

  • Integration tests

    Details about the test cases and coverage

Security checks

Samples

Provide high-level details about the samples related to this feature

Related PRs

List any other related PRs

Migrations (if applicable)

Describe migration steps and platforms on which migration has been tested

Test environment

List all JDK versions, operating systems, databases, and browser/versions on which this feature/fix was tested

Learning

Describe the research phase and any blog posts, patterns, libraries, or add-ons you used to solve the problem.

Summary by CodeRabbit

  • New Features

    • Added clearer environment status notices across observability views, including messages for unavailable, forbidden, and empty pipeline states.
    • Added a linked “no environments” empty state that can point to deployment pipeline configuration when available.
  • Bug Fixes

    • Missing deployment pipeline references now return a clean not-found result instead of a generic server error.
    • Improved loading and empty-state handling for logs, metrics, traces, incidents, alerts, wirelogs, cost analysis, and RCA pages.

akila-i added 3 commits July 9, 2026 17:11
- Introduced EnvironmentsStatusNotice component to provide specific feedback on environment loading states.
- Updated useProjectEnvironments hook to return a status indicating the reason for empty environments (ok, empty-pipeline, forbidden, unavailable).
- Refactored multiple observability components (CostAnalysis, Incidents, Metrics, RCA, RuntimeEvents, RuntimeLogs, Traces, Wirelogs) to utilize the new status handling and display appropriate messages.
- Improved test cases to validate the new status responses and ensure correct rendering of notices based on environment states.

Signed-off-by: Akila-I <akila.99g@gmail.com>
…notices

Signed-off-by: Akila-I <akila.99g@gmail.com>
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Backend ProjectInfoService now throws NotFoundError for missing deployment pipeline references instead of a generic Error. useProjectEnvironments/useWirelogsEnvironments gain a discriminated status field and refetch. A new EnvironmentsStatusNotice component renders cause-specific empty/forbidden states, adopted across nine observability pages, replacing generic error/no-environments messaging. A new NoEnvironmentsEmptyState component resolves and links to a project's deployment pipeline, replacing prior Card/ErrorState UIs in PipelineCanvas, ProjectEnvironmentsList, and ResourceEnvironmentsList.

Changes

Backend and shared environment status contract

Layer / File(s) Summary
NotFoundError for missing pipeline ref
plugins/openchoreo-backend/src/services/ProjectService/ProjectInfoService.ts, ...ProjectInfoService.test.ts
Throws NotFoundError instead of a generic Error when deploymentPipelineRef.name is missing; test asserts structured error shape.
useProjectEnvironments status/refetch contract
plugins/openchoreo-react/src/hooks/useProjectEnvironments.ts, ...useProjectEnvironments.test.tsx, plugins/openchoreo-react/src/index.ts, .changeset/observability-env-error-messages.md
Adds ProjectEnvironmentsStatus (ok/empty-pipeline/forbidden/unavailable), a refetch callback, and reload-token-based state handling; re-exported and tested.
EnvironmentsStatusNotice shared component
plugins/openchoreo-observability/src/components/common/EnvironmentsStatusNotice.tsx, .../common/index.ts
New component renders ForbiddenState/EmptyState variants per status, exported from the common module.
useWirelogsEnvironments status passthrough
plugins/openchoreo-observability/src/hooks/useWirelogsEnvironments.ts
Extends result with status/refetch, deriving status from base hook plus enrichment errors.

Observability pages
plugins/openchoreo-observability/src/components/{Alerts,CostAnalysis,Incidents,Metrics,RCA,RuntimeEvents,RuntimeLogs,Traces,Wirelogs}/*

Layer / File(s) Summary
Status-driven rendering across nine pages Each page switches from environmentsError handling to environmentsStatus/environmentsLoading gating, rendering EnvironmentsStatusNotice (or Progress) instead of prior inline error/no-environments alerts; corresponding tests updated for unavailable/empty-pipeline/forbidden scenarios.

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

NoEnvironmentsEmptyState and Deploy/Environments UI

Layer / File(s) Summary
NoEnvironmentsEmptyState component and tests
plugins/openchoreo/src/components/Environments/components/NoEnvironmentsEmptyState.tsx, ...NoEnvironmentsEmptyState.test.tsx, .changeset/deploy-backstage-empty-state.md
New component resolves a project's deployment pipeline via entity annotations and renders a link to pipeline configuration, or admin-contact guidance on failure.
PipelineCanvas integration
plugins/openchoreo/src/components/Environments/PipelineDAG/PipelineCanvas.tsx, ...PipelineCanvas.test.tsx
Replaces the prior Card/retry empty state with EmptyState for load errors and NoEnvironmentsEmptyState for no environments.
ProjectEnvironmentsList integration
plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.tsx, ...ProjectEnvironmentsList.test.tsx
Replaces Card/ErrorState retry UI with EmptyState for errors and NoEnvironmentsEmptyState for empty results.
ResourceEnvironmentsList integration
plugins/openchoreo/src/components/ResourceEnvironments/ResourceEnvironmentsList.tsx, ...ResourceEnvironments.test.tsx
Replaces Card/ErrorState UI with EmptyState for errors and NoEnvironmentsEmptyState for no environments.

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

Possibly related PRs

Suggested reviewers: sameerajayasoma, stefinie123, Mirage20, kaviththiranga

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning Only Purpose and Approach are filled; most required template sections are missing or left as placeholders. Add concise content for Goals, User stories, Release note, Documentation, tests, security checks, and the other required sections.
✅ 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 matches the main change: standardized empty states and cause-specific messaging for projects without environments.
✨ 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.

@akila-i

akila-i commented Jul 9, 2026

Copy link
Copy Markdown
Contributor Author

@CodeRabbit review

@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@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

🧹 Nitpick comments (6)
plugins/openchoreo-observability/src/components/common/EnvironmentsStatusNotice.tsx (1)

24-63: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

LGTM! The status discrimination logic is clean and covers all four cases correctly.

One optional enhancement: the unavailable branch (lines 56–62) could wire a retry button. The hooks already expose refetch, and Backstage's EmptyState supports an action prop. This would let users retry without a full page refresh.

♻️ Optional: add retry action
 export interface EnvironmentsStatusNoticeProps {
   status: ProjectEnvironmentsStatus;
   feature?: string;
+  onRetry?: () => void;
 }

 export const EnvironmentsStatusNotice = ({
   status,
   feature,
+  onRetry,
 }: EnvironmentsStatusNoticeProps) => {
   // ...
   return (
     <EmptyState
       missing="data"
       title="Failed to load environments"
       description="Couldn't load this project's deployment pipeline. Review the deployment pipeline or contact your administrator."
+      action={onRetry && <Button onClick={onRetry} variant="contained" color="primary">Retry</Button>}
     />
   );
 };
🤖 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-observability/src/components/common/EnvironmentsStatusNotice.tsx`
around lines 24 - 63, The unavailable EmptyState in EnvironmentsStatusNotice
should expose a retry action so users can re-fetch without refreshing the page.
Update EnvironmentsStatusNoticeProps usage to pass through the existing refetch
handler from the surrounding hooks, and wire it into the final EmptyState via
its action prop with a clear retry label. Keep the current status branching
intact and only enhance the “unavailable” path.
plugins/openchoreo-react/src/hooks/useProjectEnvironments.ts (1)

75-87: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider resetting status at the start of each fetch cycle.

loading and error are reset at lines 65–66, but status retains its previous value during a refetch. All observed consumers check loading first, so the stale status is never visible — but resetting it here would make the state transition self-consistent and guard against future consumers that might read status before loading.

♻️ Optional refactor
    setLoading(true);
    setError(null);
+   setStatus('ok');
🤖 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-react/src/hooks/useProjectEnvironments.ts` around lines 75
- 87, In useProjectEnvironments, the fetch cycle clears loading and error but
leaves status stale, so reset status at the start of the same request flow
before the fetch result handling. Update the state initialization in the hook’s
fetch logic so each refetch begins from a neutral status, keeping status
transitions self-consistent alongside the existing loading/error resets.
plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.test.tsx (1)

32-37: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Dead EmptyState mock in @openchoreo/backstage-plugin-react.

The component now imports EmptyState from @backstage/core-components (line 4), but this mock still defines EmptyState under the @openchoreo/backstage-plugin-react mock. Since the import source changed, this mock is no longer exercised and should be removed to avoid confusion.

🤖 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 32 - 37, The EmptyState mock in the test setup is now dead because
ProjectEnvironmentsList imports EmptyState from `@backstage/core-components`, not
`@openchoreo/backstage-plugin-react`. Remove the unused EmptyState stub from the
mock setup for ProjectEnvironmentsList.test.tsx and keep the remaining mock
entries aligned with the actual imports used by ProjectEnvironmentsList.
plugins/openchoreo/src/components/Environments/components/NoEnvironmentsEmptyState.tsx (1)

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

!projectName guard is effectively dead code.

projectName falls back to entity.metadata.name (line 22-23), which is always present on a Backstage catalog entity. The !projectName branch can never execute. Only !namespaceName is a meaningful guard here. Not breaking, but worth simplifying to avoid implying projectName can be absent.

🤖 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/NoEnvironmentsEmptyState.tsx`
at line 26, The guard in NoEnvironmentsEmptyState is overchecking projectName
even though it is always populated from entity.metadata.name. Simplify the early
return in the component by removing the dead !projectName branch and keeping
only the meaningful namespaceName check, while preserving the existing behavior
of the empty state rendering logic.
plugins/openchoreo/src/components/Environments/components/NoEnvironmentsEmptyState.test.tsx (1)

28-96: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add test coverage for missing namespace annotation.

The early-return path when namespaceName is absent (line 26 of the component) isn't tested. This path skips the fetch entirely and renders the fallback guidance. Adding a test ensures this guard isn't accidentally removed:

Proposed test
+  it('renders fallback guidance when namespace annotation is missing', async () => {
+    const fetchDeploymentPipeline = jest.fn().mockResolvedValue({ name: 'p' });
+
+    await renderWith(
+      makeEntity({ [CHOREO_ANNOTATIONS.PROJECT]: 'my-project' }, 'my-project'),
+      fetchDeploymentPipeline,
+    );
+
+    expect(
+      await screen.findByText(/Contact your administrator to configure it/),
+    ).toBeInTheDocument();
+    expect(fetchDeploymentPipeline).not.toHaveBeenCalled();
+  });
🤖 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/NoEnvironmentsEmptyState.test.tsx`
around lines 28 - 96, The NoEnvironmentsEmptyState test suite is missing
coverage for the early-return path when the namespace annotation is absent, so
add a test in NoEnvironmentsEmptyState.test.tsx that renders via
renderWith/makeEntity without CHOREO_ANNOTATIONS.NAMESPACE and verifies the
fallback guidance is shown, no pipeline configuration link is rendered, and
fetchDeploymentPipeline is not called. Use the existing NoEnvironmentsEmptyState
and renderWith helpers to cover this guard path.
plugins/openchoreo-observability/src/components/Metrics/ObservabilityMetricsPage.test.tsx (1)

113-113: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add test coverage for non-ok environment statuses.

The Incidents test file added cases for both empty-pipeline and unavailable states, but the Metrics test only updated existing mocks with status: 'ok'. Adding equivalent tests would verify the EnvironmentsStatusNotice rendering path and guard against regressions.

Also applies to: 222-222

🤖 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-observability/src/components/Metrics/ObservabilityMetricsPage.test.tsx`
at line 113, Add test coverage in ObservabilityMetricsPage.test.tsx for non-ok
environment statuses by exercising the same EnvironmentsStatusNotice rendering
path used in the Incidents tests. Update or add cases in the
ObservabilityMetricsPage test suite to mock both empty-pipeline and unavailable
statuses instead of only status: ok, and verify the notice appears for each
state so regressions in the environment status handling are caught.
🤖 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/NoEnvironmentsEmptyState.tsx`:
- Around line 17-44: The NoEnvironmentsEmptyState component shows the fallback
message before fetchDeploymentPipeline finishes because pipelineUrl is initially
undefined. Add an explicit loading state alongside the existing useEffect async
fetch in NoEnvironmentsEmptyState so the fallback text is only rendered after
the request completes or fails, and keep the link hidden while loading. Update
the render logic that currently depends on pipelineUrl to gate the “Contact your
administrator…” text on !loading, using the existing entity, client, and
setPipelineUrl flow.

In
`@plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.tsx`:
- Around line 182-191: The error UI in ProjectEnvironmentsList, and the same
pattern in ResourceEnvironmentsList and PipelineCanvas, lost the retry
affordance when switching to EmptyState. Update the error branch that renders
EmptyState to include a retry action/button wired to the existing fetchEnvs({
showProgress: true }) flow (or the equivalent fetch/reload handler in each
component), so transient failures can be retried without a full page refresh.

---

Nitpick comments:
In
`@plugins/openchoreo-observability/src/components/common/EnvironmentsStatusNotice.tsx`:
- Around line 24-63: The unavailable EmptyState in EnvironmentsStatusNotice
should expose a retry action so users can re-fetch without refreshing the page.
Update EnvironmentsStatusNoticeProps usage to pass through the existing refetch
handler from the surrounding hooks, and wire it into the final EmptyState via
its action prop with a clear retry label. Keep the current status branching
intact and only enhance the “unavailable” path.

In
`@plugins/openchoreo-observability/src/components/Metrics/ObservabilityMetricsPage.test.tsx`:
- Line 113: Add test coverage in ObservabilityMetricsPage.test.tsx for non-ok
environment statuses by exercising the same EnvironmentsStatusNotice rendering
path used in the Incidents tests. Update or add cases in the
ObservabilityMetricsPage test suite to mock both empty-pipeline and unavailable
statuses instead of only status: ok, and verify the notice appears for each
state so regressions in the environment status handling are caught.

In `@plugins/openchoreo-react/src/hooks/useProjectEnvironments.ts`:
- Around line 75-87: In useProjectEnvironments, the fetch cycle clears loading
and error but leaves status stale, so reset status at the start of the same
request flow before the fetch result handling. Update the state initialization
in the hook’s fetch logic so each refetch begins from a neutral status, keeping
status transitions self-consistent alongside the existing loading/error resets.

In
`@plugins/openchoreo/src/components/Environments/components/NoEnvironmentsEmptyState.test.tsx`:
- Around line 28-96: The NoEnvironmentsEmptyState test suite is missing coverage
for the early-return path when the namespace annotation is absent, so add a test
in NoEnvironmentsEmptyState.test.tsx that renders via renderWith/makeEntity
without CHOREO_ANNOTATIONS.NAMESPACE and verifies the fallback guidance is
shown, no pipeline configuration link is rendered, and fetchDeploymentPipeline
is not called. Use the existing NoEnvironmentsEmptyState and renderWith helpers
to cover this guard path.

In
`@plugins/openchoreo/src/components/Environments/components/NoEnvironmentsEmptyState.tsx`:
- Line 26: The guard in NoEnvironmentsEmptyState is overchecking projectName
even though it is always populated from entity.metadata.name. Simplify the early
return in the component by removing the dead !projectName branch and keeping
only the meaningful namespaceName check, while preserving the existing behavior
of the empty state rendering logic.

In
`@plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.test.tsx`:
- Around line 32-37: The EmptyState mock in the test setup is now dead because
ProjectEnvironmentsList imports EmptyState from `@backstage/core-components`, not
`@openchoreo/backstage-plugin-react`. Remove the unused EmptyState stub from the
mock setup for ProjectEnvironmentsList.test.tsx and keep the remaining mock
entries aligned with the actual imports used by ProjectEnvironmentsList.
🪄 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: 49600339-5556-4ff6-8150-cc412dc38daa

📥 Commits

Reviewing files that changed from the base of the PR and between 5222138 and 82e328c.

📒 Files selected for processing (38)
  • .changeset/deploy-backstage-empty-state.md
  • .changeset/observability-env-error-messages.md
  • plugins/openchoreo-backend/src/services/ProjectService/ProjectInfoService.test.ts
  • plugins/openchoreo-backend/src/services/ProjectService/ProjectInfoService.ts
  • plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Alerts/ObservabilityAlertsPage.tsx
  • plugins/openchoreo-observability/src/components/CostAnalysis/CostAnalysisPage.test.tsx
  • plugins/openchoreo-observability/src/components/CostAnalysis/CostAnalysisPage.tsx
  • plugins/openchoreo-observability/src/components/Incidents/ObservabilityProjectIncidentsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Incidents/ObservabilityProjectIncidentsPage.tsx
  • plugins/openchoreo-observability/src/components/Metrics/ObservabilityMetricsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Metrics/ObservabilityMetricsPage.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAPage.test.tsx
  • plugins/openchoreo-observability/src/components/RCA/RCAPage.tsx
  • plugins/openchoreo-observability/src/components/RuntimeEvents/ObservabilityRuntimeEventsPage.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeEvents/ObservabilityRuntimeEventsPage.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityProjectRuntimeLogsPage.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityRuntimeLogsPage.test.tsx
  • plugins/openchoreo-observability/src/components/RuntimeLogs/ObservabilityRuntimeLogsPage.tsx
  • plugins/openchoreo-observability/src/components/Traces/ObservabilityTracesPage.test.tsx
  • plugins/openchoreo-observability/src/components/Traces/ObservabilityTracesPage.tsx
  • plugins/openchoreo-observability/src/components/Wirelogs/ObservabilityWirelogsPage.test.tsx
  • plugins/openchoreo-observability/src/components/Wirelogs/ObservabilityWirelogsPage.tsx
  • plugins/openchoreo-observability/src/components/common/EnvironmentsStatusNotice.tsx
  • plugins/openchoreo-observability/src/components/common/index.ts
  • plugins/openchoreo-observability/src/hooks/useWirelogsEnvironments.ts
  • plugins/openchoreo-react/src/hooks/useProjectEnvironments.test.tsx
  • plugins/openchoreo-react/src/hooks/useProjectEnvironments.ts
  • plugins/openchoreo-react/src/index.ts
  • plugins/openchoreo/src/components/Environments/PipelineDAG/PipelineCanvas.test.tsx
  • plugins/openchoreo/src/components/Environments/PipelineDAG/PipelineCanvas.tsx
  • plugins/openchoreo/src/components/Environments/components/NoEnvironmentsEmptyState.test.tsx
  • plugins/openchoreo/src/components/Environments/components/NoEnvironmentsEmptyState.tsx
  • plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.test.tsx
  • plugins/openchoreo/src/components/ProjectEnvironments/ProjectEnvironmentsList.tsx
  • plugins/openchoreo/src/components/ResourceEnvironments/ResourceEnvironments.test.tsx
  • plugins/openchoreo/src/components/ResourceEnvironments/ResourceEnvironmentsList.tsx

Comment on lines +17 to +44
const [pipelineUrl, setPipelineUrl] = useState<string | undefined>();

useEffect(() => {
let cancelled = false;
const projectName =
entity.metadata.annotations?.[CHOREO_ANNOTATIONS.PROJECT] ??
entity.metadata.name;
const namespaceName =
entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE];
if (!projectName || !namespaceName) return undefined;

client
.fetchDeploymentPipeline(projectName, namespaceName)
.then((pipeline: { name?: string }) => {
if (cancelled || !pipeline?.name) return;
const catalogNamespace = entity.metadata.namespace || 'default';
setPipelineUrl(
`/catalog/${catalogNamespace}/deploymentpipeline/${pipeline.name}`,
);
})
.catch(() => {
// Leave the link out if the pipeline ref can't be resolved.
});

return () => {
cancelled = true;
};
}, [entity, client]);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Transient fallback text during pipeline fetch.

pipelineUrl starts as undefined, so the component renders "Contact your administrator to configure it." while the async fetch is in-flight. Once the pipeline resolves, the text switches to include the link. This flash of fallback content is misleading — users may read the admin-contact guidance and navigate away before the link appears.

Track a loading state and defer the fallback until the fetch completes:

Proposed fix
 export const NoEnvironmentsEmptyState = () => {
   const { entity } = useEntity();
   const client = useApi(openChoreoClientApiRef);
   const [pipelineUrl, setPipelineUrl] = useState<string | undefined>();
+  const [loading, setLoading] = useState(true);

   useEffect(() => {
     let cancelled = false;
     const projectName =
       entity.metadata.annotations?.[CHOREO_ANNOTATIONS.PROJECT] ??
       entity.metadata.name;
     const namespaceName =
       entity.metadata.annotations?.[CHOREO_ANNOTATIONS.NAMESPACE];
-    if (!projectName || !namespaceName) return undefined;
+    if (!projectName || !namespaceName) {
+      setLoading(false);
+      return undefined;
+    }

     client
       .fetchDeploymentPipeline(projectName, namespaceName)
       .then((pipeline: { name?: string }) => {
         if (cancelled || !pipeline?.name) return;
         const catalogNamespace = entity.metadata.namespace || 'default';
         setPipelineUrl(
           `/catalog/${catalogNamespace}/deploymentpipeline/${pipeline.name}`,
         );
       })
       .catch(() => {
         // Leave the link out if the pipeline ref can't be resolved.
       })
+      .finally(() => {
+        if (!cancelled) setLoading(false);
+      });

     return () => {
       cancelled = true;
     };
   }, [entity, client]);

Then gate the fallback on !loading:

         {pipelineUrl ? (
           <>
             Review the <Link to={pipelineUrl}>pipeline configuration</Link> or
             contact your administrator.
           </>
         ) : (
-          <>Contact your administrator to configure it.</>
+          !loading && <>Contact your administrator to configure it.</>
         )}
🤖 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/NoEnvironmentsEmptyState.tsx`
around lines 17 - 44, The NoEnvironmentsEmptyState component shows the fallback
message before fetchDeploymentPipeline finishes because pipelineUrl is initially
undefined. Add an explicit loading state alongside the existing useEffect async
fetch in NoEnvironmentsEmptyState so the fallback text is only rendered after
the request completes or fails, and keep the link hidden while loading. Update
the render logic that currently depends on pipelineUrl to gate the “Contact your
administrator…” text on !loading, using the existing entity, client, and
setPipelineUrl flow.

Comment on lines +182 to +191
<EmptyState
missing="data"
title="Failed to load environments"
description={getErrorMessage(error)}
/>
);
}

if (envs.length === 0) {
return (
<Card style={{ minHeight: '300px', width: '100%' }}>
<EmptyState
title="No environments available"
description="This project's deployment pipeline has no environments configured."
action={{
label: 'Retry',
onClick: () => fetchEnvs({ showProgress: true }),
}}
/>
</Card>
);
return <NoEnvironmentsEmptyState />;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Error state no longer offers a retry action.

The previous ErrorState included an onRetry that called fetchEnvs({ showProgress: true }). The new EmptyState from @backstage/core-components has no retry affordance, so users hitting a transient fetch failure must refresh the page to recover. Consider adding a retry button or action to the error EmptyState.

This same pattern applies to ResourceEnvironmentsList.tsx and PipelineCanvas.tsx.

🤖 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.tsx`
around lines 182 - 191, The error UI in ProjectEnvironmentsList, and the same
pattern in ResourceEnvironmentsList and PipelineCanvas, lost the retry
affordance when switching to EmptyState. Update the error branch that renders
EmptyState to include a retry action/button wired to the existing fetchEnvs({
showProgress: true }) flow (or the equivalent fetch/reload handler in each
component), so transient failures can be retried without a full page refresh.

@akila-i akila-i marked this pull request as ready for review July 9, 2026 12:25
@akila-i akila-i merged commit d5eff9e into openchoreo:main Jul 10, 2026
9 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.

2 participants