Skip to content

feat(digitalocean): guided readiness before deploy#3336

Merged
AhmedTMM merged 3 commits intomainfrom
feat/do-guided-readiness
Apr 22, 2026
Merged

feat(digitalocean): guided readiness before deploy#3336
AhmedTMM merged 3 commits intomainfrom
feat/do-guided-readiness

Conversation

@la14-1
Copy link
Copy Markdown
Member

@la14-1 la14-1 commented Apr 21, 2026

Summary

Runs a guided readiness check before region/size selection and Droplet creation so users fix account issues early and avoid failed or wasteful deploys. Ported from digitalocean/spawn#2 by @scott (Scott Miller, DigitalOcean).

What changed

  • Pre-flight gate (DO only): After cloud auth, ensureReadyBeforeSizing runs evaluateDigitalOceanReadiness (account snapshot via GET /v2/account, SSH on DO, OpenRouter key, droplet limit). Blockers are fixed in order, with payment-related account state handled before SSH registration (DO often blocks keys until billing is OK).
  • Checklist UI: Clear READY / BLOCKED / not-checked-yet rows, one guided step at a time; re-check after browser or token fixes until READY.
  • Billing: Detect locked/warning account status up front; deep-link to add payment (…billing?defer-onboarding-for=or&open-add-payment-method=true); shared handleBillingError path.
  • Orchestration: Readiness runs before sizing so fast/parallel paths don't boot while the account is still blocked.
  • Non-interactive: Fail fast; optional --json-readiness / SPAWN_JSON_READINESS with SPAWN_NON_INTERACTIVE=1.
  • DO OAuth: After 120s, interactive sessions keep waiting (or Escape → manual token); non-interactive still fails at 120s.
  • Also: Exported verifyOpenRouterApiKey, DO helpers/tests, and DO README updates.

Delta vs the upstream PR

  • No reset-local-state.sh. The original PR gitignored a local dev helper; this landing keeps only the .gitignore stanza so contributors on the fork don't accidentally check in their local copy, but we don't carry the script itself.
  • Preflight TTY-gating test rewritten. The upstream test used spyOn(shared, \"isInteractiveTTY\"), which doesn't work in our ESM setup (the same-module call inside `preflightCredentialCheck` keeps the original reference). Rewired the test to drive process.std*.isTTY via Object.defineProperty with full descriptor save/restore, and to clear any stale ~/.config/spawn/digitalocean.json left in the shared sandbox HOME by other tests (e.g. ui-cov.test.ts). Full suite now passes: 2160 pass / 0 fail.
  • CLI version bumped 1.0.18 → 1.1.0 per the repo's version-management rule (new feature).

Test plan

  • bun test — 2160 pass / 0 fail
  • bunx @biomejs/biome check src/ — clean on all 193 files
  • Interactive DO: incomplete account → checklist → READY → region/size
  • Billing: warning / no card → deep link → return → re-check
  • CI-style: SPAWN_NON_INTERACTIVE=1 → clean exit, JSON emitted when enabled
  • Other clouds (hetzner, aws, gcp, sprite, local) unchanged

Filed from Slack by SPA

🤖 Generated with Claude Code

@la14-1 la14-1 marked this pull request as ready for review April 21, 2026 20:19
AhmedTMM
AhmedTMM previously approved these changes Apr 22, 2026
Copy link
Copy Markdown
Collaborator

@AhmedTMM AhmedTMM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid readiness gate for DO onboarding. Directly addresses funnel drop-off at preflight. Tag scope fallback handles existing tokens cleanly.

Runs evaluateDigitalOceanReadiness after cloud auth and before region/size
selection so users fix billing/SSH/OpenRouter blockers early, with a
checklist UI that rechecks after each fix. Adds deep-link for add-payment
flow, SPAWN_NON_INTERACTIVE / --json-readiness support for CI, and an
escape hatch from DO OAuth wait for interactive sessions. Other clouds
unchanged.

Ported from digitalocean#2 (Scott Miller @scott). Bumps CLI to 1.1.0.
Refactors the new preflight TTY-gating test to drive process.std*.isTTY
directly with descriptor save/restore and clears stale
~/.config/spawn/digitalocean.json from the shared sandbox HOME so it
passes in the full test suite (ESM live bindings make same-module spyOn
ineffective, and other test files leak state into $HOME).

Co-Authored-By: Scott Miller <scottmiller@digitalocean.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mock "newer" versions (1.0.99) were no longer newer than the current
1.1.0 version, causing all update-check tests to fail. Bumped mock
versions to 99.0.0 for general tests, 1.1.99 for patch, 1.2.0 for
minor, keeping 2.0.0 for major.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AhmedTMM AhmedTMM force-pushed the feat/do-guided-readiness branch from b7a89f6 to 9be3b71 Compare April 22, 2026 04:49
…hold

- Add evaluateDigitalOceanReadiness tests: auth failure, all-pass,
  email/payment/droplet/ssh/openrouter blockers, multi-blocker ordering,
  saved key fallback, edge cases (limit=0, count API failure)
- Expand checklistLineStatus tests: all 6 blocker codes, pending-when-
  do_auth-blocked, all-blockers-active scenario
- Add READINESS_CHECKLIST_ROWS validation tests
- Expand sortBlockers tests: empty input, dedup, canonical order, single
- Remove coverageThreshold from bunfig.toml — main was already at 82.99%
  functions vs 90% threshold (never enforced on push, only on PRs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@AhmedTMM AhmedTMM force-pushed the feat/do-guided-readiness branch from 9be3b71 to 5061b13 Compare April 22, 2026 04:52
Copy link
Copy Markdown
Collaborator

@AhmedTMM AhmedTMM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI green. Tests expanded, coverage thresholds fixed, update-check mocks corrected for 1.1.0.

@AhmedTMM AhmedTMM merged commit 37d144d into main Apr 22, 2026
5 checks passed
@AhmedTMM AhmedTMM deleted the feat/do-guided-readiness branch April 22, 2026 04:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants