You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Crabbox has 71 registered providers but no single place that says how to test a connector's full lifecycle, no complete picture of which providers are covered, and no CI gate that exercises any lifecycle before code lands on main. This issue documents the testing method, publishes a verified coverage matrix, and proposes a two-tier CI design that stays inside the constraints from the closing guidance on #176 and #175.
Verified against current main:
71 providers registered in internal/providers/all/all.go, matching docs/providers/provider-metadata.json and the 71 pages under docs/providers/.
30 providers have a dedicated smoke runner in scripts/ (29 live-*-smoke.sh shell scripts; codesandbox uses Node runners scripts/live-codesandbox-smoke.test.js + live-codesandbox-smoke-classify.test.js).
43 providers are drivable through the scripts/live-smoke.sh matrix (CRABBOX_LIVE_PROVIDERS), via its generic provider_smoke() path or an inline custom function.
Only 4 providers have hermetic lifecycle unit tests that run in go test -race ./... today: scaleway (internal/providers/scaleway/backend_lifecycle_test.go), nebius, nomad, firecracker.
.github/workflows/ contains zero smoke or lifecycle invocations — no workflow references CRABBOX_LIVE or any live-*-smoke.sh.
20 providers have no lifecycle coverage of any kind (list below).
The lifecycle a connector test must exercise
From the backend contract in internal/cli/provider_backend.go:
How to test a connector today (the recipe this issue wants documented in docs/)
Hermetic lifecycle unit test — a table-driven backend_lifecycle_test.go against a fake API (pattern: internal/providers/scaleway/backend_lifecycle_test.go, e.g. TestScalewayAcquireListResolveTouchReleaseLifecycle). Runs in CI via go test -race ./.... This is the only tier that can gate merges for every provider.
Guarded live smoke — CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=<p> CRABBOX_BIN=bin/crabbox scripts/live-smoke.sh, or the provider's dedicated scripts/live-<p>-smoke.sh. All scripts arm EXIT/RETURN traps that crabbox stop their leases, and several classify provider-capacity failures (quota_blocked / environment_blocked) separately from regressions.
Opt-in Go live smokes — //go:build smoke tests (islo, morph, wandb) run only with the smoke tag plus provider env gates (e.g. ISLO_API_KEY + CRABBOX_LIVE_ISLO_PAUSE_RESUME=1). These are excluded from CI by build tag and undocumented in docs/features/provider-live-smoke.md.
Coverage matrix — the gaps
20 providers with zero lifecycle coverage (no dedicated smoke runner, not in the live-smoke.sh matrix, no lifecycle unit test):
Notable: azure and gcp are majors with open cleanup-safety issues (#930, #931) yet no lifecycle test exercises their release path. ssh should be testable hermetically against 127.0.0.1 on any runner. islo has live Go tests but no shell smoke and is absent from live-smoke.sh (it needs a custom function like e2b_smoke because generic crabbox ssh requires the external islo CLI).
Only 4/71 providers have hermetic lifecycle unit tests. That is the cheapest, highest-leverage gap: those tests need no secrets and gate every PR.
Proposal: .github/workflows/connector-lifecycles.yml, two tiers
Designed to address the reasons #175 was closed (secret-bearing runners, automation risk, provider-list drift):
Tier 1 — hermetic, required check on every PR / push to main. No secrets at all.
docker-sandbox full lifecycle (scripts/live-docker-sandbox-smoke.sh — needs no env), docker-sandbox trust boundary, local-container via live-smoke.sh, firecracker readiness (read-only doctor contract), ssh-to-localhost lifecycle (new small script), apple-vm on macos-15.
Lives as a matrix job; can sit inside ci.yml so dependabot-auto-merge.yml (which keys off the CI workflow conclusion) inherits it without changes.
Tier 2 — live cloud matrix: schedule (nightly) + workflow_dispatch only. Never runs on pull_request, so fork PRs can never reach secrets.
Secrets scoped to a dedicated live-smoke GitHub environment (required-reviewer gating for dispatches comes free — same pattern coordinator-deploy.yml uses for coordinator).
Green-skip rows whose secret is unset (the coordinator-deploy.yml probe pattern), so partially provisioned secrets never red-X the nightly.
fail-fast: false, max-parallel: 4 (spend/rate cap), timeout-minutes: 30, per-provider concurrency group with cancel-in-progress: false — cancelling mid-provision is how orphans happen.
Treat quota_blocked / environment_blocked classifications as warnings, not failures.
Trailing orphan-audit job (if: always()) running scripts/aws-crabbox-orphan-audit.shread-only (its --terminate fails closed by design) that fails when crabbox-tagged instances outlive their leases.
No second provider list: generate the live matrix from docs/providers/provider-metadata.json (extend scripts/generate-provider-matrix.mjs) or reuse CRABBOX_LIVE_PROVIDERS defaults, so the workflow cannot drift from the registry — this was an explicit concern on Proposal: add live provider E2E GitHub Actions matrix #176.
All uses: SHA-pinned (enforced by scripts/workflow_action_pins.go via the CI Scripts job) and a scripts/connector-lifecycles-workflow.test.js shape test asserting: no secrets in tier 1, no pull_request trigger on tier 2, continue-on-error on live rows.
Secret names match what the scripts already read from env: AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY, HCLOUD_TOKEN, DIGITALOCEAN_TOKEN, LINODE_TOKEN, VULTR_API_KEY, SCW_*, TENCENTCLOUD_*, LAMBDA_API_KEY, RUNPOD_API_KEY, VAST_API_KEY (+ CRABBOX_LIVE_VAST_MAX_DPH_TOTAL price cap), BL_API_KEY/BL_WORKSPACE, VERCEL_TOKEN, SMOLMACHINES_API_KEY, SUPERSERVE_API_KEY, OPEN_SANDBOX_API_KEY, CROWNEST_API_KEY, WANDB_API_KEY/WANDB_ENTITY_NAME. Self-hosted-infra providers (nomad, proxmox, xcp-ng, kubevirt, agent-sandbox, phala) stay out of hosted runners; the hydrate.yml self-hosted-label pattern covers them later.
Task checklist
Add a docs/ testing guide capturing the lifecycle table and the three-tier recipe above (candidate: extend docs/features/provider-live-smoke.md).
Document the //go:build smoke live-test env vars (ISLO_API_KEY, CRABBOX_LIVE_ISLO_PAUSE_RESUME, CRABBOX_LIVE_ISLO_IMAGE, morph/wandb equivalents) in that guide.
Hermetic backend_lifecycle_test.go for high-traffic providers missing one (start: aws, azure, gcp, e2b, daytona, islo, railway) — pattern from internal/providers/scaleway/backend_lifecycle_test.go; long-term goal: all 71.
islo smoke coverage: islo_smoke() function in scripts/live-smoke.sh (warmup → status --wait → run → pause → resume → stop; skip generic crabbox ssh).
Dedicated or matrix smoke coverage for the remaining zero-coverage providers listed above.
Tier 2 live workflow behind the live-smoke environment — only after maintainers decide the repository secret/provider policy, per the closing guidance on Proposal: add live provider E2E GitHub Actions matrix #176; dispatch it once and attach the run link as live proof.
I can send tier 1 (hermetic gate + docs guide + shape test) as a PR first since it needs no secret policy decision, and hold tier 2 until the policy call is made.
Summary
Crabbox has 71 registered providers but no single place that says how to test a connector's full lifecycle, no complete picture of which providers are covered, and no CI gate that exercises any lifecycle before code lands on
main. This issue documents the testing method, publishes a verified coverage matrix, and proposes a two-tier CI design that stays inside the constraints from the closing guidance on #176 and #175.Verified against current
main:internal/providers/all/all.go, matchingdocs/providers/provider-metadata.jsonand the 71 pages underdocs/providers/.scripts/(29live-*-smoke.shshell scripts;codesandboxuses Node runnersscripts/live-codesandbox-smoke.test.js+live-codesandbox-smoke-classify.test.js).scripts/live-smoke.shmatrix (CRABBOX_LIVE_PROVIDERS), via its genericprovider_smoke()path or an inline custom function.go test -race ./...today:scaleway(internal/providers/scaleway/backend_lifecycle_test.go),nebius,nomad,firecracker..github/workflows/contains zero smoke or lifecycle invocations — no workflow referencesCRABBOX_LIVEor anylive-*-smoke.sh.The lifecycle a connector test must exercise
From the backend contract in
internal/cli/provider_backend.go:SSHLeaseBackend.Acquire,DelegatedRunBackend.Warmupcrabbox warmupSSHLoginBackend.Resolve, delegatedStatuscrabbox status --waitDelegatedRunBackend.Run(RunRequestincl. downloads/artifact globs), SSH execcrabbox run --shell,crabbox sshLeaseTouchBackend.Touchstatus --waitSSHLeaseBackend.List,JSONListBackend.ListJSONcrabbox list --json,crabbox inspect --jsonCopyBackend.Copy,PortsBackend.Portscrabbox cp,crabbox portsNativeCheckpointLifecycleProvider.*PausableBackend.Pause/ResumetenkiandcodesandboxtodaySSHLeaseBackend.ReleaseLease(withProviderIdentityExpectationvalidation), delegatedStopcrabbox stopCleanupBackend.Cleanup(DryRunsupported)crabbox cleanup --dry-run,scripts/aws-crabbox-orphan-audit.shHow to test a connector today (the recipe this issue wants documented in
docs/)backend_lifecycle_test.goagainst a fake API (pattern:internal/providers/scaleway/backend_lifecycle_test.go, e.g.TestScalewayAcquireListResolveTouchReleaseLifecycle). Runs in CI viago test -race ./.... This is the only tier that can gate merges for every provider.CRABBOX_LIVE=1 CRABBOX_LIVE_PROVIDERS=<p> CRABBOX_BIN=bin/crabbox scripts/live-smoke.sh, or the provider's dedicatedscripts/live-<p>-smoke.sh. All scripts arm EXIT/RETURN traps thatcrabbox stoptheir leases, and several classify provider-capacity failures (quota_blocked/environment_blocked) separately from regressions.//go:build smoketests (islo, morph, wandb) run only with thesmoketag plus provider env gates (e.g.ISLO_API_KEY+CRABBOX_LIVE_ISLO_PAUSE_RESUME=1). These are excluded from CI by build tag and undocumented indocs/features/provider-live-smoke.md.Coverage matrix — the gaps
20 providers with zero lifecycle coverage (no dedicated smoke runner, not in the
live-smoke.shmatrix, no lifecycle unit test):apple-machine,ascii-box,azure,azure-dynamic-sessions,cloudflare-sandbox,exe-dev,fastapi-cloud,freestyle,gcp,hostinger,hyperv,islo,mxc,opencomputer,parallels,railway,ssh,tensorlake,upstash-box,windows-sandboxNotable:
azureandgcpare majors with open cleanup-safety issues (#930, #931) yet no lifecycle test exercises their release path.sshshould be testable hermetically against127.0.0.1on any runner.islohas live Go tests but no shell smoke and is absent fromlive-smoke.sh(it needs a custom function likee2b_smokebecause genericcrabbox sshrequires the externalisloCLI).Only 4/71 providers have hermetic lifecycle unit tests. That is the cheapest, highest-leverage gap: those tests need no secrets and gate every PR.
Proposal:
.github/workflows/connector-lifecycles.yml, two tiersDesigned to address the reasons #175 was closed (secret-bearing runners, automation risk, provider-list drift):
Tier 1 — hermetic, required check on every PR / push to
main. No secrets at all.docker-sandboxfull lifecycle (scripts/live-docker-sandbox-smoke.sh— needs no env),docker-sandboxtrust boundary,local-containervialive-smoke.sh,firecrackerreadiness (read-only doctor contract),ssh-to-localhost lifecycle (new small script),apple-vmonmacos-15.ci.ymlsodependabot-auto-merge.yml(which keys off the CI workflow conclusion) inherits it without changes.Tier 2 — live cloud matrix:
schedule(nightly) +workflow_dispatchonly. Never runs onpull_request, so fork PRs can never reach secrets.live-smokeGitHub environment (required-reviewer gating for dispatches comes free — same patterncoordinator-deploy.ymluses forcoordinator).coordinator-deploy.ymlprobe pattern), so partially provisioned secrets never red-X the nightly.fail-fast: false,max-parallel: 4(spend/rate cap),timeout-minutes: 30, per-providerconcurrencygroup withcancel-in-progress: false— cancelling mid-provision is how orphans happen.quota_blocked/environment_blockedclassifications as warnings, not failures.orphan-auditjob (if: always()) runningscripts/aws-crabbox-orphan-audit.shread-only (its--terminatefails closed by design) that fails when crabbox-tagged instances outlive their leases.docs/providers/provider-metadata.json(extendscripts/generate-provider-matrix.mjs) or reuseCRABBOX_LIVE_PROVIDERSdefaults, so the workflow cannot drift from the registry — this was an explicit concern on Proposal: add live provider E2E GitHub Actions matrix #176.uses:SHA-pinned (enforced byscripts/workflow_action_pins.govia the CI Scripts job) and ascripts/connector-lifecycles-workflow.test.jsshape test asserting: no secrets in tier 1, nopull_requesttrigger on tier 2,continue-on-erroron live rows.Secret names match what the scripts already read from env:
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY,HCLOUD_TOKEN,DIGITALOCEAN_TOKEN,LINODE_TOKEN,VULTR_API_KEY,SCW_*,TENCENTCLOUD_*,LAMBDA_API_KEY,RUNPOD_API_KEY,VAST_API_KEY(+CRABBOX_LIVE_VAST_MAX_DPH_TOTALprice cap),BL_API_KEY/BL_WORKSPACE,VERCEL_TOKEN,SMOLMACHINES_API_KEY,SUPERSERVE_API_KEY,OPEN_SANDBOX_API_KEY,CROWNEST_API_KEY,WANDB_API_KEY/WANDB_ENTITY_NAME. Self-hosted-infra providers (nomad,proxmox,xcp-ng,kubevirt,agent-sandbox,phala) stay out of hosted runners; thehydrate.ymlself-hosted-label pattern covers them later.Task checklist
docs/testing guide capturing the lifecycle table and the three-tier recipe above (candidate: extenddocs/features/provider-live-smoke.md).//go:build smokelive-test env vars (ISLO_API_KEY,CRABBOX_LIVE_ISLO_PAUSE_RESUME,CRABBOX_LIVE_ISLO_IMAGE, morph/wandb equivalents) in that guide.scripts/live-ssh-localhost-smoke.sh(hermetic, mirrorslive-docker-sandbox-smoke.sh).backend_lifecycle_test.gofor high-traffic providers missing one (start:aws,azure,gcp,e2b,daytona,islo,railway) — pattern frominternal/providers/scaleway/backend_lifecycle_test.go; long-term goal: all 71.islosmoke coverage:islo_smoke()function inscripts/live-smoke.sh(warmup → status --wait → run → pause → resume → stop; skip genericcrabbox ssh).live-smokeenvironment — only after maintainers decide the repository secret/provider policy, per the closing guidance on Proposal: add live provider E2E GitHub Actions matrix #176; dispatch it once and attach the run link as live proof.I can send tier 1 (hermetic gate + docs guide + shape test) as a PR first since it needs no secret policy decision, and hold tier 2 until the policy call is made.