@botbuddy/cli 1.21.1 → 1.22.0
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 +19 -0
package/package.json
CHANGED
package/src/stack.mjs
CHANGED
|
@@ -31,6 +31,7 @@ import { callToolJson } from "./api.mjs";
|
|
|
31
31
|
import { SERVER_URL, getConfig } from "./config.mjs";
|
|
32
32
|
import { resolveOwnerToken, resolveAgentKey } from "./cli-credentials.mjs";
|
|
33
33
|
import { runDockerCommand, runDockerWorkflow } from "./docker-hygiene.mjs";
|
|
34
|
+
import { machineUuid } from "./machine-id.mjs";
|
|
34
35
|
import { bold, dim, yellow } from "./utils.mjs";
|
|
35
36
|
|
|
36
37
|
export const STACK_SCHEMA_VERSION = 1;
|
|
@@ -667,6 +668,7 @@ export async function cmdUp(opts, {
|
|
|
667
668
|
localProvisionFn = localProvision,
|
|
668
669
|
waitFn = waitForLease,
|
|
669
670
|
emitResult = emit,
|
|
671
|
+
machineUuidFn = machineUuid,
|
|
670
672
|
} = {}) {
|
|
671
673
|
let slot;
|
|
672
674
|
try { slot = deriveSlot(opts); } catch (e) {
|
|
@@ -696,6 +698,13 @@ export async function cmdUp(opts, {
|
|
|
696
698
|
const auth = await authProvider();
|
|
697
699
|
if (!auth) return emitResult(buildReceipt({ command: "up", outcome: "error", error: "not authenticated — run `botbuddy login`" }), opts, EXIT.AUTH);
|
|
698
700
|
|
|
701
|
+
// BOT-1585: co-location dispatches the lease to the Helper enrolled for THIS
|
|
702
|
+
// physical machine (hardware id), since a hostname is not machine-unique. The
|
|
703
|
+
// server requires it; fail fast with an actionable message if it can't be read.
|
|
704
|
+
const hardwareUuid = machineUuidFn();
|
|
705
|
+
if (!hardwareUuid) {
|
|
706
|
+
return emitResult(buildReceipt({ command: "up", outcome: "error", code: "MACHINE_UUID_REQUIRED", error: "could not determine this machine's hardware id (needed to dispatch the stack lease to the right machine)" }), opts, EXIT.BACKEND);
|
|
707
|
+
}
|
|
699
708
|
const req = await callTool("request_stack_lease", {
|
|
700
709
|
slot, host_key: opts.host || undefined, repo: opts.repo || undefined,
|
|
701
710
|
ticket_id: opts.ticket || undefined, ticket_url: opts.ticketUrl || undefined,
|
|
@@ -703,6 +712,7 @@ export async function cmdUp(opts, {
|
|
|
703
712
|
purpose: opts.purpose || undefined, idle_ttl_secs: opts.idleTtl ?? undefined,
|
|
704
713
|
stack_path: execution.stackPath,
|
|
705
714
|
worktree_root: execution.worktreeRoot,
|
|
715
|
+
machine_uuid: hardwareUuid,
|
|
706
716
|
});
|
|
707
717
|
if (!req.ok) {
|
|
708
718
|
return req.auth
|
|
@@ -1046,6 +1056,7 @@ export async function runStackLifecycle(opts, childArgv, adapters = {}) {
|
|
|
1046
1056
|
release: (leaseId, signal) => callToolJson("release_stack_lease", { lease_id: leaseId, disposition: "destroy" }, { signal }),
|
|
1047
1057
|
};
|
|
1048
1058
|
const auth = adapters.auth ?? await stackAuthHeader();
|
|
1059
|
+
const machineUuidFn = adapters.machineUuidFn ?? machineUuid;
|
|
1049
1060
|
const wait = adapters.wait ?? ((leaseId, done, failed, options) => waitForLease(leaseId, done, failed, options));
|
|
1050
1061
|
// nosemgrep: javascript.lang.security.detect-child-process.detect-child-process -- validated executable + argv only; shell is never used.
|
|
1051
1062
|
const startChild = adapters.startChild ?? ((argv, env, cwd) => spawn(argv[0], argv.slice(1), { cwd, env, stdio: "inherit", detached: true }));
|
|
@@ -1122,6 +1133,13 @@ export async function runStackLifecycle(opts, childArgv, adapters = {}) {
|
|
|
1122
1133
|
|
|
1123
1134
|
try {
|
|
1124
1135
|
if (!auth) return { exitCode: EXIT.AUTH, outcome: "error", error: "not authenticated — run botbuddy profile setup botbuddy-dev" };
|
|
1136
|
+
// BOT-1585: request_stack_lease requires this machine's hardware id so the lease
|
|
1137
|
+
// dispatches to the machine the worktree was registered on. `stack run` builds its
|
|
1138
|
+
// own payload (separate from `cmdUp`), so it must send it too.
|
|
1139
|
+
const hardwareUuid = machineUuidFn();
|
|
1140
|
+
if (!hardwareUuid) {
|
|
1141
|
+
return { exitCode: EXIT.BACKEND, outcome: "error", error: "could not determine this machine's hardware id (needed to dispatch the stack lease to the right machine)" };
|
|
1142
|
+
}
|
|
1125
1143
|
const slot = deriveSlot(opts);
|
|
1126
1144
|
const execution = resolveStackPath(process.cwd(), opts.stackPath);
|
|
1127
1145
|
const request = await api.request({
|
|
@@ -1129,6 +1147,7 @@ export async function runStackLifecycle(opts, childArgv, adapters = {}) {
|
|
|
1129
1147
|
ticket_url: opts.ticketUrl || undefined, pr_id: opts.prId || undefined, pr_url: opts.prUrl || undefined,
|
|
1130
1148
|
purpose: opts.purpose || "stack run", idle_ttl_secs: opts.idleTtl ?? undefined,
|
|
1131
1149
|
stack_path: execution.stackPath, worktree_root: execution.worktreeRoot,
|
|
1150
|
+
machine_uuid: hardwareUuid,
|
|
1132
1151
|
});
|
|
1133
1152
|
if (!request?.ok) return { exitCode: request?.auth ? EXIT.AUTH : EXIT.BACKEND, outcome: "error", error: request?.error || "lease request failed" };
|
|
1134
1153
|
if (!request.data?.success) return { exitCode: EXIT.BACKEND, outcome: "error", error: request.data?.message || request.data?.code || "lease request refused" };
|