/** * The gate for celilo#1423. `image-freshness` stamped an attestation of INTENT * (the tree / the staged tarball) and nothing ever read the committed artifact, * so an image carrying a stale CLI certified as fresh. These tests cover the * comparison that now refuses the commit. * * Rule 7.6 — watched failing. The end-to-end proof is the shell digest running * against two real trees below: point it at a directory whose bytes differ and * it reports different digests. Delete the `find | sha256sum` pipeline from * digestScript and `digests the real bytes` goes red. */ import { afterAll, describe, expect, test } from 'bun:test'; import { execFileSync } from 'node:child_process'; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { digestScript, mismatchMessage, parseDigests } from './installed-cli-digest'; /** Scratch dirs removed at exit: the CI runner's PrivateTmp is never reclaimed (celilo#1469). */ const scratchDirs: string[] = []; function scratch(dir: string): string { scratchDirs.push(dir); return dir; } afterAll(() => { for (const dir of scratchDirs) rmSync(dir, { recursive: true, force: true }); }); describe('parseDigests', () => { test('reads both digests', () => { const a = 'a'.repeat(64); const b = 'b'.repeat(64); expect(parseDigests(`staged=${a}\ninstalled=${b}\n`)).toEqual({ staged: a, installed: b }); }); test('throws on a truncated probe rather than degrading to a pass', () => { // The whole failure class this file exists for: a check that cannot fail. expect(() => parseDigests(`staged=${'a'.repeat(64)}\n`)).toThrow(/no installed digest/); }); test('throws when the probe printed nothing at all', () => { expect(() => parseDigests('')).toThrow(/no staged digest/); }); test('ignores a digest-shaped string that is not the probe line', () => { expect(() => parseDigests(`note: staged=${'a'.repeat(64)} inline`)).toThrow(); }); }); describe('mismatchMessage', () => { test('names both digests and the rebuild that fixes it', () => { const msg = mismatchMessage({ staged: 'a'.repeat(64), installed: 'b'.repeat(64) }); expect(msg).toContain('a'.repeat(64)); expect(msg).toContain('b'.repeat(64)); expect(msg).toContain('cele2e build-infra'); }); }); // Runs the REAL script against real directories, on the container's // sha256sum or a dev box's shasum — see digestScript. describe('digestScript', () => { /** A tarball of `package/` plus an install tree, wired where the script looks. */ function stage(installedFiles: Record): { dir: string; run: () => string } { const dir = scratch(mkdtempSync(join(tmpdir(), 'cli-digest-'))); const pkg = join(dir, 'src', 'package'); mkdirSync(pkg, { recursive: true }); writeFileSync(join(pkg, 'index.js'), 'export const a = 1;\n'); writeFileSync(join(pkg, 'package.json'), '{"name":"@celilo/cli"}\n'); execFileSync('tar', ['-czf', join(dir, 'cli.tgz'), '-C', join(dir, 'src'), 'package']); const installed = join(dir, 'installed'); mkdirSync(installed, { recursive: true }); for (const [name, body] of Object.entries(installedFiles)) { writeFileSync(join(installed, name), body); } const script = digestScript(installed) .replace('/tmp/cli-staged.tgz', join(dir, 'cli.tgz')) .replaceAll('/tmp/cli-staged', join(dir, 'extract')) .replaceAll('/tmp/cli-files', join(dir, 'files')); return { dir, run: () => execFileSync('bash', ['-c', script], { encoding: 'utf-8' }), }; } test('digests the real bytes: identical trees agree', () => { const { run } = stage({ 'index.js': 'export const a = 1;\n', 'package.json': '{"name":"@celilo/cli"}\n', }); const { staged, installed } = parseDigests(run()); expect(installed).toBe(staged); }); test('one changed byte in the installed tree disagrees', () => { const { run } = stage({ 'index.js': 'export const a = 2;\n', 'package.json': '{"name":"@celilo/cli"}\n', }); const { staged, installed } = parseDigests(run()); expect(installed).not.toBe(staged); }); test('a tarball file missing from the install disagrees', () => { const { run } = stage({ 'index.js': 'export const a = 1;\n' }); const { staged, installed } = parseDigests(run()); expect(installed).not.toBe(staged); }); test('an install directory that does not exist yields no digest at all', () => { const { dir, run } = stage({}); // Point at a path nothing created: `cd` fails, the digest is empty, and // parseDigests refuses to read that as agreement. const script = digestScript(join(dir, 'absent')); expect(script).toContain(join(dir, 'absent')); expect(() => parseDigests(run().replace(/^installed=.*$/m, 'installed='))).toThrow( /no installed digest/, ); }); });