Skip to content

feat: show diff of current vs proposed rendered argo CR#1126

Merged
adityachoudhari26 merged 2 commits into
mainfrom
show-argo0cr-diff
May 13, 2026
Merged

feat: show diff of current vs proposed rendered argo CR#1126
adityachoudhari26 merged 2 commits into
mainfrom
show-argo0cr-diff

Conversation

@adityachoudhari26
Copy link
Copy Markdown
Member

@adityachoudhari26 adityachoudhari26 commented May 13, 2026

fixes #1075
fixes #1076

Summary by CodeRabbit

  • New Features

    • Enhanced plan detail page with improved navigation and plan version information.
    • Added section-aware diff viewing with dropdown selector for multi-section plans.
    • Introduced split/unified view toggle for plan diffs.
    • Improved ArgoCD Application manifest handling in plan comparisons.
    • Organized plan details with tabbed interface for Diff and Validations views.
  • Refactor

    • Restructured plan diff dialog and page components for better modularity and state management.

Review Change Stack

Copilot AI review requested due to automatic review settings May 13, 2026 17:57
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 13, 2026

Warning

Rate limit exceeded

@adityachoudhari26 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 37 minutes and 44 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6c4729f0-2173-48c6-a1e5-bb885f1d7d4d

📥 Commits

Reviewing files that changed from the base of the PR and between 8f1702f and 2ad165b.

📒 Files selected for processing (2)
  • apps/web/app/lib/plan-sections.ts
  • apps/web/app/routes/ws/deployments/_components/plans/PlanDiffDialog.tsx
📝 Walkthrough

Walkthrough

This PR adds end-to-end support for including Argo CD Application custom resources in deployment plan diffs. The backend fetches live Applications, normalizes them for clean diffs, and includes them as distinct YAML sections. The frontend parses plan content into sections, manages tab/section selection via URL state, and renders section-specific diffs in a Monaco editor.

Changes

Plan Results with Application CR and Section-aware Diffs

Layer / File(s) Summary
Argo Application Getter Interface & Implementation
apps/workspace-engine/pkg/jobagents/argo/argocd.go, apps/workspace-engine/pkg/jobagents/argo/application_upserter.go
ApplicationGetter interface defined; GoApplicationGetter implementation fetches live Argo CD Applications via the Argo CD API.
Plan Diff Enhancement with Application CR
apps/workspace-engine/pkg/jobagents/argo/argocd_plan.go
normalizeApplicationForDiff helper removes server-managed fields; ArgoCDPlanner accepts ApplicationGetter, fetches live Application, normalizes both proposed and current CRs, and prepends them to manifest YAML bundles for diff computation.
Backend Testing & Integration
apps/workspace-engine/pkg/jobagents/argo/argoapp_test.go, apps/workspace-engine/svc/controllers/deploymentplanresult/getters_postgres.go
mockApplicationGetter test double and planAppGetter helper added; plan tests extended to validate Application CR ordering, conditional inclusion based on live app existence, and error handling; registry wired with GoApplicationGetter.
Frontend Plan Section Parsing
apps/web/app/lib/plan-sections.ts
extractPlanSections parses YAML streams into "Application CR" and "Rendered Manifests" sections; unionSectionNames computes section names across multiple streams; fallback to single "Rendered Manifests" section on parse errors.
Plan Result URL State & Tab Management
apps/web/app/routes/ws/deployments/_hooks/usePlanResultParam.ts
PlanResultTab type added; hook now derives and manages tab ("diff" | "validations") from URL params; openResult, setTab, and closeResult helpers updated to synchronize both resultId and tab.
Plan Diff Dialog & UI Components
apps/web/app/routes/ws/deployments/_components/plans/PlanDiffDialog.tsx, apps/web/app/routes/ws/deployments/_components/plans/plan-diff/DiffEditorPane.tsx, apps/web/app/routes/ws/deployments/_components/plans/plan-diff/SectionSelector.tsx
PlanDiffDialog refactored from props-driven to route/hook-driven; computes section names from diff payload and uses SectionSelector to drive activeSection; DiffEditorPane renders Monaco diff editor with theme-aware colors and split/unified view toggle; SectionSelector dropdown conditionally renders only when multiple sections present.
Plan Detail Page Header & Integration
apps/web/app/routes/ws/deployments/_components/plans/PlanDetailPageHeader.tsx, apps/web/app/routes/ws/deployments/page.$deploymentId.plans.$planId.tsx
PlanDetailPageHeader new component renders breadcrumbs and plan version display; page component refactored to remove local header/tab state management and delegate to PlanDetailPageHeader and URL-driven PlanDiffDialog.

Sequence Diagram(s)

sequenceDiagram
  participant Plan as ArgoCDPlanner.Plan
  participant AppGetter as ApplicationGetter
  participant ManifestGetter as ManifestGetter
  participant Normalizer as normalizeApplicationForDiff
  Plan->>AppGetter: GetApplication(context, live app)
  Plan->>ManifestGetter: GetCurrentManifests()
  Plan->>ManifestGetter: GetProposedManifests()
  AppGetter-->>Plan: Application or nil
  ManifestGetter-->>Plan: current manifests
  ManifestGetter-->>Plan: proposed manifests
  Plan->>Normalizer: normalize proposed Application CR
  alt live Application exists
    Plan->>Normalizer: normalize current Application CR
  end
  Normalizer-->>Plan: normalized Application YAML(s)
  Plan->>Plan: prepend Application CR(s) to manifest YAML bundles
  Plan-->>Plan: return current & proposed with Application CRs included
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • jsbroks

Poem

🐰 With Application CRs now in sight,
Section-split diffs make changes bright,
Hook-driven dialogs, state in the URL—
Plans are diffing like never before, how full!
From Argo to frontend, a seamless delight. ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main feature: adding diff visualization for Argo CR (Application Custom Resource) between current and proposed states.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch show-argo0cr-diff

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 and usage tips.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds ArgoCD Application CR visibility to deployment plan diffs and refactors the plan diff UI to support section-based viewing of the Application CR versus rendered manifests.

Changes:

  • Adds ArgoCD Application fetching to the workspace-engine planner and includes normalized current/proposed Application CR YAML in plan diffs.
  • Adds tests for Application CR inclusion and ArgoCD application fetch error handling.
  • Refactors the web plan detail dialog/header and adds section selection for diff content.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
apps/workspace-engine/svc/controllers/deploymentplanresult/getters_postgres.go Registers the production Application getter with the ArgoCD planner.
apps/workspace-engine/pkg/jobagents/argo/argocd.go Defines the ApplicationGetter interface.
apps/workspace-engine/pkg/jobagents/argo/argocd_plan.go Fetches, normalizes, and includes Application CR YAML in plan diffs.
apps/workspace-engine/pkg/jobagents/argo/argoapp_test.go Updates planner tests and adds Application CR diff coverage.
apps/workspace-engine/pkg/jobagents/argo/application_upserter.go Implements production Application fetching through the ArgoCD API.
apps/web/app/routes/ws/deployments/page.$deploymentId.plans.$planId.tsx Refactors page header/dialog ownership and uses URL-backed result opening.
apps/web/app/routes/ws/deployments/_hooks/usePlanResultParam.ts Adds URL-backed tab state for plan result dialogs.
apps/web/app/routes/ws/deployments/_components/plans/PlanDiffDialog.tsx Refactors diff/validation dialog and adds section-aware diff rendering.
apps/web/app/routes/ws/deployments/_components/plans/PlanDetailPageHeader.tsx Extracts the plan detail breadcrumb/header.
apps/web/app/routes/ws/deployments/_components/plans/plan-diff/SectionSelector.tsx Adds the section dropdown for diff sections.
apps/web/app/routes/ws/deployments/_components/plans/plan-diff/DiffEditorPane.tsx Extracts the Monaco diff editor pane.
apps/web/app/lib/plan-sections.ts Adds YAML stream parsing and section extraction helpers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread apps/web/app/lib/plan-sections.ts Outdated
Comment on lines +33 to +34
const cr = docs.filter(isArgoApplication);
const manifests = docs.filter((d) => !isArgoApplication(d));
Comment on lines +39 to +41
const diffQuery = trpc.deployment.plans.resultDiff.useQuery(
{ deploymentId, resultId },
{ enabled: open },
{ deploymentId: deployment.id, resultId: resultId ?? "" },
{ enabled: resultId != null },
Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (4)
apps/web/app/routes/ws/deployments/_components/plans/plan-diff/DiffEditorPane.tsx (1)

5-13: ⚡ Quick win

Promote exported props shape to an interface.

For exported component APIs, define a named props interface instead of an inline object type.

Proposed change
+interface DiffEditorPaneProps {
+  current: string;
+  proposed: string;
+  view: "split" | "unified";
+}
+
 export function DiffEditorPane({
   current,
   proposed,
   view,
-}: {
-  current: string;
-  proposed: string;
-  view: "split" | "unified";
-}) {
+}: DiffEditorPaneProps) {

As per coding guidelines, **/*.{ts,tsx}: "Use TypeScript with explicit types; prefer interface for public APIs".

🤖 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
`@apps/web/app/routes/ws/deployments/_components/plans/plan-diff/DiffEditorPane.tsx`
around lines 5 - 13, Export a named props interface for the DiffEditorPane
component instead of the inline object type: create and export an interface
(e.g., DiffEditorPaneProps) that declares current: string; proposed: string;
view: "split" | "unified"; then update the DiffEditorPane declaration to accept
props: DiffEditorPaneProps (and keep existing destructuring of current,
proposed, view). Ensure the new interface is exported so the component's public
API uses an explicit, named type.
apps/web/app/lib/plan-sections.ts (1)

3-3: ⚡ Quick win

Use interface for exported PlanSection.

PlanSection is an exported object contract; use an interface to align with project API typing conventions.

Proposed change
-export type PlanSection = { name: string; content: string };
+export interface PlanSection {
+  name: string;
+  content: string;
+}

As per coding guidelines, **/*.{ts,tsx}: "Use TypeScript with explicit types; prefer interface for public APIs".

🤖 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 `@apps/web/app/lib/plan-sections.ts` at line 3, Replace the exported type alias
PlanSection with an exported interface to follow the project's public API typing
convention: change the declaration of PlanSection (currently "export type
PlanSection = { name: string; content: string }") to an exported interface named
PlanSection with the same properties (name: string; content: string) so callers
see the interface contract instead of a type alias.
apps/web/app/routes/ws/deployments/_components/plans/plan-diff/SectionSelector.tsx (1)

9-13: ⚡ Quick win

Use interface for exported SectionSelectorProps.

Switch this exported object contract from type to interface for API consistency.

Proposed change
-export type SectionSelectorProps = {
+export interface SectionSelectorProps {
   sections: string[];
   value: string | undefined;
   onChange: (value: string) => void;
-};
+}

As per coding guidelines, **/*.{ts,tsx}: "Use TypeScript with explicit types; prefer interface for public APIs".

🤖 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
`@apps/web/app/routes/ws/deployments/_components/plans/plan-diff/SectionSelector.tsx`
around lines 9 - 13, Replace the exported type alias with an exported interface:
change the declaration "export type SectionSelectorProps = { sections: string[];
value: string | undefined; onChange: (value: string) => void; }" to an
equivalent "export interface SectionSelectorProps { sections: string[]; value?:
string; onChange(value: string): void; }" (or keep value: string | undefined if
you prefer explicit undefined), updating the symbols SectionSelectorProps,
sections, value, and onChange accordingly to maintain the same shape and
exported API.
apps/web/app/routes/ws/deployments/_components/plans/PlanDiffDialog.tsx (1)

44-47: ⚡ Quick win

Avoid reparsing YAML streams on every render.

unionSectionNames(...) parses both streams, and DiffBody parses them again. Memoize extracted sections once per diffQuery.data and reuse for names + selected section lookup.

Also applies to: 143-148

🤖 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 `@apps/web/app/routes/ws/deployments/_components/plans/PlanDiffDialog.tsx`
around lines 44 - 47, Memoize parsing of the YAML streams so you don't reparse
on every render: use useMemo keyed on diffQuery.data (or its current/proposed
fields) to produce parsedSections for both current and proposed, then call
unionSectionNames(parsedSections.current, parsedSections.proposed) instead of
unionSectionNames(diffQuery.data?.current, ...), and pass the parsedSections
into DiffBody and any selected-section lookup logic (e.g. where you derive
selectedSection by name) so both the names list and the selected-section
resolution reuse the same parsed result rather than reparsing; update references
to unionSectionNames, DiffBody, and the selected section lookup to use the
memoized parsedSections.
🤖 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.

Nitpick comments:
In `@apps/web/app/lib/plan-sections.ts`:
- Line 3: Replace the exported type alias PlanSection with an exported interface
to follow the project's public API typing convention: change the declaration of
PlanSection (currently "export type PlanSection = { name: string; content:
string }") to an exported interface named PlanSection with the same properties
(name: string; content: string) so callers see the interface contract instead of
a type alias.

In
`@apps/web/app/routes/ws/deployments/_components/plans/plan-diff/DiffEditorPane.tsx`:
- Around line 5-13: Export a named props interface for the DiffEditorPane
component instead of the inline object type: create and export an interface
(e.g., DiffEditorPaneProps) that declares current: string; proposed: string;
view: "split" | "unified"; then update the DiffEditorPane declaration to accept
props: DiffEditorPaneProps (and keep existing destructuring of current,
proposed, view). Ensure the new interface is exported so the component's public
API uses an explicit, named type.

In
`@apps/web/app/routes/ws/deployments/_components/plans/plan-diff/SectionSelector.tsx`:
- Around line 9-13: Replace the exported type alias with an exported interface:
change the declaration "export type SectionSelectorProps = { sections: string[];
value: string | undefined; onChange: (value: string) => void; }" to an
equivalent "export interface SectionSelectorProps { sections: string[]; value?:
string; onChange(value: string): void; }" (or keep value: string | undefined if
you prefer explicit undefined), updating the symbols SectionSelectorProps,
sections, value, and onChange accordingly to maintain the same shape and
exported API.

In `@apps/web/app/routes/ws/deployments/_components/plans/PlanDiffDialog.tsx`:
- Around line 44-47: Memoize parsing of the YAML streams so you don't reparse on
every render: use useMemo keyed on diffQuery.data (or its current/proposed
fields) to produce parsedSections for both current and proposed, then call
unionSectionNames(parsedSections.current, parsedSections.proposed) instead of
unionSectionNames(diffQuery.data?.current, ...), and pass the parsedSections
into DiffBody and any selected-section lookup logic (e.g. where you derive
selectedSection by name) so both the names list and the selected-section
resolution reuse the same parsed result rather than reparsing; update references
to unionSectionNames, DiffBody, and the selected section lookup to use the
memoized parsedSections.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c3cfa9b5-80eb-4151-8638-fd66196eb6d1

📥 Commits

Reviewing files that changed from the base of the PR and between b358745 and 8f1702f.

📒 Files selected for processing (12)
  • apps/web/app/lib/plan-sections.ts
  • apps/web/app/routes/ws/deployments/_components/plans/PlanDetailPageHeader.tsx
  • apps/web/app/routes/ws/deployments/_components/plans/PlanDiffDialog.tsx
  • apps/web/app/routes/ws/deployments/_components/plans/plan-diff/DiffEditorPane.tsx
  • apps/web/app/routes/ws/deployments/_components/plans/plan-diff/SectionSelector.tsx
  • apps/web/app/routes/ws/deployments/_hooks/usePlanResultParam.ts
  • apps/web/app/routes/ws/deployments/page.$deploymentId.plans.$planId.tsx
  • apps/workspace-engine/pkg/jobagents/argo/application_upserter.go
  • apps/workspace-engine/pkg/jobagents/argo/argoapp_test.go
  • apps/workspace-engine/pkg/jobagents/argo/argocd.go
  • apps/workspace-engine/pkg/jobagents/argo/argocd_plan.go
  • apps/workspace-engine/svc/controllers/deploymentplanresult/getters_postgres.go

@adityachoudhari26 adityachoudhari26 merged commit d3d417a into main May 13, 2026
5 of 6 checks passed
@adityachoudhari26 adityachoudhari26 deleted the show-argo0cr-diff branch May 13, 2026 18:19
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.

Application CR Preview

2 participants