Files
eleith 67cb29b7f6
ci/woodpecker/pr/config Pipeline was successful
ci/woodpecker/pr/hledger Pipeline was successful
ci/woodpecker/pr/jobs Pipeline was successful
ci/woodpecker/pr/snapshots Pipeline was successful
ci/woodpecker/pr/web Pipeline was successful
ci/woodpecker/pr/worker Pipeline was successful
ci/woodpecker/push/config Pipeline was successful
ci/woodpecker/push/hledger Pipeline was successful
ci/woodpecker/push/jobs Pipeline was successful
ci/woodpecker/push/snapshots Pipeline was successful
ci/woodpecker/push/web Pipeline was successful
ci/woodpecker/push/worker Pipeline was successful
test: generate small fixtures and simplify CI setup
2026-11-06 16:38:05 -08:00

75 lines
2.4 KiB
JavaScript

import { spawn } from 'node:child_process';
import { randomUUID } from 'node:crypto';
import { once } from 'node:events';
import { rm } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import { setTimeout as delay } from 'node:timers/promises';
import { fileURLToPath } from 'node:url';
import { prepareBrowserFixture } from './fixture.js';
// App-owned test deployment: no personal config and no reused SQLite/data files.
const deployment =
process.env.HLEDGER_TEST_DEPLOYMENT ?? join(tmpdir(), `hledger-browser-${randomUUID()}`);
const { configPath } = await prepareBrowserFixture(deployment);
const children = [];
let stopping = false;
async function stop(code) {
if (stopping) return;
stopping = true;
const exits = children.map((child) =>
child.pid === undefined || child.exitCode !== null || child.signalCode !== null
? Promise.resolve()
: once(child, 'exit')
);
for (const child of children) child.kill('SIGTERM');
const deadline = setTimeout(() => {
for (const child of children) child.kill('SIGKILL');
}, 5_000);
await Promise.all(exits);
clearTimeout(deadline);
await rm(deployment, { recursive: true, force: true });
process.exit(code);
}
process.once('SIGINT', () => void stop(0));
process.once('SIGTERM', () => void stop(0));
function start(relativeEntry, environment) {
const entry = fileURLToPath(new URL(relativeEntry, import.meta.url));
const child = spawn(process.execPath, [entry], {
env: { ...process.env, ...environment, CONFIG_PATH: configPath },
stdio: 'inherit'
});
children.push(child);
child.once('error', () => void stop(1));
child.once('exit', () => {
if (!stopping) void stop(1);
});
}
start('../../worker/dist/src/index.js', { WORKER_PORT: '4193' });
try {
let ready = false;
for (let attempt = 0; attempt < 100 && !ready; attempt++) {
ready = await fetch('http://127.0.0.1:4193/healthz', {
signal: AbortSignal.timeout(1_000)
})
.then((response) => response.ok)
.catch(() => false);
if (!ready) await delay(100);
}
if (!ready) throw new Error('Fixture worker did not become ready.');
start('./web.js', {
HOST: '127.0.0.1',
PORT: '3000',
ADDRESS_HEADER: 'x-real-ip',
PROTOCOL_HEADER: 'x-forwarded-proto',
HOST_HEADER: '',
PORT_HEADER: ''
});
} catch {
console.error('Browser fixture startup failed. Build both apps and check hledger 1.99.5.');
await stop(1);
}