mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix: fail crabbox lease-claim refusals (#104789)
This commit is contained in:
committed by
GitHub
parent
d1f614c9e6
commit
5c7e1341ab
+31
-10
@@ -936,6 +936,21 @@ function blacksmithTestboxPrivateKeyPath(id) {
|
||||
return resolve(crabboxConfigDir(), "testboxes", id, "id_ed25519");
|
||||
}
|
||||
|
||||
// Crabbox claims bind raw Testbox ids to one repo before remote execution.
|
||||
// Check the same sidecar so a dependency exit bug cannot make refusal green.
|
||||
function blacksmithTestboxClaimRepoRoot(id) {
|
||||
const configuredStateRoot = process.env.XDG_STATE_HOME?.trim();
|
||||
const stateDir = configuredStateRoot
|
||||
? resolve(configuredStateRoot, "crabbox")
|
||||
: resolve(crabboxConfigDir(), "state");
|
||||
const claimPath = resolve(stateDir, "claims", `${id}.json`);
|
||||
if (!pathExists(claimPath)) {
|
||||
return "";
|
||||
}
|
||||
const claim = JSON.parse(readFileSync(claimPath, "utf8"));
|
||||
return typeof claim.repoRoot === "string" ? claim.repoRoot : "";
|
||||
}
|
||||
|
||||
function enforceCrabboxOwnedBlacksmithLease(commandArgs) {
|
||||
if (commandArgs[0] !== "run") {
|
||||
return;
|
||||
@@ -949,18 +964,24 @@ function enforceCrabboxOwnedBlacksmithLease(commandArgs) {
|
||||
}
|
||||
|
||||
const keyPath = blacksmithTestboxPrivateKeyPath(id);
|
||||
if (pathExists(keyPath)) {
|
||||
return;
|
||||
if (!pathExists(keyPath)) {
|
||||
console.error(
|
||||
[
|
||||
`[crabbox] provider=blacksmith-testbox --id ${id} has no Crabbox SSH key at ${userDisplayPath(keyPath)}.`,
|
||||
"[crabbox] create reusable Testboxes through Crabbox before reusing them: node scripts/crabbox-wrapper.mjs warmup --provider blacksmith-testbox --idle-timeout 90m",
|
||||
"[crabbox] direct `blacksmith testbox warmup` leases can be used with `blacksmith testbox run`, but Crabbox cannot sync or run them by id.",
|
||||
].join("\n"),
|
||||
);
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
console.error(
|
||||
[
|
||||
`[crabbox] provider=blacksmith-testbox --id ${id} has no Crabbox SSH key at ${userDisplayPath(keyPath)}.`,
|
||||
"[crabbox] create reusable Testboxes through Crabbox before reusing them: node scripts/crabbox-wrapper.mjs warmup --provider blacksmith-testbox --idle-timeout 90m",
|
||||
"[crabbox] direct `blacksmith testbox warmup` leases can be used with `blacksmith testbox run`, but Crabbox cannot sync or run them by id.",
|
||||
].join("\n"),
|
||||
);
|
||||
process.exit(2);
|
||||
const claimRepoRoot = blacksmithTestboxClaimRepoRoot(id);
|
||||
if (claimRepoRoot && claimRepoRoot !== repoRoot && !hasOption(commandArgs, "--reclaim")) {
|
||||
console.error(
|
||||
`[crabbox] lease ${id} is claimed by repo ${claimRepoRoot}; use --reclaim to claim it for ${repoRoot}`,
|
||||
);
|
||||
process.exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
function preserveTemporaryCrabboxRuns() {
|
||||
|
||||
@@ -798,6 +798,42 @@ describe("scripts/crabbox-wrapper", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("fails before reuse when a Blacksmith Testbox is claimed by another repo", () => {
|
||||
const home = mkdtempSync(path.join(tmpdir(), "openclaw-crabbox-home-"));
|
||||
tempDirs.push(home);
|
||||
const id = "tbx_claimed";
|
||||
const keyPath = path.join(testCrabboxConfigDir(home), "testboxes", id, "id_ed25519");
|
||||
mkdirSync(path.dirname(keyPath), { recursive: true });
|
||||
writeFileSync(keyPath, "fake test key\n", "utf8");
|
||||
const stateRoot = path.join(home, ".local", "state");
|
||||
const claimPath = path.join(stateRoot, "crabbox", "claims", `${id}.json`);
|
||||
mkdirSync(path.dirname(claimPath), { recursive: true });
|
||||
writeFileSync(
|
||||
claimPath,
|
||||
`${JSON.stringify({ leaseID: id, repoRoot: "/tmp/other-repo" })}\n`,
|
||||
"utf8",
|
||||
);
|
||||
|
||||
const result = runWrapper(
|
||||
"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
|
||||
["run", "--provider", "blacksmith-testbox", "--id", id, "--", "echo ok"],
|
||||
{ env: { ...testHomeEnv(home), XDG_STATE_HOME: stateRoot } },
|
||||
);
|
||||
|
||||
expect(result.status).toBe(2);
|
||||
expect(result.stdout).toBe("");
|
||||
expect(result.stderr).toContain(`lease ${id} is claimed by repo /tmp/other-repo`);
|
||||
expect(result.stderr).toContain(`use --reclaim to claim it for ${repoRoot}`);
|
||||
|
||||
const reclaimed = runWrapper(
|
||||
"provider: hetzner, aws, local-container, blacksmith-testbox, or cloudflare\n",
|
||||
["run", "--provider", "blacksmith-testbox", "--id", id, "--reclaim", "--", "echo ok"],
|
||||
{ env: { ...testHomeEnv(home), XDG_STATE_HOME: stateRoot } },
|
||||
);
|
||||
expect(reclaimed.status).toBe(0);
|
||||
expect(parseFakeCrabboxOutput(reclaimed).args).toContain("--reclaim");
|
||||
});
|
||||
|
||||
it("lets Crabbox resolve reusable Testbox slugs", () => {
|
||||
const home = mkdtempSync(path.join(tmpdir(), "openclaw-crabbox-home-"));
|
||||
tempDirs.push(home);
|
||||
|
||||
Reference in New Issue
Block a user