Skip to content

Commit 08afcc4

Browse files
committed
fix: harden live smoke preflights
1 parent 0069ed6 commit 08afcc4

5 files changed

Lines changed: 271 additions & 37 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
### Fixed
4343

4444
- Fixed code-scanning findings in container command execution, Worker sanitizers, docs link/build helpers, and JSON error responses.
45+
- Fixed live smoke scripts so provider-specific missing workflow, snapshot, CLI, Python client, or Semaphore config prerequisites fail before allocating resources, and added Sprites coverage to the live provider smoke.
46+
- Fixed live coordinator auth smoke so GitHub-authenticated coordinator identities are accepted and Cloudflare Access credential gaps print an actionable prerequisite error.
4547
- Fixed raw SSH-provider JS package command failures so Crabbox probes obvious `pnpm`, `npm`, `node`, `corepack`, `yarn`, and `bun` entrypoints before syncing and fails with hydration/setup guidance instead of an empty `exit 127` tail.
4648
- Fixed `crabbox webvnc --open` so opened portal links make the lease visible to authenticated org users instead of showing a misleading 404 when CLI auth and browser auth differ.
4749
- Fixed WebVNC portal click forwarding so controller clicks reach the remote desktop while preserving focus and browser context-menu suppression.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,9 +440,9 @@ npm run build --prefix worker
440440
npm run docs:check
441441
442442
# Optional live smoke, when broker/provider credentials are available
443-
CRABBOX_LIVE=1 CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
443+
CRABBOX_LIVE=1 CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
444444
# Add Blacksmith only for repos with a Testbox workflow.
445-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=blacksmith-testbox scripts/live-smoke.sh
445+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=blacksmith-testbox CRABBOX_BLACKSMITH_WORKFLOW=.github/workflows/testbox.yml scripts/live-smoke.sh
446446
# Cloudflare Containers deploy plus live smoke, when Cloudflare credentials are available.
447447
scripts/deploy-cloudflare-smoke.sh
448448
```

docs/operations.md

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -36,28 +36,33 @@ bin/crabbox history --limit 5
3636
When broker/provider credentials are available and infra changed, run the live smoke:
3737

3838
```sh
39-
CRABBOX_LIVE=1 CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
39+
CRABBOX_LIVE=1 CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
4040
```
4141

4242
To narrow the live matrix while debugging, set `CRABBOX_LIVE_PROVIDERS`:
4343

4444
```sh
45-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=aws CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
46-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=hetzner CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
47-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=blacksmith-testbox CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
48-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=e2b CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
49-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=modal CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
50-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=daytona CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
51-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=namespace-devbox CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
52-
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=semaphore CRABBOX_LIVE_REPO=/path/to/openclaw scripts/live-smoke.sh
45+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=aws CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
46+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=hetzner CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
47+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=blacksmith-testbox CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
48+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=e2b CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
49+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=modal CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
50+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=daytona CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
51+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=namespace-devbox CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
52+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=semaphore CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
53+
CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=sprites CRABBOX_LIVE_REPO=/path/to/my-app scripts/live-smoke.sh
5354
```
5455

55-
E2B smoke requires `E2B_API_KEY`. Modal smoke requires an authenticated Modal
56-
Python client (`python3 -m modal setup` or Modal token env vars). Semaphore smoke requires
57-
`CRABBOX_SEMAPHORE_HOST`, `CRABBOX_SEMAPHORE_PROJECT`, and
58-
`CRABBOX_SEMAPHORE_TOKEN` or equivalent user config.
59-
Daytona needs `CRABBOX_DAYTONA_SNAPSHOT` or `daytona.snapshot`.
60-
Namespace needs the authenticated `devbox` CLI on `PATH`.
56+
Blacksmith smoke requires a workflow containing a `useblacksmith/testbox`,
57+
`useblacksmith/begin-testbox`, or `useblacksmith/run-testbox` step; set
58+
`CRABBOX_BLACKSMITH_WORKFLOW` when the default path is not correct. E2B smoke
59+
requires `E2B_API_KEY`. Modal smoke requires an authenticated Modal Python
60+
client (`python3 -m modal setup` or Modal token env vars). Semaphore smoke
61+
requires `CRABBOX_SEMAPHORE_HOST`, `CRABBOX_SEMAPHORE_PROJECT`, and
62+
`CRABBOX_SEMAPHORE_TOKEN` or equivalent user config. Daytona needs
63+
`CRABBOX_DAYTONA_SNAPSHOT`, `DAYTONA_SNAPSHOT`, or `daytona.snapshot`.
64+
Namespace needs the authenticated `devbox` CLI on `PATH`. Sprites needs the
65+
authenticated `sprite` CLI on `PATH` plus a Sprites token in the environment.
6166

6267
For direct-provider smoke, disable the coordinator with a scratch config and run the same commands manually:
6368

@@ -97,7 +102,7 @@ health checks for `crabbox.openclaw.ai` plus the workers.dev fallback. To includ
97102
a short AWS lease smoke after deploy:
98103

99104
```sh
100-
CRABBOX_DEPLOY_SMOKE_AWS=1 CRABBOX_LIVE_REPO=/path/to/openclaw scripts/deploy-worker-smoke.sh
105+
CRABBOX_DEPLOY_SMOKE_AWS=1 CRABBOX_LIVE_REPO=/path/to/my-app scripts/deploy-worker-smoke.sh
101106
```
102107

103108
Required Worker secrets:

scripts/live-auth-smoke.sh

Lines changed: 65 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,25 @@ fi
99
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
1010
cb="${CRABBOX_BIN:-$root/bin/crabbox}"
1111
coord="${CRABBOX_AUTH_SMOKE_COORDINATOR:-${CRABBOX_COORDINATOR:-https://crabbox-access.openclaw.ai}}"
12-
config_path="$("$cb" config path)"
12+
config_cwd="$PWD"
13+
config_paths=()
14+
15+
add_config_path() {
16+
local path="$1"
17+
[[ -n "$path" ]] || return 0
18+
if [[ "$path" != /* ]]; then
19+
path="$config_cwd/$path"
20+
fi
21+
config_paths+=("$path")
22+
}
23+
24+
if [[ -n "${CRABBOX_CONFIG:-}" ]]; then
25+
add_config_path "$CRABBOX_CONFIG"
26+
else
27+
add_config_path "$("$cb" config path 2>/dev/null || true)"
28+
add_config_path "$config_cwd/crabbox.yaml"
29+
add_config_path "$config_cwd/.crabbox.yaml"
30+
fi
1331

1432
need_tool() {
1533
if ! command -v "$1" >/dev/null 2>&1; then
@@ -24,13 +42,36 @@ need_tool ruby
2442

2543
config_value() {
2644
local key_path="$1"
27-
ruby -ryaml -e '
28-
value = ARGV[1].split(".").reduce(YAML.load_file(ARGV[0])) do |memo, key|
29-
memo.is_a?(Hash) ? memo[key] : nil
30-
end
31-
exit 3 if value.nil? || value.to_s.empty?
32-
print value
33-
' "$config_path" "$key_path"
45+
local value=""
46+
local found=0
47+
local path
48+
for path in "${config_paths[@]}"; do
49+
[[ -r "$path" ]] || continue
50+
if value="$(ruby -ryaml -e '
51+
value = ARGV[1].split(".").reduce(YAML.load_file(ARGV[0])) do |memo, key|
52+
memo.is_a?(Hash) ? memo[key] : nil
53+
end
54+
exit 3 if value.nil? || value.to_s.empty?
55+
print value
56+
' "$path" "$key_path" 2>/dev/null)"; then
57+
found=1
58+
fi
59+
done
60+
if [[ "$found" == "1" ]]; then
61+
printf '%s' "$value"
62+
return 0
63+
fi
64+
return 1
65+
}
66+
67+
required_config_value() {
68+
local key_path="$1"
69+
local value
70+
if ! value="$(config_value "$key_path" 2>/dev/null)"; then
71+
echo "missing required config: $key_path" >&2
72+
exit 2
73+
fi
74+
printf '%s' "$value"
3475
}
3576

3677
curl_quote() {
@@ -82,8 +123,8 @@ request_json() {
82123
printf '%s' "$status"
83124
}
84125

85-
shared_token="$(config_value broker.token)"
86-
admin_token="$(config_value broker.adminToken)"
126+
shared_token="$(required_config_value broker.token)"
127+
admin_token="$(required_config_value broker.adminToken)"
87128
access_client_id="${CRABBOX_ACCESS_CLIENT_ID:-$(config_value broker.access.clientId 2>/dev/null || true)}"
88129
access_client_secret="${CRABBOX_ACCESS_CLIENT_SECRET:-$(config_value broker.access.clientSecret 2>/dev/null || true)}"
89130
owner="${CRABBOX_OWNER:-$(git config user.email 2>/dev/null || true)}"
@@ -97,11 +138,22 @@ if [[ "$coord" == *"crabbox-access.openclaw.ai"* ]]; then
97138
exit 1
98139
fi
99140
echo "ok no-access edge denied http=403"
141+
if [[ -z "$access_client_id" || -z "$access_client_secret" ]]; then
142+
echo "access auth smoke requires CRABBOX_ACCESS_CLIENT_ID/CRABBOX_ACCESS_CLIENT_SECRET or broker.access.clientId/clientSecret for $coord" >&2
143+
exit 2
144+
fi
100145
fi
101146

102-
whoami="$(env -u CRABBOX_COORDINATOR_TOKEN CRABBOX_COORDINATOR="$coord" "$cb" whoami --json)"
103-
printf '%s\n' "$whoami" | jq -e '.auth == "bearer" and (.owner | length > 0) and (.org | length > 0)' >/dev/null
104-
echo "ok shared token whoami owner=$(printf '%s\n' "$whoami" | jq -r '.owner') org=$(printf '%s\n' "$whoami" | jq -r '.org')"
147+
if ! whoami="$(env -u CRABBOX_COORDINATOR_TOKEN CRABBOX_COORDINATOR="$coord" "$cb" whoami --json 2>&1)"; then
148+
echo "failed coordinator whoami: $whoami" >&2
149+
exit 1
150+
fi
151+
if ! printf '%s\n' "$whoami" | jq -e '(.auth == "bearer" or .auth == "github") and (.owner | length > 0) and (.org | length > 0)' >/dev/null; then
152+
echo "failed coordinator whoami shape: $whoami" >&2
153+
exit 1
154+
fi
155+
whoami_auth="$(printf '%s\n' "$whoami" | jq -r '.auth')"
156+
echo "ok coordinator whoami auth=$whoami_auth owner=$(printf '%s\n' "$whoami" | jq -r '.owner') org=$(printf '%s\n' "$whoami" | jq -r '.org')"
105157

106158
body="$(mktemp)"
107159
trap 'rm -f "$body"' EXIT

0 commit comments

Comments
 (0)