test: follow the extracted cloud workflow in image guards

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Devin Foley 2026-09-10 18:49:27 -07:00
parent ca83970d79
commit 02b68fc74b
2 changed files with 8 additions and 9 deletions

View File

@ -20,6 +20,7 @@ import { BUNDLED_PLUGIN_CATALOG } from "../services/bundled-plugins.js";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
const dockerfile = readFileSync(path.join(repoRoot, "Dockerfile"), "utf8");
const workflow = readFileSync(path.join(repoRoot, ".github", "workflows", "docker.yml"), "utf8");
const cloudWorkflow = readFileSync(path.join(repoRoot, ".github", "workflows", "docker-cloud.yml"), "utf8");
function parseList(source: string, pattern: RegExp, label: string): string[] {
const match = source.match(pattern);
@ -35,7 +36,7 @@ const dockerfileDefault = parseList(
"Dockerfile",
);
const workflowArg = parseList(
workflow,
cloudWorkflow,
/^\s*CLOUD_BUNDLED_PLUGINS=(.*)$/m,
"docker workflow",
);
@ -77,16 +78,14 @@ describe("cloud image bundled plugins", () => {
});
it("publishes the cloud image in its own job with no needs coupling", () => {
// The cloud publish runs as its own top-level job so the stock/production
// publish can never gate, delay, or skip it. Both jobs share only the
// single top-level concurrency slot; there is deliberately no `needs:`
// between them, so a failure in one is never coupled to the other.
const jobsSection = workflow.slice(workflow.indexOf("\njobs:\n"));
// The reusable cloud workflow owns its job and SHA concurrency group.
// Production publication must not gate, delay, or skip the cloud build.
const jobsSection = cloudWorkflow.slice(cloudWorkflow.indexOf("\njobs:\n"));
const headers = [...jobsSection.matchAll(/^ {2}([\w-]+):[^\n]*$/gm)];
expect(
headers.length,
"docker.yml must declare at least two jobs under jobs:",
).toBeGreaterThanOrEqual(2);
"docker-cloud.yml must declare a cloud build job under jobs:",
).toBeGreaterThanOrEqual(1);
// Locate the job block that carries the cloud build (target: cloud) and
// assert it declares no `needs:` — coupling it to another job would

View File

@ -37,7 +37,7 @@ import { describe, expect, it } from "vitest";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "..", "..");
const dockerfile = readFileSync(path.join(repoRoot, "Dockerfile"), "utf8");
const workflow = readFileSync(path.join(repoRoot, ".github", "workflows", "docker.yml"), "utf8");
const workflow = readFileSync(path.join(repoRoot, ".github", "workflows", "docker-cloud.yml"), "utf8");
const serverPackageJson = JSON.parse(
readFileSync(path.join(repoRoot, "server", "package.json"), "utf8"),
) as { peerDependencies?: Record<string, string> };