73 lines
4.2 KiB
JavaScript
73 lines
4.2 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { execFileSync } from 'node:child_process';
|
|
import { cpSync, existsSync, lstatSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
import { imageFingerprint, prepareImage, verifyImage } from '../../../scripts/testing/lane-image.mjs';
|
|
|
|
function fixture(t) {
|
|
const root = execFileSync('mktemp', ['-d', '-p', '/mnt/storage/scratch/tmp'], { encoding: 'utf8' }).trimEnd();
|
|
t.diagnostic(`scratch created: ${root}`);
|
|
assert.match(root, /^\/mnt\/storage\/scratch\/tmp\/tmp\.[A-Za-z0-9]{10}$/);
|
|
const initial = lstatSync(root);
|
|
assert.ok(initial.isDirectory() && !initial.isSymbolicLink());
|
|
assert.equal(initial.uid, process.getuid());
|
|
assert.equal(initial.mode & 0o777, 0o700);
|
|
t.after(() => {
|
|
const current = lstatSync(root);
|
|
assert.equal(current.dev, initial.dev); assert.equal(current.ino, initial.ino);
|
|
assert.equal(current.uid, initial.uid); assert.ok(current.isDirectory() && !current.isSymbolicLink());
|
|
rmSync(root, { recursive: true, force: false });
|
|
assert.equal(existsSync(root), false); t.diagnostic(`scratch disposed: ${root}`);
|
|
});
|
|
for (const file of ['Containerfile', 'package.json', 'package-lock.json', 'RELEASE']) {
|
|
cpSync(new URL('../../../' + file, import.meta.url), join(root, file));
|
|
}
|
|
for (const dir of ['contracts', 'src', 'adapters', 'packages/processing-control/src']) mkdirSync(join(root, dir), { recursive: true });
|
|
for (const file of ['state.mjs', 'entrypoint.mjs']) cpSync(new URL('../../processing-control/src/' + file, import.meta.url), join(root, 'packages/processing-control/src', file));
|
|
return root;
|
|
}
|
|
const actual = { Id: 'sha256:' + 'a'.repeat(64), Os: 'linux', Architecture: 'amd64' };
|
|
function base(root) { return /^FROM (\S+)$/m.exec(readFileSync(join(root, 'Containerfile'), 'utf8'))[1]; }
|
|
function receipt(root) {
|
|
const pkg = JSON.parse(readFileSync(join(root, 'package.json'), 'utf8'));
|
|
const release = readFileSync(join(root, 'RELEASE'), 'utf8').trim();
|
|
return { inputDigest: imageFingerprint(root), imageId: actual.Id, tag: `mosaic-poc-agent:${pkg.dependencies['@earendil-works/pi-coding-agent']}-r${release}`, baseDigest: base(root), platform: 'linux/amd64' };
|
|
}
|
|
|
|
test('image receipt records the actual pinned FROM rather than a stale mutable tag', t => {
|
|
const root = fixture(t), file = join(root, 'Containerfile');
|
|
// A second arbitrary valid pin rules out a hardcoded replacement tag/digest.
|
|
const selected = 'node:24.22.2-bookworm-slim@sha256:' + 'd'.repeat(64);
|
|
writeFileSync(file, readFileSync(file, 'utf8').replace(/^FROM .+$/m, 'FROM ' + selected));
|
|
const calls = [];
|
|
const invoke = args => {
|
|
calls.push(args);
|
|
if (args[0] === 'compose') return '';
|
|
if (args[2] === 'node:24-bookworm-slim') return JSON.stringify({ RepoDigests: ['node@sha256:' + 'b'.repeat(64)] });
|
|
return JSON.stringify(actual);
|
|
};
|
|
const result = prepareImage(root, { grant: 'fixture-only', tempRoot: root }, invoke);
|
|
assert.equal(result.baseDigest, selected);
|
|
assert.equal(calls.some(args => args[2] === 'node:24-bookworm-slim'), false);
|
|
assert.equal(calls.filter(args => args[0] === 'compose').length, 1);
|
|
});
|
|
|
|
test('a well-formed stale base receipt refuses before any image inspection', t => {
|
|
const root = fixture(t), good = receipt(root);
|
|
assert.equal(verifyImage(good, root, () => actual), good);
|
|
let inspected = false;
|
|
assert.throws(() => verifyImage({ ...good, baseDigest: 'node@sha256:' + 'b'.repeat(64) }, root, () => { inspected = true; return actual; }), /base differs/);
|
|
assert.equal(inspected, false);
|
|
});
|
|
|
|
test('mutable, multistage and indirect FROM values refuse before build dispatch', t => {
|
|
const root = fixture(t), file = join(root, 'Containerfile'), original = readFileSync(file, 'utf8');
|
|
for (const from of ['FROM node:24-bookworm-slim', 'FROM ${BASE}', 'FROM scratch', `FROM ${base(root)} AS build`, `FROM ${base(root)}\nFROM ${base(root)}`]) {
|
|
writeFileSync(file, original.replace(/^FROM .+$/m, from));
|
|
let invoked = false;
|
|
assert.throws(() => prepareImage(root, { grant: 'fixture-only', tempRoot: root }, () => { invoked = true; return ''; }), /pinned FROM/);
|
|
assert.equal(invoked, false);
|
|
}
|
|
});
|