mirror of
https://github.com/garrytan/gbrain.git
synced 2026-07-30 03:12:32 +00:00
fix(autopilot): derive bun runtime dir for cron PATH; detect wrapper in --status (#3397)
Two robustness fixes to `gbrain autopilot --install`/`--status`, hardening #3305. 1. Universal bun PATH (extends #3305). The install-generated wrapper (~/.gbrain/autopilot-run.sh) execs the `#!/usr/bin/env bun` gbrain shim, so bun must be on PATH under cron/systemd/launchd's minimal env. #3305 hardcodes `$HOME/.bun/bin`, which only covers the default bun.sh installer. Hosts where bun lives elsewhere (Homebrew, npm -g, Docker /usr/local/bin, custom BUN_INSTALL, nix) still die with `env: bun: No such file or directory`, leaving a stale lock that stalls the nightly cycle. Fix: bake the dir of the actually-running bun (dirname(process.execPath)) onto PATH at install time, ~/.bun/bin kept as fallback, single-quote-escaped, empty execPath guarded. 2. `--status` false negative. showStatus() checked crontab.includes('gbrain autopilot'), but --install writes a line calling the wrapper `.../autopilot-run.sh` — no such substring. So `--status` reported installed:false on every wrapper-based Linux host. Fix: also match 'autopilot-run.sh'. Tests: test/autopilot-install.test.ts — universal-form + runtime-derivation + wrapper-detection assertions (fail-before/pass-after verified).
This commit is contained in:
@@ -115,13 +115,30 @@ describe('autopilot wrapper script — bun PATH export (v0.42.x regression)', ()
|
||||
test('wrapper exports ~/.bun/bin onto PATH before the exec', async () => {
|
||||
const { readFileSync } = await import('fs');
|
||||
const src = readFileSync('src/commands/autopilot.ts', 'utf8');
|
||||
// The export line must appear inside the writeWrapperScript heredoc.
|
||||
expect(src).toMatch(/export\s+PATH="\$HOME\/\.bun\/bin:\$PATH"/);
|
||||
// The export line must appear inside the writeWrapperScript heredoc, now
|
||||
// prefixed with the runtime dir derived at install time (universal), with
|
||||
// ~/.bun/bin retained as a fallback.
|
||||
expect(src).toMatch(/export PATH=\$\{runtimePathPrefix\}"\$HOME\/\.bun\/bin:\$PATH"/);
|
||||
// The runtime dir is derived from the actually-running bun (covers Homebrew /
|
||||
// npm -g / Docker / custom BUN_INSTALL / nix), not hardcoded to ~/.bun/bin.
|
||||
expect(src).toMatch(/const runtimeDir = dirname\(process\.execPath/);
|
||||
// The export must precede the exec line, otherwise env never sees it.
|
||||
const exportIdx = src.search(/export\s+PATH="\$HOME\/\.bun\/bin/);
|
||||
const exportIdx = src.search(/export PATH=\$\{runtimePathPrefix\}/);
|
||||
const execIdx = src.search(/exec\s+'\${safeGbrainPath}'/);
|
||||
expect(exportIdx).toBeGreaterThan(0);
|
||||
expect(execIdx).toBeGreaterThan(0);
|
||||
expect(exportIdx).toBeLessThan(execIdx);
|
||||
});
|
||||
});
|
||||
|
||||
// Status detection must recognize the wrapper-based cron line that --install
|
||||
// actually writes (…/autopilot-run.sh), not just the legacy `gbrain autopilot`
|
||||
// invocation — otherwise `--status` reports installed:false on every Linux host
|
||||
// that installed via the wrapper indirection.
|
||||
describe('autopilot showStatus — wrapper-path detection', () => {
|
||||
test('status detects the autopilot-run.sh wrapper line', async () => {
|
||||
const { readFileSync } = await import('fs');
|
||||
const src = readFileSync('src/commands/autopilot.ts', 'utf8');
|
||||
expect(src).toMatch(/crontab\.includes\('autopilot-run\.sh'\)/);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user