Files
ECC/docker/context-profiles/run-podman.js
T

51 lines
2.7 KiB
JavaScript

#!/usr/bin/env node
'use strict';
const assert = require('node:assert/strict');
const crypto = require('node:crypto');
const fs = require('node:fs');
const os = require('node:os');
const path = require('node:path');
const { spawnSync } = require('node:child_process');
const repoRoot = path.resolve(__dirname, '../..');
const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'ecc-context-podman-'));
const image = `localhost/ecc-context-profiles:${process.pid}-${Date.now()}`;
function run(command, args, capture = false) {
const result = spawnSync(command, args, { cwd: repoRoot, encoding: 'utf8',
timeout: 600000, maxBuffer: 32 * 1024 * 1024, stdio: capture ? 'pipe' : 'inherit' });
assert.equal(result.status, 0, `${command}: ${result.error || result.stderr || result.stdout}`);
return result.stdout;
}
try {
const packed = JSON.parse(run('npm', ['pack', '--json', '--pack-destination', temp], true));
const { planContextCarrier } = require('../../scripts/lib/context-carriers');
const expected = [];
for (const target of ['claude', 'codex', 'pi', 'opencode', 'cursor']) {
for (const profileId of ['lean@1', 'full@1']) {
expected.push(planContextCarrier({ repoRoot, target, profileId, selectionMode: 'auto' }));
}
}
const archivePaths = new Set(packed[0].files.map(file => file.path));
const missing = expected[1].files.filter(file => file.kind === 'copy' && !archivePaths.has(file.sourcePath));
assert.deepEqual(missing, [], 'Packed archive omitted canonical skill resources');
fs.writeFileSync(path.join(temp, 'expected-carriers.json'), JSON.stringify(expected));
fs.renameSync(path.join(temp, packed[0].filename), path.join(temp, 'package.tgz'));
for (const file of ['Dockerfile', 'native-probe.js', 'native-switch-probe.js', 'packed-smoke.js']) {
fs.copyFileSync(path.join(__dirname, file), path.join(temp, file));
}
fs.copyFileSync(path.join(repoRoot, 'tests/lib/helpers/context-carrier-fixture.js'),
path.join(temp, 'context-carrier-fixture.js'));
const packageDigest = crypto.createHash('sha256').update(fs.readFileSync(path.join(temp, 'package.tgz'))).digest('hex');
process.stdout.write(`${JSON.stringify({ packageDigest, image })}\n`);
const args = ['build', '--tag', image];
if (process.env.ECC_CONTEXT_NODE_IMAGE) args.push('--build-arg', `NODE_IMAGE=${process.env.ECC_CONTEXT_NODE_IMAGE}`);
args.push(temp);
run('podman', args);
run('podman', ['run', '--rm', '--network=none', '--cap-drop=all', '--security-opt=no-new-privileges', image]);
} finally {
// Only the image and temporary directory created by this invocation are removed.
spawnSync('podman', ['image', 'rm', image], { stdio: 'ignore', timeout: 60000 });
fs.rmSync(temp, { recursive: true, force: true });
}