Skip to content

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

Commit

Separate latest branch checks from production deployment status

syntaqxcommitted Parent6049e67Browse files
4 files+53−200/4 viewed
+1−6
124124 /**
125125 * An app that deploys itself (its workflows, or another pipeline): production at the address it was
126126 * given, with the latest reported deployment, or else the default branch's
127− * latest commit and its checks.
127+ * latest commit. Branch checks are shown separately below the production status.
128128 */
129129 export function ElsewhereHead({
130130 project,
133133 canDeploy,
134134 deployment,
135135 commit,
136− checks,
137136 shot,
138137 }: Head & {
139138 deployment?: ExternalDeployment | null;
140139 commit: { hash: string; authoredAt: string } | null;
141− /** The commit's checks, as a badge; left out until there is one to show. */
142− checks?: ReactNode;
143140 /** Production's picture, beside the rest, as an app on g1t has (components/production-shot.tsx). */
144141 shot?: ReactNode;
145142 }) {
157154 {deployment ? (
158155 <>
159156 <StatusDot status={deploymentStatus(deployment.state)} />
160− {checks}
161157 <span className="inline-flex items-center gap-1 font-mono">
162158 <GitCommitHorizontal size={13} className="text-faint" />
163159 <Link to={`${base}/commit/${deployment.sha}`} className="hover:text-fg">{deployment.sha.slice(0, 7)}</Link>
187183 <GitCommitHorizontal size={13} className="text-faint" />
188184 {commit.hash.slice(0, 7)}
189185 </Link>
190− {checks}
191186 <TimeAgo at={commit.authoredAt} />
192187 </span>
193188 )}
+21−0
1+import assert from "node:assert/strict";
2+import { test } from "node:test";
3+import { projectCheckSections } from "./project-checks.ts";
4+
5+test("a CLI-only fix keeps latest branch checks separate from the older production commit", () => {
6+ assert.deepEqual(projectCheckSections("6049e67", "main", "a8f62b9"), [
7+ { kind: "branch", label: "Latest on main", sha: "6049e67" },
8+ { kind: "production", label: "Checks for deployed commit", sha: "a8f62b9" },
9+ ]);
10+});
11+
12+test("the same commit is not reported twice, and a project without deployment still shows branch checks", () => {
13+ const branch = [{ kind: "branch", label: "Latest on trunk", sha: "head" }];
14+ assert.deepEqual(projectCheckSections("head", "trunk", "head"), branch);
15+ assert.deepEqual(projectCheckSections("head", "trunk", null), branch);
16+});
17+
18+test("an unavailable branch head never mislabels deployed checks as latest branch checks", () => {
19+ assert.deepEqual(projectCheckSections(null, "main", "old"), [{ kind: "production", label: "Checks for deployed commit", sha: "old" }]);
20+ assert.deepEqual(projectCheckSections(null, null, null), []);
21+});
+7−0
1+/** Branch health and deployed-code checks refer to different commits after a no-op deploy. */
2+export function projectCheckSections(head: string | null | undefined, branch: string | null | undefined, deployed: string | null | undefined) {
3+ const sections: { kind: "branch" | "production"; label: string; sha: string }[] = [];
4+ if (head) sections.push({ kind: "branch", label: `Latest on ${branch ?? "default branch"}`, sha: head });
5+ if (deployed && deployed !== head) sections.push({ kind: "production", label: "Checks for deployed commit", sha: deployed });
6+ return sections;
7+}
+24−14
6060 import { cardSources, externalTarget, externalVersion, productionImageUrl } from "../../lib/production-image";
6161 import { useAddresses } from "../../lib/addresses";
6262 import { commitChecksFor } from "../../lib/commit-checks.server";
63−import { CommitChecksBadge, CommitChecksSummary } from "../../components/commit-checks";
63+import { CommitChecksSummary } from "../../components/commit-checks";
64+import { projectCheckSections } from "../../lib/project-checks";
6465 import { StatusIcon, Duration, shortRef, standingWord } from "../../components/actions";
6566 import { resolveRange, rangeLabel } from "../../lib/usage";
6667 import { deliveryDays, duration as deliveryDuration } from "../../lib/workspace-insights";
292293 : null,
293294 commit: commit ? { hash: commit.hash, authoredAt: commit.authoredAt } : null,
294295 // The commit's checks, streamed in after the page.
295− checks: commitChecksFor(path, viewer, [commit?.hash, deployment?.sha, productionLatest?.sha]),
296+ checks: commitChecksFor(path, viewer, [commit?.hash, current?.sha, production?.commit]),
296297 workflowRuns: ok(workflowRuns),
297298 insights,
298299 range,
798799 const name = project?.name ?? params.repo;
799800 const plan = project ? projectPlan(project) : "production";
800801 const canChange = member && loaderData.can.manage_settings;
801− const checkSha = loaderData.productionLatest?.sha ?? loaderData.commit?.hash;
802+ const deployedSha = loaderData.serving?.sha ?? loaderData.production?.commit;
803+ const checkSections = projectCheckSections(loaderData.commit?.hash, defaultBranch, deployedSha);
802804 const addresses = useAddresses();
803805 // The production card's picture: an uploaded image, served from the
804806 // usercontent origin, and where someone who may change it adds one.
841843 canDeploy={member && loaderData.can.manage_integrations}
842844 deployment={loaderData.deployment}
843845 commit={loaderData.commit}
844− checks={(loaderData.deployment?.sha ?? loaderData.commit?.hash) ? <CommitChecksBadge checks={loaderData.checks} sha={(loaderData.deployment?.sha ?? loaderData.commit?.hash)!} /> : undefined}
845846 shot={
846847 <ProductionShot
847848 sources={cardSources(loaderData.elsewhereShot, upload)}
863864 ) : (
864865 <ProductionHead loaderData={loaderData} base={base} name={name} upload={upload} addImage={addImage} />
865866 )}
866− {checkSha && (
867+ {checkSections.length > 0 && (
867868 <div className="border-t border-line px-5 py-4 sm:px-6">
868− <div className="mb-2 flex flex-wrap items-center gap-2 text-xs text-muted">
869− <GitCommitHorizontal size={14} />
870− <span>{loaderData.productionLatest ? "Latest production deployment" : `Latest on ${defaultBranch ?? "default branch"}`}</span>
871− <Link to={`${base}/commit/${checkSha}`} className="font-mono hover:text-fg">{checkSha.slice(0, 7)}</Link>
872− </div>
873− <CommitChecksSummary checks={loaderData.checks} sha={checkSha} />
874− {loaderData.serving && loaderData.serving.sha !== checkSha && (
875− <p className="mt-2 text-xs text-muted">Currently serving <Link to={`${base}/commit/${loaderData.serving.sha}`} className="font-mono text-fg-soft hover:underline">{loaderData.serving.sha.slice(0, 7)}</Link> &middot; deployed <TimeAgo at={loaderData.serving.at} /></p>
876− )}
869+ {checkSections.map((section) => section.kind === "branch" ? (
870+ <div key={section.kind}>
871+ <div className="mb-2 flex flex-wrap items-center gap-2 text-xs text-muted">
872+ <GitCommitHorizontal size={14} />
873+ <span>{section.label}</span>
874+ <Link to={`${base}/commit/${section.sha}`} className="font-mono hover:text-fg">{section.sha.slice(0, 7)}</Link>
875+ </div>
876+ <CommitChecksSummary checks={loaderData.checks} sha={section.sha} />
877+ </div>
878+ ) : (
879+ <details key={section.kind} className="mt-3 text-xs text-muted">
880+ <summary className="cursor-pointer hover:text-fg">{section.label} <span className="font-mono">{section.sha.slice(0, 7)}</span></summary>
881+ <p className="my-2">These checks belong to the code deployed to production. Deployment status is shown above.</p>
882+ <Link to={`${base}/commit/${section.sha}`} className="mb-2 inline-block text-accent hover:underline">View deployed commit</Link>
883+ <CommitChecksSummary checks={loaderData.checks} sha={section.sha} />
884+ </details>
885+ ))}
886+ {deployedSha && <p className="mt-2 text-xs text-muted">Currently serving <Link to={`${base}/commit/${deployedSha}`} className="font-mono text-fg-soft hover:underline">{deployedSha.slice(0, 7)}</Link>{loaderData.serving && <> &middot; deployed <TimeAgo at={loaderData.serving.at} /></>}</p>}
877887 </div>
878888 )}
879889 {actionData && (

Comments

Sign in to comment.