Skip to content

feat(cli): port bootstrap command to native TypeScript#5470

Merged
Coly010 merged 4 commits into
developfrom
cli/port-bootstrap-command
Jun 5, 2026
Merged

feat(cli): port bootstrap command to native TypeScript#5470
Coly010 merged 4 commits into
developfrom
cli/port-bootstrap-command

Conversation

@Coly010
Copy link
Copy Markdown
Contributor

@Coly010 Coly010 commented Jun 4, 2026

What changed

Replaces the Phase-0 Go proxy for supabase bootstrap with a native TypeScript implementation in the legacy shell. bootstrap is a meta-orchestrator that chains: workdir resolve/prompt → template list/download → blank init → ensure-login → projects createprojects api-keys (backoff) → link services → health poll (backoff) → write .envdb push → start suggestion.

Per the "hoist before you duplicate" policy, the shared orchestration is extracted from the already-ported login / projects create / projects api-keys / link handlers into legacy/shared/, and those handlers are refactored to delegate (no behavior change — their existing tests still pass):

  • legacy-ensure-login (browser login flow + post-login telemetry)
  • legacy-project-create-core
  • legacy-get-api-keys
  • legacy-link-services-core
  • legacy-tenant-keys (legacyExtractServiceKeys)
  • the login api/crypto layers move to legacy/shared/ so bootstrap can compose them without a cross-command import

Why

Phase 1+ native port of bootstrap (the last Quick-Start command still proxied), unblocking native machine output (--output-format json|stream-json) and removing the Go dependency for everything except the migration push.

Reviewer-relevant context

  • db push is delegated to the bundled Go binary (interim). It is the only non-native step, pending a separate native db push port. LegacyGoProxy.exec exits the process on a non-zero exit rather than returning a failure, so Go's push backoff cannot be reproduced from the proxy (single attempt). Documented in SIDE_EFFECTS.md.
  • Go-parity decisions worth a look:
    • No cli_project_linked telemetry — Go's bootstrap calls link.LinkServices (services-only), not link.Run, so it deliberately skips the project-linked event, status check, and linked-project.json temp write.
    • API keys are fetched without reveal (Go's RunGetApiKeys uses empty params).
    • Workdir / DB password env vars are read prefixed (SUPABASE_WORKDIR, SUPABASE_DB_PASSWORD) to match Go's viper.SetEnvPrefix("SUPABASE").
    • Using workdir … prints only when the resolved workdir differs from the cwd (matches Go's ChangeWorkDir guard).
  • Hardening: template download rejects entries that would escape the target directory; GitHub and health error bodies are sanitized before surfacing.
  • docs/go-cli-porting-status.md flips bootstrap wrappedported with the interim-db-push note.

Follow-ups (out of scope)

  • Native db push port will remove the proxy delegation (eliminating the single-attempt and transient --password-in-process-table limitations).
  • bootstrap.e2e.test.ts deferred — integration coverage is comprehensive; e2e needs replayed API fixtures plus handling of the real Go db push subprocess.

Replaces the Phase-0 Go proxy for `supabase bootstrap` with a native
TypeScript implementation in the legacy shell. The command orchestrates:
workdir resolve/prompt -> template list/download -> blank init ->
ensure-login -> projects create -> api-keys (backoff) -> link services ->
health poll (backoff) -> write .env -> db push -> start suggestion.

Every step is native except the migration push, which is delegated to the
bundled Go binary via LegacyGoProxy as a documented interim until `db push`
is natively ported (LegacyGoProxy.exec exits on non-zero rather than
failing, so its push backoff is not reproducible from the proxy).

Per the "hoist before you duplicate" policy, shared orchestration cores are
extracted from the already-ported login/create/api-keys/link handlers and
those handlers refactored to delegate:
- legacy-ensure-login (browser login + post-login telemetry)
- legacy-project-create-core
- legacy-get-api-keys
- legacy-link-services-core
- legacy-tenant-keys (legacyExtractServiceKeys)
- login api/crypto layers moved to legacy/shared so bootstrap composes them
  without a cross-command import

Go-parity notes:
- bootstrap fires no cli_project_linked event: Go calls link.LinkServices
  (services only), not link.Run, so it skips the project-linked telemetry,
  status check, and linked-project.json temp write.
- api-keys are fetched without `reveal` (Go's RunGetApiKeys uses empty params).
- workdir / db-password env vars are read prefixed (SUPABASE_WORKDIR,
  SUPABASE_DB_PASSWORD) to match Go's viper SetEnvPrefix("SUPABASE").
- "Using workdir" prints only when the resolved workdir differs from the cwd.

Template download validates entries stay within the target directory, and
GitHub/health error bodies are sanitized before surfacing.
@Coly010 Coly010 requested a review from a team as a code owner June 4, 2026 10:59
@Coly010 Coly010 self-assigned this Jun 4, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 4, 2026

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase@5470

Preview package for commit 792bc53.

Comment thread apps/cli/src/legacy/commands/bootstrap/bootstrap.handler.ts Outdated
Comment thread apps/cli/src/legacy/commands/bootstrap/bootstrap.handler.ts
Comment thread apps/cli/src/legacy/commands/bootstrap/bootstrap.templates.ts Outdated
Comment thread apps/cli/src/legacy/commands/bootstrap/bootstrap.templates.ts Outdated
Coly010 added 2 commits June 5, 2026 10:06
Resolve the review comments on the native bootstrap port:

- Retry backoff now reproduces Go's full cenkalti policy (3s initial,
  factor 1.5, 60s max interval, +/-50% jitter, 15m max elapsed, 8 retries)
  and the NewErrorCallback "Retry (n/8)" notice (debug logger for failures
  1-2, stderr from 3 on, none on the final attempt). Extracted to
  bootstrap.retry.ts.
- linked-project.json now resolves against the bootstrap-resolved workdir
  via an optional LegacyLinkedProjectCache.cache(ref, workdir?) override,
  so it lands beside project-ref on the prompt path instead of
  cliConfig.workdir.
- Template download: segment-aware root prefix stripping and an explicit
  guard for null/empty GitHub download_url (files >1MB / submodules).
- Provide legacyDebugLoggerLayer to the bootstrap runtime base layers,
  fixing a "Service not found: DebugLogger" panic at the first HTTP call
  that the mocked integration tests could not catch.
@Coly010 Coly010 requested a review from avallete June 5, 2026 09:23
Copy link
Copy Markdown
Member

@avallete avallete left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@Coly010 Coly010 merged commit 94b0db1 into develop Jun 5, 2026
19 checks passed
@Coly010 Coly010 deleted the cli/port-bootstrap-command branch June 5, 2026 09:47
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.

2 participants