repositories / will
will
owned by admin
scripts/boot-test.ts
Raw/**
* Two-container boot test (spec AC4/AC23): build images if needed, run the
* pod with fake providers, and assert both containers become ready within
* the 60-second startup deadline. Requires podman; exits 77 when unavailable
* so CI can distinguish "skipped" from "failed".
*/
import { execFile } from 'node:child_process'
import { promisify } from 'node:util'
const exec = promisify(execFile)
const podman = async (...args: string[]) => exec('podman', args, { timeout: 300_000 })
async function main() {
try {
await podman('--version')
} catch {
console.error('boot-test: podman not available, skipping (77)')
process.exit(77)
}
const fakeEnv = [
'-e',
'WILL_SESSION_MODE=fake',
'-e',
'WILL_TELEGRAM_TOKEN=boot-test',
'-e',
'WILL_TELEGRAM_CHAT_ID=-100',
'-e',
'WILL_TELEGRAM_OLIVER_ID=1',
]
console.log('boot-test: creating pod')
await podman('pod', 'rm', '-f', 'will-boot-test').catch(() => undefined)
await podman('pod', 'create', '--name', 'will-boot-test', '-p', '33100:3000')
console.log('boot-test: starting service container')
await podman(
'run',
'-d',
'--name',
'will-boot-test-service',
'--pod',
'will-boot-test',
'-e',
'WILL_SERVICE_DATA_DIR=/srv/will-data',
'-v',
'will-boot-test-data:/srv/will-data',
'ghcr.io/bugabinga/will-service:dev',
).catch((err) => {
console.error(`boot-test: service image missing, build first (mise run images): ${err.message}`)
process.exit(1)
})
console.log('boot-test: starting agent container')
await podman(
'run',
'-d',
'--name',
'will-boot-test-agent',
'--pod',
'will-boot-test',
...fakeEnv,
'-v',
'will-boot-test-agent:/srv/will-agent',
'ghcr.io/bugabinga/will-agent:dev',
)
const deadline = Date.now() + 60_000
let serviceOk = false
let agentOk = false
while (Date.now() < deadline && !(serviceOk && agentOk)) {
if (!serviceOk) {
serviceOk = await fetch('http://127.0.0.1:33100/healthz')
.then((r) => r.ok)
.catch(() => false)
}
if (!agentOk) {
agentOk = await exec('podman', [
'exec',
'will-boot-test-agent',
'node',
'-e',
"fetch('http://127.0.0.1:8081/readyz').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))",
])
.then(() => true)
.catch(() => false)
}
if (!(serviceOk && agentOk)) await new Promise((r) => setTimeout(r, 2000))
}
const teardown = async () => {
await podman('rm', '-f', 'will-boot-test-service', 'will-boot-test-agent').catch(
() => undefined,
)
await podman('pod', 'rm', '-f', 'will-boot-test').catch(() => undefined)
}
if (serviceOk && agentOk) {
console.log('boot-test: both containers ready within deadline')
await teardown()
process.exit(0)
}
console.error(`boot-test: FAILED (service=${serviceOk}, agent=${agentOk})`)
await podman('logs', 'will-boot-test-service')
.then((r) => console.error(r.stdout))
.catch(() => undefined)
await podman('logs', 'will-boot-test-agent')
.then((r) => console.error(r.stdout))
.catch(() => undefined)
await teardown()
process.exit(1)
}
void main()