// @ts-nocheck import { readFileSync } from "node:fs"; import { expect, it } from "vitest"; const workflow = readFileSync(".gitea/workflows/ci.yaml", "utf8"); const deploy = readFileSync("scripts/ci-deploy.sh", "utf8"); it("uses two test workers and runs smoke checks in the deployment transaction", () => { expect(workflow).toContain("pnpm test:coverage --maxWorkers=4"); expect(workflow).not.toContain("\n e2e:"); expect(workflow).toContain("bash scripts/ci-deploy.sh"); expect(deploy).toContain( "node scripts/verify-deployed-release.mjs http://127.0.0.1:3002/api/health", ); }); it("locks CI and scheduled deployments using the same production lock", () => { expect(deploy).toContain('exec 9>"$deploy_dir/.deploy.lock"'); expect(deploy).toContain("flock -w 1800 9"); const scheduled = readFileSync("scripts/docker-update.sh", "utf8"); expect(scheduled).toContain('exec 9>"$DIR/.deploy.lock"'); expect(scheduled.indexOf("flock -w 1800 9")).toBeLessThan( scheduled.indexOf("git pull --ff-only"), ); }); it("preserves production runtime configuration and recent cache", () => { expect(deploy).toContain("--net=host"); expect(deploy).toContain("--restart always"); expect(deploy).toContain("/var/www/Gamedata:/var/www/Gamedata"); expect(deploy).toContain("/app/storage"); expect(deploy).not.toContain("--env-file"); // The scoped prune lives in docker-prune.sh; deploys invoke it for both CI // and scheduled updates. It reclaims build cache + old unreferenced images // but never touches volumes. expect(deploy).toContain('bash "$deploy_dir/scripts/docker-prune.sh"'); const prune = readFileSync("scripts/docker-prune.sh", "utf8"); // The build cache is bounded by the cap alone. buildx treats --max-used-space // and --filter as mutually exclusive: combining them silently dropped the // cap, so the cache grew unbounded (49 GB observed on this host). expect(prune).toContain("docker builder prune -af --max-used-space="); expect(prune).toContain('docker image prune -af --filter "until=168h"'); expect(prune).toContain('docker container prune -f --filter "until=24h"'); // Emergency `--force` mode drops every age window to reclaim unused bytes, // but even then volumes are off-limits. expect(prune).toContain('== "--force" ]]'); expect(prune).toContain("FORCE=1"); expect(prune).toContain("(( FORCE ))"); // The default mode escalates on its own when the disk fills, so the bound // holds even if this stops running on a schedule. expect(prune).toContain("FREE_KB"); expect(prune).toMatch(/if\s*\(\(\s*FREE_KB\s* { const dockerfile = readFileSync("Dockerfile", "utf8"); expect(dockerfile).toContain("COPY . ."); expect(dockerfile).not.toMatch( /^ADD\s+https?:\/\/.*(?:repository|branches)/m, ); expect(dockerfile).not.toMatch(/^RUN\s+git\s+(?:pull|fetch|clone)\b/m); }); it("no longer publishes container images in CI", () => { expect(workflow).not.toContain("publish-container"); expect(workflow).not.toContain("publish-container.sh"); });