fix: clean up live smoke blockers
This commit is contained in:
parent
189e03657b
commit
41ad14cc81
@ -20,6 +20,9 @@
|
||||
### Fixed
|
||||
|
||||
- Fixed `crabbox run --junit` so all-passing JUnit files record results instead of leaving the coordinator run stuck when the failure list is empty.
|
||||
- Fixed failed Blacksmith Testbox warmups so a printed `tbx_...` is stopped instead of being left ready after an upstream workflow error.
|
||||
- Fixed Worker deploy smoke to prefer the Crabbox-scoped Cloudflare token when it is present in the environment or local profile.
|
||||
- Fixed brokered Tailscale requests on coordinators without OAuth secrets so they fail as disabled instead of entering the auth-key minting path.
|
||||
- Fixed native Windows `--shell` runs so multi-statement PowerShell scripts keep their quotes instead of being re-parsed by a nested PowerShell process.
|
||||
- Removed the static macOS managed-login path so static host VNC cannot be mistaken for a Crabbox-created external instance.
|
||||
- Excluded macOS AppleDouble `._*` sidecar files from default sync manifests so native Windows archives do not transfer invalid TypeScript/package sidecars.
|
||||
|
||||
@ -223,6 +223,9 @@ func (a App) blacksmithWarmupLease(ctx context.Context, cfg Config, repo Repo, r
|
||||
cmd.Stdout = io.MultiWriter(a.Stdout, &output)
|
||||
cmd.Stderr = io.MultiWriter(a.Stderr, &output)
|
||||
if err := cmd.Run(); err != nil {
|
||||
if leaseID := parseBlacksmithID(output.String()); leaseID != "" {
|
||||
_ = a.blacksmithStopLease(ctx, cfg, leaseID)
|
||||
}
|
||||
return "", "", exit(exitCode(err), "blacksmith testbox warmup failed: %v", err)
|
||||
}
|
||||
leaseID := parseBlacksmithID(output.String())
|
||||
|
||||
@ -94,6 +94,39 @@ func TestBlacksmithWarmupFailureRemovesPendingKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlacksmithWarmupFailureStopsPrintedTestbox(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
t.Setenv("XDG_CONFIG_HOME", filepath.Join(home, ".config"))
|
||||
original := blacksmithCommandContext
|
||||
var stopped string
|
||||
blacksmithCommandContext = func(_ context.Context, _ string, args ...string) *exec.Cmd {
|
||||
if len(args) >= 3 && args[0] == "testbox" && args[1] == "stop" {
|
||||
for i, arg := range args {
|
||||
if arg == "--id" && i+1 < len(args) {
|
||||
stopped = args[i+1]
|
||||
}
|
||||
}
|
||||
return exec.Command("sh", "-c", "exit 0")
|
||||
}
|
||||
return exec.Command("sh", "-c", "printf 'queued tbx_leaked123\\n'; exit 1")
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
blacksmithCommandContext = original
|
||||
})
|
||||
|
||||
cfg := baseConfig()
|
||||
cfg.Blacksmith.Workflow = ".github/workflows/testbox.yml"
|
||||
app := App{Stdout: io.Discard, Stderr: io.Discard}
|
||||
_, _, err := app.blacksmithWarmupLease(context.Background(), cfg, Repo{Root: "/repo"}, false)
|
||||
if err == nil {
|
||||
t.Fatal("expected warmup failure")
|
||||
}
|
||||
if stopped != "tbx_leaked123" {
|
||||
t.Fatalf("stopped=%q, want tbx_leaked123", stopped)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlacksmithOneShotRunRemovesClaimAfterStop(t *testing.T) {
|
||||
home := t.TempDir()
|
||||
t.Setenv("HOME", home)
|
||||
|
||||
@ -4,6 +4,36 @@ set -euo pipefail
|
||||
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
CRABBOX_BIN="${CRABBOX_BIN:-$ROOT/bin/crabbox}"
|
||||
|
||||
profile_export() {
|
||||
local name="$1" file line value
|
||||
for file in "$HOME/.profile" "$HOME/.zprofile"; do
|
||||
[[ -r "$file" ]] || continue
|
||||
line="$(grep -E "^export ${name}=" "$file" | tail -n 1 || true)"
|
||||
[[ -n "$line" ]] || continue
|
||||
value="${line#export ${name}=}"
|
||||
value="${value%\"}"
|
||||
value="${value#\"}"
|
||||
value="${value%\'}"
|
||||
value="${value#\'}"
|
||||
printf '%s' "$value"
|
||||
return 0
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
if [[ -z "${CRABBOX_CLOUDFLARE_API_TOKEN:-}" ]]; then
|
||||
CRABBOX_CLOUDFLARE_API_TOKEN="$(profile_export CRABBOX_CLOUDFLARE_API_TOKEN || true)"
|
||||
fi
|
||||
if [[ -z "${CRABBOX_CLOUDFLARE_ACCOUNT_ID:-}" ]]; then
|
||||
CRABBOX_CLOUDFLARE_ACCOUNT_ID="$(profile_export CRABBOX_CLOUDFLARE_ACCOUNT_ID || true)"
|
||||
fi
|
||||
if [[ -n "${CRABBOX_CLOUDFLARE_API_TOKEN:-}" ]]; then
|
||||
export CLOUDFLARE_API_TOKEN="$CRABBOX_CLOUDFLARE_API_TOKEN"
|
||||
fi
|
||||
if [[ -n "${CRABBOX_CLOUDFLARE_ACCOUNT_ID:-}" ]]; then
|
||||
export CLOUDFLARE_ACCOUNT_ID="$CRABBOX_CLOUDFLARE_ACCOUNT_ID"
|
||||
fi
|
||||
|
||||
run() {
|
||||
printf '+'
|
||||
printf ' %q' "$@"
|
||||
|
||||
@ -7,7 +7,13 @@ export interface TailscaleKeyRequest {
|
||||
}
|
||||
|
||||
export function tailscaleAllowed(env: Env): boolean {
|
||||
return env.CRABBOX_TAILSCALE_ENABLED !== "0";
|
||||
if (env.CRABBOX_TAILSCALE_ENABLED === "0") {
|
||||
return false;
|
||||
}
|
||||
if (env.CRABBOX_TAILSCALE_ENABLED === "1") {
|
||||
return true;
|
||||
}
|
||||
return Boolean(env.CRABBOX_TAILSCALE_CLIENT_ID && env.CRABBOX_TAILSCALE_CLIENT_SECRET);
|
||||
}
|
||||
|
||||
export function tailscaleDefaultTags(env: Env): string[] {
|
||||
|
||||
@ -217,6 +217,29 @@ describe("fleet lease identity and idle", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("reports brokered Tailscale disabled when OAuth secrets are absent", async () => {
|
||||
const fleet = testFleet(new MemoryStorage(), { hetzner: fakeProvider() });
|
||||
const create = await fleet.fetch(
|
||||
request("POST", "/v1/leases", {
|
||||
headers: {
|
||||
"x-crabbox-owner": "peter@example.com",
|
||||
"x-crabbox-org": "openclaw",
|
||||
},
|
||||
body: {
|
||||
leaseID: "cbx_abcdef123456",
|
||||
provider: "hetzner",
|
||||
tailscale: true,
|
||||
sshPublicKey: "ssh-ed25519 test",
|
||||
},
|
||||
}),
|
||||
);
|
||||
expect(create.status).toBe(403);
|
||||
await expect(create.json()).resolves.toMatchObject({
|
||||
error: "tailscale_disabled",
|
||||
message: "Tailscale is disabled for this coordinator",
|
||||
});
|
||||
});
|
||||
|
||||
it("passes the Cloudflare request source IP as AWS SSH ingress CIDR", async () => {
|
||||
let awsCIDRs: string[] = [];
|
||||
const fleet = testFleet(new MemoryStorage(), {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user