Skip to content

Commit 8f1702f

Browse files
feat: show diff of current vs proposed rendered argo CR
1 parent b358745 commit 8f1702f

12 files changed

Lines changed: 653 additions & 262 deletions

File tree

apps/web/app/lib/plan-sections.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import yaml from "js-yaml";
2+
3+
export type PlanSection = { name: string; content: string };
4+
5+
const isArgoApplication = (doc: unknown): boolean => {
6+
const d = doc as { apiVersion?: unknown; kind?: unknown } | null;
7+
return (
8+
typeof d?.apiVersion === "string" &&
9+
d.apiVersion.startsWith("argoproj.io/") &&
10+
d.kind === "Application"
11+
);
12+
};
13+
14+
function tryParseYamlStream(stream: string): unknown[] | null {
15+
try {
16+
return yaml
17+
.loadAll(stream)
18+
.filter(
19+
(d) =>
20+
d != null && (typeof d !== "object" || Object.keys(d).length > 0),
21+
);
22+
} catch {
23+
return null;
24+
}
25+
}
26+
27+
export function extractPlanSections(stream: string): PlanSection[] {
28+
if (!stream.trim()) return [];
29+
30+
const docs = tryParseYamlStream(stream);
31+
if (docs == null) return [{ name: "Rendered Manifests", content: stream }];
32+
33+
const cr = docs.filter(isArgoApplication);
34+
const manifests = docs.filter((d) => !isArgoApplication(d));
35+
36+
return [
37+
...(cr.length > 0
38+
? [
39+
{
40+
name: "Application CR",
41+
content: cr.map((d) => yaml.dump(d)).join("---\n"),
42+
},
43+
]
44+
: []),
45+
...(manifests.length > 0
46+
? [
47+
{
48+
name: "Rendered Manifests",
49+
content: manifests.map((d) => yaml.dump(d)).join("---\n"),
50+
},
51+
]
52+
: []),
53+
];
54+
}
55+
56+
export function unionSectionNames(...streams: string[]): string[] {
57+
const names = new Set<string>();
58+
for (const s of streams) {
59+
for (const sec of extractPlanSections(s)) names.add(sec.name);
60+
}
61+
return [...names];
62+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { Link, useParams } from "react-router";
2+
3+
import { trpc } from "~/api/trpc";
4+
import {
5+
Breadcrumb,
6+
BreadcrumbItem,
7+
BreadcrumbList,
8+
BreadcrumbPage,
9+
BreadcrumbSeparator,
10+
} from "~/components/ui/breadcrumb";
11+
import { Separator } from "~/components/ui/separator";
12+
import { SidebarTrigger } from "~/components/ui/sidebar";
13+
import { useWorkspace } from "~/components/WorkspaceProvider";
14+
import { useDeployment } from "../DeploymentProvider";
15+
import { DeploymentsNavbarTabs } from "../DeploymentsNavbarTabs";
16+
17+
export function PlanDetailPageHeader() {
18+
const { workspace } = useWorkspace();
19+
const { deployment } = useDeployment();
20+
const { planId } = useParams<{ planId: string }>();
21+
22+
const resultsQuery = trpc.deployment.plans.results.useQuery(
23+
{ deploymentId: deployment.id, planId: planId! },
24+
{ enabled: !!planId },
25+
);
26+
const version = resultsQuery.data?.version;
27+
28+
return (
29+
<header className="flex h-16 shrink-0 items-center justify-between gap-2 border-b pr-4">
30+
<div className="flex items-center gap-2 px-4">
31+
<SidebarTrigger className="-ml-1" />
32+
<Separator
33+
orientation="vertical"
34+
className="mr-2 data-[orientation=vertical]:h-4"
35+
/>
36+
<Breadcrumb>
37+
<BreadcrumbList>
38+
<BreadcrumbItem>
39+
<Link to={`/${workspace.slug}/deployments`}>Deployments</Link>
40+
</BreadcrumbItem>
41+
<BreadcrumbSeparator />
42+
<BreadcrumbItem>
43+
<Link to={`/${workspace.slug}/deployments/${deployment.id}`}>
44+
{deployment.name}
45+
</Link>
46+
</BreadcrumbItem>
47+
<BreadcrumbSeparator />
48+
<BreadcrumbItem>
49+
<Link
50+
to={`/${workspace.slug}/deployments/${deployment.id}/plans`}
51+
>
52+
Plans
53+
</Link>
54+
</BreadcrumbItem>
55+
<BreadcrumbSeparator />
56+
<BreadcrumbPage className="max-w-xs truncate font-mono">
57+
{version?.name ?? version?.tag ?? planId}
58+
</BreadcrumbPage>
59+
</BreadcrumbList>
60+
</Breadcrumb>
61+
</div>
62+
63+
<div className="flex items-center gap-4">
64+
<DeploymentsNavbarTabs />
65+
</div>
66+
</header>
67+
);
68+
}

0 commit comments

Comments
 (0)