fix(ci): restore preflight image cleanup marker and remove obsolete publish-container tests
- Restore build_attempted=1 in ci-preflight.sh so the exit trap
removes the temporary image tag
- Remove publish-container.test.ts and its harness (publication
workflow and script were removed in fff284aa)
- Update deploy-workflow-contract and docker-build-contract tests
to assert that publication has been removed
This commit is contained in:
1 parent
da90b90c97
commit
faa37e7c58
5 files changed
+6
-148
No files matched your search
@@ -38,6 +38,7 @@ pnpm install --frozen-lockfile
|
||||
pnpm exec playwright install chromium
|
||||
export NEWS_E2E_IMAGE="$image"
|
||||
export NEWS_E2E_RELEASE="$sha"
|
||||
build_attempted=1
|
||||
DOCKER_BUILDKIT=1 docker build --network=host --progress=plain \
|
||||
--build-arg NEXT_DEPLOYMENT_ID="$sha" -t "$image" .
|
||||
NEWS_E2E_IMAGE="$image" NEWS_E2E_RELEASE="$sha" node --import tsx e2e/news-real/run.ts
|
||||
@@ -54,16 +54,7 @@ it("builds the checked out source without fetching a moving remote branch", () =
|
||||
expect(dockerfile).not.toMatch(/^RUN\s+git\s+(?:pull|fetch|clone)\b/m);
|
||||
});
|
||||
|
||||
it("publishes commit images after successful main deployment and preserves manual retries", () => {
|
||||
const publish = workflow.slice(workflow.indexOf("\n publish-container:"));
|
||||
expect(publish).toContain("needs: deploy");
|
||||
expect(publish).toContain("gitea.event_name == 'push'");
|
||||
expect(publish).toContain("gitea.ref_name == 'main'");
|
||||
expect(publish).toContain("gitea.ref_name == 'master'");
|
||||
expect(publish).toContain("bash scripts/publish-container.sh");
|
||||
expect(publish).toContain("secrets.CONTAINER_REGISTRY_USER");
|
||||
expect(publish).toContain("secrets.CONTAINER_REGISTRY_TOKEN");
|
||||
const manual = readFileSync(".gitea/workflows/container.yaml", "utf8");
|
||||
expect(manual).toContain("workflow_dispatch:");
|
||||
expect(manual).not.toMatch(/^ {2}push:/m);
|
||||
it("no longer publishes container images in CI", () => {
|
||||
expect(workflow).not.toContain("publish-container");
|
||||
expect(workflow).not.toContain("publish-container.sh");
|
||||
});
|
||||
@@ -58,14 +58,8 @@ it("builds with fixtures and excludes installation secrets from every stage", ()
|
||||
expect(updater).toContain("target=/app/.env,readonly");
|
||||
expect(updater).toContain("--target migrations");
|
||||
});
|
||||
it("verifies portability before publishing and uses committed build context", () => {
|
||||
const publish = readFileSync("scripts/publish-container.sh", "utf8");
|
||||
expect(publish).toContain("git archive HEAD");
|
||||
expect(
|
||||
publish.indexOf("node scripts/verify-portable-image.mjs"),
|
||||
).toBeLessThan(publish.indexOf("regctl image import"));
|
||||
expect(publish).toContain("--password-stdin");
|
||||
expect(publish).not.toContain(":latest");
|
||||
it("does not reference a container publication script", () => {
|
||||
expect(() => readFileSync("scripts/publish-container.sh", "utf8")).toThrow();
|
||||
});
|
||||
|
||||
it("does not prerender installation metadata into a shared image", () => {
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
import { spawnSync } from "node:child_process";
|
||||
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { delimiter, dirname, join, resolve } from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
const root = process.cwd();
|
||||
const bash =
|
||||
process.platform === "win32"
|
||||
? ((process.env.PATH ?? "")
|
||||
.split(delimiter)
|
||||
.flatMap((dir) => [
|
||||
join(dir, "bash.exe"),
|
||||
join(dirname(dir), "bin", "bash.exe"),
|
||||
join(dirname(dirname(dir)), "bin", "bash.exe"),
|
||||
])
|
||||
.find((path) => existsSync(path)) ?? "bash")
|
||||
: "bash";
|
||||
const sha = "a".repeat(40);
|
||||
function simulate(scenario: string, namespace = "", expectedStatus = 0) {
|
||||
const dir = mkdtempSync(join(tmpdir(), "cms-publish-test-"));
|
||||
try {
|
||||
const result = spawnSync(
|
||||
bash,
|
||||
[resolve(root, "scripts/publish-container.sh")],
|
||||
{
|
||||
cwd: dir,
|
||||
encoding: "utf8",
|
||||
timeout: 10000,
|
||||
env: {
|
||||
...process.env,
|
||||
BASH_ENV: resolve(root, "src/test/publish-container-harness.sh"),
|
||||
TEST_DIR: dir.replaceAll("\\", "/"),
|
||||
TEST_SHA: sha,
|
||||
SCENARIO: scenario,
|
||||
REGISTRY_SERVER: "https://registry.invalid",
|
||||
REGISTRY_REPOSITORY: "owner/cms",
|
||||
REGISTRY_USER: "Simo",
|
||||
REGISTRY_NAMESPACE: namespace,
|
||||
REGISTRY_TOKEN: "fixture-only",
|
||||
},
|
||||
},
|
||||
);
|
||||
if (result.error) throw result.error;
|
||||
expect(result.status, result.stdout + result.stderr).toBe(expectedStatus);
|
||||
return readFileSync(join(dir, "calls"), "utf8");
|
||||
} finally {
|
||||
rmSync(dir, { recursive: true, force: true });
|
||||
}
|
||||
}
|
||||
describe("verified application image reuse", () => {
|
||||
it("reuses only the exact image digest that passed deployment checks", () => {
|
||||
const calls = simulate("verified");
|
||||
expect(calls).toContain(
|
||||
`docker tag sha256:candidate registry.invalid/simo/cms:${sha}`,
|
||||
);
|
||||
expect(calls).not.toContain("docker build --network=host --build-arg");
|
||||
expect(
|
||||
calls.indexOf("verify scripts/verify-portable-image.mjs"),
|
||||
).toBeLessThan(calls.indexOf("regctl image copy"));
|
||||
});
|
||||
it.each(["missing", "mismatch"])(
|
||||
"builds committed source when verification marker is %s",
|
||||
(scenario) => {
|
||||
const calls = simulate(scenario);
|
||||
expect(calls).toContain("docker build --network=host --build-arg");
|
||||
expect(calls).not.toContain("docker tag sha256:candidate");
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
it("uses the token account namespace instead of the repository owner", () => {
|
||||
const calls = simulate("verified");
|
||||
expect(calls).toContain(`registry.invalid/simo/cms:${sha}\n`);
|
||||
expect(calls).not.toContain("registry.invalid/owner/cms");
|
||||
});
|
||||
it("supports an explicit organization namespace", () => {
|
||||
const calls = simulate("verified", "My-Org");
|
||||
expect(calls).toContain(`registry.invalid/my-org/cms:${sha}\n`);
|
||||
});
|
||||
|
||||
it("bounds uploads and verifies both published image configs", () => {
|
||||
const calls = simulate("verified");
|
||||
expect(calls).toContain("--blob-chunk 8388608 --blob-max 8388608");
|
||||
expect(calls).not.toContain("docker push");
|
||||
expect(calls.match(/regctl image import/g)).toHaveLength(2);
|
||||
expect(calls.match(/regctl image copy/g)).toHaveLength(2);
|
||||
expect(calls.match(/regctl manifest get/g)).toHaveLength(4);
|
||||
expect(calls.match(/--platform linux\/amd64/g)).toHaveLength(4);
|
||||
});
|
||||
it.each(["upload-fails", "wrong-config", "bad-checksum"])(
|
||||
"stops publication on %s",
|
||||
(scenario) => {
|
||||
const calls = simulate(scenario, "", 1);
|
||||
expect(calls.match(/regctl image copy/g)?.length ?? 0).toBeLessThanOrEqual(
|
||||
1,
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -1,29 +0,0 @@
|
||||
git() { if [ "$1" = rev-parse ]; then echo "$TEST_SHA"; fi; }
|
||||
tar() { cat >/dev/null; }
|
||||
node() { echo "verify $*" >> "$TEST_DIR/calls"; }
|
||||
docker() {
|
||||
echo "docker $*" >> "$TEST_DIR/calls"
|
||||
if [ "$1" = login ]; then cat >/dev/null; return; fi
|
||||
if [ "$1 $2" = "image inspect" ]; then
|
||||
if [[ "$*" = *org.opencontainers.image.revision* ]]; then echo "$TEST_SHA"
|
||||
elif [[ "${@: -1}" = *verified-* ]]; then
|
||||
case "$SCENARIO" in verified) echo sha256:candidate ;; mismatch) echo sha256:other ;; *) return 1 ;; esac
|
||||
else echo sha256:candidate; fi
|
||||
fi
|
||||
}
|
||||
export -f git tar node docker
|
||||
|
||||
curl() {
|
||||
local output="${@: -1}"
|
||||
cat > "$output" <<'MOCK'
|
||||
#!/usr/bin/env bash
|
||||
echo "regctl $*" >> "$TEST_DIR/calls"
|
||||
if [[ "$1 $2" = "image copy" && "$SCENARIO" = upload-fails ]]; then exit 1; fi
|
||||
if [[ "$1 $2" = "manifest get" ]]; then
|
||||
if [[ "$SCENARIO" = wrong-config && "$3" != ocidir:* ]]; then echo sha256:wrong; else printf "sha256:%064d\n" 0; fi
|
||||
fi
|
||||
MOCK
|
||||
}
|
||||
sha256sum() { cat >/dev/null; [[ "$SCENARIO" != bad-checksum ]]; }
|
||||
uname() { echo x86_64; }
|
||||
export -f curl sha256sum uname
|
||||
Reference in new issue
Block a user