81 lines
3.2 KiB
JavaScript
81 lines
3.2 KiB
JavaScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mkdtempSync, mkdirSync, readFileSync, writeFileSync, rmSync, existsSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
import { spawnSync } from 'node:child_process';
|
|
|
|
for (const status of ['0', '23', '124', '137', 'empty']) {
|
|
for (const pending of [false, true]) {
|
|
test('runtime prestart status ' + status + ', pending migration ' + pending, () => {
|
|
const dir = mkdtempSync(join(tmpdir(), 'dsh-prestart-'));
|
|
try {
|
|
if (status !== 'empty') {
|
|
mkdirSync(join(dir, 'profiles/web'), { recursive: true, mode: 0o700 });
|
|
writeFileSync(join(dir, 'profiles/web/package.json'), '{}', { mode: 0o600 });
|
|
if (pending) writeFileSync(join(dir, 'profiles/web/.dsh-lockfile-pending'), 'pending');
|
|
}
|
|
const scripts = {
|
|
node: `#!/bin/bash
|
|
exit 0
|
|
`,
|
|
timeout: `#!/bin/bash
|
|
printf 'timeout %s\n' "$*" >> "$TRACE"
|
|
test "$1 $2 $3" = "--signal=TERM --kill-after=5s 120s" || exit 90
|
|
shift 3
|
|
exec "$@"
|
|
`,
|
|
dsh: `#!/bin/bash
|
|
printf 'dsh %s\n' "$*" >> "$TRACE"
|
|
test "$npm_config_ignore_scripts:$npm_config_ignore_pnpmfile" = true:true || exit 91
|
|
if [ "$1" = plugin ]; then
|
|
test "$*" = "plugin --profile web install --ignore-scripts$EXPECTED_ARGS" || exit 92
|
|
exit "$PLUGIN_STATUS"
|
|
fi
|
|
exit 0
|
|
`,
|
|
caddy: `#!/bin/bash
|
|
echo caddy >> "$TRACE"
|
|
sleep 0.1
|
|
`,
|
|
};
|
|
for (const [name, script] of Object.entries(scripts)) {
|
|
writeFileSync(join(dir, name), script, { mode: 0o700 });
|
|
}
|
|
const result = spawnSync('bash', [fileURLToPath(new URL('./entrypoint.sh', import.meta.url)), 'web', '--no-open', '--port', '3080'], {
|
|
env: { ...process.env, PATH: dir + ':' + process.env.PATH, DSH_HOME: dir, TRACE: join(dir, 'trace'), PLUGIN_STATUS: status, EXPECTED_ARGS: pending ? ' --no-frozen-lockfile' : '' },
|
|
encoding: 'utf8', timeout: 5000,
|
|
});
|
|
assert.ifError(result.error);
|
|
const output = result.stdout + result.stderr;
|
|
const trace = readFileSync(join(dir, 'trace'), 'utf8');
|
|
assert.equal(result.status, status === 'empty' ? 0 : Number(status), output);
|
|
if (status === 'empty') {
|
|
assert.doesNotMatch(trace, /plugin/);
|
|
assert.match(trace, /dsh web/);
|
|
return;
|
|
}
|
|
assert.match(trace, /dsh plugin --profile web install --ignore-scripts/);
|
|
assert.equal(existsSync(join(dir, 'profiles/web/.dsh-lockfile-pending')), pending && status !== '0');
|
|
if (status === '0') {
|
|
assert.match(output, /reconciliation complete/);
|
|
assert.match(trace, /dsh web/);
|
|
} else {
|
|
assert.ok(output.includes('failed (exit ' + status + ')'), output);
|
|
assert.doesNotMatch(trace, /caddy|dsh web/);
|
|
}
|
|
} finally {
|
|
rmSync(dir, { recursive: true, force: true });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
test('runtime pins pnpm and uses nonroot with tini process-group forwarding', () => {
|
|
const dockerfile = readFileSync(new URL('./Dockerfile', import.meta.url), 'utf8');
|
|
for (const required of ['[email protected]', 'test "$(pnpm --version)" = "10.11.0"', 'USER node', '"/usr/bin/tini", "-g"']) {
|
|
assert.ok(dockerfile.includes(required), 'missing ' + required);
|
|
}
|
|
});
|