@botbuddy/cli 1.43.0 → 1.43.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/stack.mjs +46 -1
package/package.json
CHANGED
package/src/stack.mjs
CHANGED
|
@@ -60,6 +60,13 @@ const CALLBACK_PORT_REMOTE_REFUSAL =
|
|
|
60
60
|
"(pre-forward GatewayPorts probe). Use --local-only for a run that needs a callback port.";
|
|
61
61
|
export const DEFAULT_RECEIPT_MAX_BYTES = 10240;
|
|
62
62
|
export const DEFAULT_TIMEOUT_SEC = 3600;
|
|
63
|
+
/**
|
|
64
|
+
* BOT-2154: how long `stack up --local-exec` lets `supabase start` run before it gives up and
|
|
65
|
+
* releases the lease itself (`--provision-timeout` overrides). Deliberately below the server's
|
|
66
|
+
* 1200 s `local_exec_provision_ttl_secs` backstop, so the CLI's own clean `stack done` wins the
|
|
67
|
+
* race against the reaper.
|
|
68
|
+
*/
|
|
69
|
+
export const LOCAL_EXEC_PROVISION_TIMEOUT_SEC = 900;
|
|
63
70
|
/** BOT-2230: the bounds the control plane enforces on an owner place hold (hold_stack_lease_place). */
|
|
64
71
|
export const HOLD_ON_TIMEOUT_MIN_SEC = 60;
|
|
65
72
|
export const HOLD_ON_TIMEOUT_MAX_SEC = 14400;
|
|
@@ -122,6 +129,10 @@ ${bold("up OPTIONS")}
|
|
|
122
129
|
deadline (exit 2) and a failed wait (its own exit code) never retry.
|
|
123
130
|
--local-exec FALLBACK (no Helper): run 'supabase start' in an ISOLATED --stack-path
|
|
124
131
|
stack and self-activate. Refused at the worktree root (shared stack).
|
|
132
|
+
--provision-timeout N LOCAL-EXEC: seconds 'supabase start' may run (default ${LOCAL_EXEC_PROVISION_TIMEOUT_SEC}). On
|
|
133
|
+
timeout up runs 'stack done --local-exec' itself and exits 6 with
|
|
134
|
+
park_reason provision_timeout (BOT-2154). The server also fails a local-exec
|
|
135
|
+
lease still provisioning after local_exec_provision_ttl_secs (default 1200).
|
|
125
136
|
Refused (exit 4, ENGINE_PUBLISHES_BEYOND_LOOPBACK) when the Docker
|
|
126
137
|
engine would publish the stack's ports beyond loopback (BOT-2146).
|
|
127
138
|
--docker-context <name> Explicit Docker context for the mandatory local preflight
|
|
@@ -1851,7 +1862,16 @@ export function localProvision(opts, dockerTarget, execution, spawn = spawnSync,
|
|
|
1851
1862
|
const url = resolveIsolatedStackApiUrl(stackDir, env);
|
|
1852
1863
|
const spawnEnv = { ...dockerEnvForTarget(dockerTarget, env), VITE_SUPABASE_URL: url };
|
|
1853
1864
|
process.stderr.write(`${yellow("⚠ LOCAL-EXEC FALLBACK")} — no BotBuddy Helper; running ${bold("supabase start")} in ${stackDir} (VITE_SUPABASE_URL=${url}).\n`);
|
|
1854
|
-
|
|
1865
|
+
// BOT-2154: never an unbounded start — a hung `supabase start` held the host slot for hours.
|
|
1866
|
+
const timeoutSec = opts?.provisionTimeout ?? LOCAL_EXEC_PROVISION_TIMEOUT_SEC;
|
|
1867
|
+
const start = spawn("supabase", ["start", "--workdir", stackDir], {
|
|
1868
|
+
encoding: "utf8", env: spawnEnv, timeout: timeoutSec * 1000, killSignal: "SIGTERM",
|
|
1869
|
+
});
|
|
1870
|
+
if (start.error?.code === "ETIMEDOUT") {
|
|
1871
|
+
const timedOut = new Error(`supabase start did not finish within ${timeoutSec}s (--provision-timeout); stopping it and releasing the lease`);
|
|
1872
|
+
timedOut.code = "PROVISION_TIMEOUT";
|
|
1873
|
+
throw timedOut;
|
|
1874
|
+
}
|
|
1855
1875
|
if (start.status !== 0) {
|
|
1856
1876
|
throw new Error(`supabase start failed (${start.status}): ${(start.stderr || start.stdout || "").slice(0, 400)}`);
|
|
1857
1877
|
}
|
|
@@ -1942,11 +1962,21 @@ function emit(receipt, opts, code) {
|
|
|
1942
1962
|
|
|
1943
1963
|
// ── command orchestration ────────────────────────────────────────────────────
|
|
1944
1964
|
|
|
1965
|
+
/** BOT-2154: run `stack done` in-process and capture its receipt instead of printing it, so
|
|
1966
|
+
* `stack up` still emits exactly one receipt. */
|
|
1967
|
+
async function runLocalDone(leaseId, opts, deps = {}) {
|
|
1968
|
+
let receipt = null;
|
|
1969
|
+
const exitCode = await cmdDone(leaseId, opts, { ...deps, emitResult: (r, _o, code) => { receipt = r; return code; } });
|
|
1970
|
+
return { exitCode, receipt };
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1945
1973
|
export async function cmdUp(opts, {
|
|
1946
1974
|
runPreflight = runLocalExecPreflight,
|
|
1947
1975
|
callTool = callToolJson,
|
|
1948
1976
|
authProvider = stackAuthHeader,
|
|
1949
1977
|
localProvisionFn = localProvision,
|
|
1978
|
+
// BOT-2154: the self-release after a timed-out local start (`stack done --local-exec`).
|
|
1979
|
+
localDoneFn = null,
|
|
1950
1980
|
waitFn = waitForLease,
|
|
1951
1981
|
emitResult = emit,
|
|
1952
1982
|
machineUuidFn = machineUuid,
|
|
@@ -2278,6 +2308,21 @@ export async function cmdUp(opts, {
|
|
|
2278
2308
|
try {
|
|
2279
2309
|
conn = connectionWithDockerTarget(localProvisionFn(opts, localDockerTarget, execution), localDockerTarget);
|
|
2280
2310
|
} catch (e) {
|
|
2311
|
+
if (e?.code === "PROVISION_TIMEOUT") {
|
|
2312
|
+
// BOT-2154: a bounded start that ran out of time. Release the lease ourselves —
|
|
2313
|
+
// `stack done --local-exec` stops whatever the start left behind and reaps the lease
|
|
2314
|
+
// — instead of leaving it provisioning for the server's backstop to find.
|
|
2315
|
+
const done = await (localDoneFn ?? ((id, doneOpts) => runLocalDone(id, doneOpts, { callTool, authProvider })))(
|
|
2316
|
+
leaseId, { ...opts, localExec: true, disposition: "destroy", json: false });
|
|
2317
|
+
const doneReceipt = done?.receipt ?? {};
|
|
2318
|
+
const cleaned = done?.exitCode === 0;
|
|
2319
|
+
return emitResult(buildReceipt({
|
|
2320
|
+
command: "up", outcome: "timeout", code: "PROVISION_TIMEOUT", park_reason: "provision_timeout",
|
|
2321
|
+
lease_id: leaseId, slot, error: e.message, cleanup: cleaned,
|
|
2322
|
+
done: { outcome: doneReceipt.outcome ?? null, state: doneReceipt.state ?? null, exit_code: done?.exitCode ?? null },
|
|
2323
|
+
...(cleaned ? {} : { cleanup_error: doneReceipt.error ?? `stack done --local-exec exited ${done?.exitCode}` }),
|
|
2324
|
+
}), opts, EXIT.LEASE_FAILED);
|
|
2325
|
+
}
|
|
2281
2326
|
// Once the local provisioner has run, `supabase start` may have created
|
|
2282
2327
|
// (or fully started) containers even on a nonzero exit or a status-parse
|
|
2283
2328
|
// failure. Cancelling here would reap the lease and free the slot while
|