Files
dsh-web/image/entrypoint.test.mjs
T

86 lines
3.5 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
echo 'install progress and peer warnings'
echo 'install stderr diagnostics' >&2
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.doesNotMatch(output, /install progress|install stderr/);
assert.match(output, /reconciliation complete/);
assert.match(trace, /dsh web/);
} else {
assert.match(result.stderr, /install progress and peer warnings/);
assert.match(result.stderr, /install stderr diagnostics/);
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);
}
});