What version of HAPI is running?
main (verified at 994a820)
What platform is your computer?
Linux x86_64 (also reproduces on macOS — same mechanism)
What issue are you seeing?
cli/vitest.config.ts spreads the whole shell environment into every test worker via env: { ...process.env, ...testEnv }. Any contributor who uses the HAPI CLI day-to-day has CLI_API_TOKEN and HAPI_API_URL exported by their shell (that is how the CLI authenticates against their real hub). The moment they run cd cli && pnpm test, runner.integration.test.ts connects to that real hub — for many of us that is the production hub.
This is silent: the suite passes, but in the process it has written rows to the prod hub's database (sessions / runners / heartbeats) and the contributor may not even realise it ran against prod until they see ghost sessions in the web UI.
Repro
- Start from a fresh
tiann/hapi main checkout (commit 994a820).
- In your shell, have the same env you normally use to talk to your real HAPI hub:
export CLI_API_TOKEN=<your real token>
export HAPI_API_URL=https://hapi.your-domain.tld
cd cli && pnpm test
- Tail your prod hub's logs / open the web UI's sessions list while the suite runs.
Expected: integration tests run against a throwaway hub created for the test process and produce zero side effects on any real hub.
Actual: runner.integration.test.ts authenticates against HAPI_API_URL, registers a runner, writes session rows, and emits heartbeats — all against the real hub. After the suite finishes you can see fresh runner_id entries and a short-lived session whose workspace path is whatever the test fixture used.
Root cause
cli/vitest.config.ts:5-31 does:
import dotenv from 'dotenv'
const testEnv = dotenv.config({ path: '.env.integration-test' }).parsed
export default defineConfig({
test: {
// ...
env: {
...process.env,
...testEnv,
}
},
})
...process.env injects the contributor's real CLI_API_TOKEN and HAPI_API_URL into the workers. .env.integration-test only exists locally for contributors who happen to know about it (it is not in the repo); CI generates it in .github/workflows/test.yml with HAPI_API_URL=http://localhost:3006 and a placeholder token. So on CI the leak is harmless (localhost is dead → tests skip / no-op), but on a real contributor's machine the leak hits prod.
cli/src/runner/runner.integration.test.ts then takes those env values at face value and runs against whichever hub they point to.
Suggested fix
Spin up a throwaway hub on a random port before the test suite, write its URL + token to a config file, and have a per-worker setup file read that config and overwrite HAPI_API_URL / CLI_API_TOKEN / HAPI_HOME before any test module loads configuration. That keeps the integration tests honest (they still talk to a real hub process, just one we own and tear down) while guaranteeing they cannot touch anything outside /tmp.
PR #734 already implements exactly this. It:
- replaces the
env: { ...process.env } block with globalSetup + setupFiles,
- starts a temp hub via
bun run hub/src/index.ts on a free port with isolated HAPI_HOME and sanitized env (no TELEGRAM_BOT_TOKEN, no inherited DB_PATH),
- fails closed when the isolated config file is missing (so a stale-cache scenario can never silently fall back to ambient creds),
- handles cross-platform bun lookup and waits for the hub child process to exit before
rmSync of the temp dir.
All three HAPI Bot review rounds have been addressed; the latest review reports no findings, CI is green, and the branch is mergeable.
Workaround
Until #734 lands, contributors have to scrub the env every time:
tmp_home=$(mktemp -d /tmp/hapi-test-home.XXXXXX)
env -u HAPI_API_URL -u CLI_API_TOKEN -u HAPI_CLI_EXECUTABLE \
HAPI_HOME="$tmp_home" \
npm exec -- bun run test
This works, but every new contributor has to learn it the hard way, and the failure mode (silently writing to prod) is exactly the kind of thing that should not depend on tribal knowledge.
Additional information
Discovered the first time I ran pnpm test after configuring my shell to use my real hub. Fix lives in #734.
What version of HAPI is running?
main (verified at 994a820)
What platform is your computer?
Linux x86_64 (also reproduces on macOS — same mechanism)
What issue are you seeing?
cli/vitest.config.tsspreads the whole shell environment into every test worker viaenv: { ...process.env, ...testEnv }. Any contributor who uses the HAPI CLI day-to-day hasCLI_API_TOKENandHAPI_API_URLexported by their shell (that is how the CLI authenticates against their real hub). The moment they runcd cli && pnpm test,runner.integration.test.tsconnects to that real hub — for many of us that is the production hub.This is silent: the suite passes, but in the process it has written rows to the prod hub's database (sessions / runners / heartbeats) and the contributor may not even realise it ran against prod until they see ghost sessions in the web UI.
Repro
tiann/hapimaincheckout (commit 994a820).cd cli && pnpm testExpected: integration tests run against a throwaway hub created for the test process and produce zero side effects on any real hub.
Actual:
runner.integration.test.tsauthenticates againstHAPI_API_URL, registers a runner, writes session rows, and emits heartbeats — all against the real hub. After the suite finishes you can see freshrunner_identries and a short-lived session whose workspace path is whatever the test fixture used.Root cause
cli/vitest.config.ts:5-31does:...process.envinjects the contributor's realCLI_API_TOKENandHAPI_API_URLinto the workers..env.integration-testonly exists locally for contributors who happen to know about it (it is not in the repo); CI generates it in.github/workflows/test.ymlwithHAPI_API_URL=http://localhost:3006and a placeholder token. So on CI the leak is harmless (localhost is dead → tests skip / no-op), but on a real contributor's machine the leak hits prod.cli/src/runner/runner.integration.test.tsthen takes those env values at face value and runs against whichever hub they point to.Suggested fix
Spin up a throwaway hub on a random port before the test suite, write its URL + token to a config file, and have a per-worker setup file read that config and overwrite
HAPI_API_URL/CLI_API_TOKEN/HAPI_HOMEbefore any test module loadsconfiguration. That keeps the integration tests honest (they still talk to a real hub process, just one we own and tear down) while guaranteeing they cannot touch anything outside/tmp.PR #734 already implements exactly this. It:
env: { ...process.env }block withglobalSetup+setupFiles,bun run hub/src/index.tson a free port with isolatedHAPI_HOMEand sanitized env (noTELEGRAM_BOT_TOKEN, no inheritedDB_PATH),rmSyncof the temp dir.All three HAPI Bot review rounds have been addressed; the latest review reports no findings, CI is green, and the branch is mergeable.
Workaround
Until #734 lands, contributors have to scrub the env every time:
This works, but every new contributor has to learn it the hard way, and the failure mode (silently writing to prod) is exactly the kind of thing that should not depend on tribal knowledge.
Additional information
Discovered the first time I ran
pnpm testafter configuring my shell to use my real hub. Fix lives in #734.