Skip to content

Commit ad71a99

Browse files
committed
fix(crabbox): default macos aws runs on demand
1 parent e4332f7 commit ad71a99

3 files changed

Lines changed: 122 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Docs: https://docs.openclaw.ai
1919
- Crabbox: let the wrapper find a sibling Crabbox checkout from linked Git worktrees so Codex worktrees can run remote gates without a PATH shim.
2020
- Scripts: tolerate the standard `--` option separator in shared script flag parsing so perf/test helpers accept package-manager argument forwarding.
2121
- Tests: preserve `--` passthrough arguments in live-media, live-shard, and extension batch harnesses so Vitest filters are not misread or silently ignored.
22+
- Crabbox: default AWS macOS runner requests to on-demand capacity so EC2 Mac proof commands do not fail on the unsupported Spot market default.
2223
- Tests: run upgrade-survivor config recipe commands through the Windows npm shim so native Windows package walks keep baseline config coverage.
2324
- Image tool: use bundled Anthropic media limits when resolving image compression policy without provider-runtime hooks.
2425
- Tests: fail the kitchen-sink RPC Docker walk when gateway RSS sampling is unavailable instead of silently disabling the per-process memory guard.

scripts/crabbox-wrapper.mjs

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,31 @@ function hasOption(commandArgs, name) {
387387
return false;
388388
}
389389

390+
function commandOptionEnd(commandArgs) {
391+
if (commandArgs[0] === "run") {
392+
return runCommandBounds(commandArgs).optionEnd;
393+
}
394+
const delimiter = commandArgs.indexOf("--");
395+
return delimiter >= 0 ? delimiter : commandArgs.length;
396+
}
397+
398+
function ensureAwsMacOnDemandMarket(commandArgs, providerName) {
399+
if (
400+
!["run", "warmup"].includes(commandArgs[0]) ||
401+
providerName !== "aws" ||
402+
optionValue(commandArgs, "--target") !== "macos" ||
403+
hasOption(commandArgs, "--market") ||
404+
hasOption(commandArgs, "--id")
405+
) {
406+
return commandArgs;
407+
}
408+
409+
const optionEnd = commandOptionEnd(commandArgs);
410+
const normalizedArgs = [...commandArgs];
411+
normalizedArgs.splice(optionEnd, 0, "--market", "on-demand");
412+
return normalizedArgs;
413+
}
414+
390415
const localPathRunOptions = new Set([
391416
"capture-stderr",
392417
"capture-stdout",
@@ -669,6 +694,7 @@ const providers = parseProvidersFromHelp(help.text);
669694
const displayBinary = binary === "crabbox" ? "crabbox" : relative(repoRoot, binary);
670695
const provider = selectedProvider(args);
671696
const commandProviderValue = commandProvider(args);
697+
const normalizedArgs = ensureAwsMacOnDemandMarket(args, provider);
672698

673699
console.error(
674700
`[crabbox] bin=${displayBinary} version=${version.text || "unknown"} provider=${provider || "unknown"} providers=${providers.join(",") || "unknown"}`,
@@ -712,8 +738,8 @@ if (provider === "blacksmith-testbox") {
712738
let childCwd = repoRoot;
713739
let cleanupChildCwd = () => {};
714740
let cleanupDone = false;
715-
if (shouldUseFullCheckoutForCleanSparseRemoteSync(args, provider)) {
716-
const runWords = runCommandArgs(args);
741+
if (shouldUseFullCheckoutForCleanSparseRemoteSync(normalizedArgs, provider)) {
742+
const runWords = runCommandArgs(normalizedArgs);
717743
const changedGateBase =
718744
isChangedGateCommand(runWords) && !headInRemoteRefs() ? mergeBaseForChangedGate() : "";
719745
const checkout = prepareFullCheckoutForSync({ changedGateBase });
@@ -737,9 +763,9 @@ function cleanupOnce() {
737763
cleanupChildCwd();
738764
}
739765

740-
const runtimeEntrypoint = commandRuntimeEntrypoint(runCommandArgs(args));
741-
if (args[0] === "run" && provider === "aws" && runtimeEntrypoint) {
742-
const id = optionValue(args, "--id");
766+
const runtimeEntrypoint = commandRuntimeEntrypoint(runCommandArgs(normalizedArgs));
767+
if (normalizedArgs[0] === "run" && provider === "aws" && runtimeEntrypoint) {
768+
const id = optionValue(normalizedArgs, "--id");
743769
const hydrate = id
744770
? `pnpm crabbox:hydrate -- --id ${id}`
745771
: "pnpm crabbox:warmup, then pnpm crabbox:hydrate -- --id <id>";
@@ -752,7 +778,7 @@ const childEnv = { ...process.env };
752778
if (
753779
isLocalContainerProvider(provider) &&
754780
!childEnv.CRABBOX_LOCAL_CONTAINER_DOCKER_SOCKET &&
755-
!hasOption(args, "--local-container-docker-socket")
781+
!hasOption(normalizedArgs, "--local-container-docker-socket")
756782
) {
757783
childEnv.CRABBOX_LOCAL_CONTAINER_DOCKER_SOCKET = "1";
758784
console.error(
@@ -763,15 +789,15 @@ if (
763789
isLocalContainerProvider(provider) &&
764790
process.platform !== "win32" &&
765791
!childEnv.CRABBOX_LOCAL_CONTAINER_WORK_ROOT &&
766-
!hasOption(args, "--local-container-work-root")
792+
!hasOption(normalizedArgs, "--local-container-work-root")
767793
) {
768794
childEnv.CRABBOX_LOCAL_CONTAINER_WORK_ROOT = "/tmp/openclaw-crabbox-docker-work";
769795
console.error(
770796
"[crabbox] provider=docker using short host-visible work root for OpenClaw Docker tests",
771797
);
772798
}
773799

774-
const childArgs = childCwd === repoRoot ? args : absolutizeLocalRunPaths(args);
800+
const childArgs = childCwd === repoRoot ? normalizedArgs : absolutizeLocalRunPaths(normalizedArgs);
775801
const childInvocation = spawnInvocation(binary, childArgs, childEnv, process.platform);
776802
const child = spawn(childInvocation.command, childInvocation.args, {
777803
cwd: childCwd,

test/scripts/crabbox-wrapper.test.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,93 @@ describe("scripts/crabbox-wrapper", () => {
112112
expect(result.stdout).toContain('"local-container"');
113113
});
114114

115+
it("defaults AWS macOS runs to on-demand capacity", () => {
116+
const result = runWrapper(
117+
"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
118+
["run", "--provider", "aws", "--target", "macos", "--", "echo ok"],
119+
);
120+
121+
expect(result.status).toBe(0);
122+
expect(parseFakeCrabboxOutput(result).args).toEqual([
123+
"run",
124+
"--provider",
125+
"aws",
126+
"--target",
127+
"macos",
128+
"--market",
129+
"on-demand",
130+
"--",
131+
"echo ok",
132+
]);
133+
});
134+
135+
it("defaults AWS macOS warmups to on-demand capacity", () => {
136+
const result = runWrapper(
137+
"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
138+
["warmup", "--provider", "aws", "--target", "macos"],
139+
);
140+
141+
expect(result.status).toBe(0);
142+
expect(parseFakeCrabboxOutput(result).args).toEqual([
143+
"warmup",
144+
"--provider",
145+
"aws",
146+
"--target",
147+
"macos",
148+
"--market",
149+
"on-demand",
150+
]);
151+
});
152+
153+
it("does not override explicit AWS macOS market or lease selections", () => {
154+
const helpText = "provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n";
155+
const explicitMarket = runWrapper(helpText, [
156+
"run",
157+
"--provider",
158+
"aws",
159+
"--target=macos",
160+
"--market",
161+
"spot",
162+
"--",
163+
"echo ok",
164+
]);
165+
const existingLease = runWrapper(helpText, [
166+
"run",
167+
"--provider",
168+
"aws",
169+
"--target",
170+
"macos",
171+
"--id",
172+
"cbx_existing",
173+
"--",
174+
"echo ok",
175+
]);
176+
177+
expect(explicitMarket.status).toBe(0);
178+
expect(parseFakeCrabboxOutput(explicitMarket).args).toEqual([
179+
"run",
180+
"--provider",
181+
"aws",
182+
"--target=macos",
183+
"--market",
184+
"spot",
185+
"--",
186+
"echo ok",
187+
]);
188+
expect(existingLease.status).toBe(0);
189+
expect(parseFakeCrabboxOutput(existingLease).args).toEqual([
190+
"run",
191+
"--provider",
192+
"aws",
193+
"--target",
194+
"macos",
195+
"--id",
196+
"cbx_existing",
197+
"--",
198+
"echo ok",
199+
]);
200+
});
201+
115202
it("finds a Crabbox checkout next to the Git common dir in linked worktrees", () => {
116203
const fakeWorkspaceParent = mkdtempSync(path.join(tmpdir(), "openclaw-linked-worktree-"));
117204
tempDirs.push(fakeWorkspaceParent);

0 commit comments

Comments
 (0)