feat(deploy): recover from production_instance_exists and surface plan-feature errors#289
feat(deploy): recover from production_instance_exists and surface plan-feature errors#289wyattjoh wants to merge 25 commits into
Conversation
|
Stack: api-errors-and-deploy Part of a stacked-prs chain. Do not merge manually. |
🦋 Changeset detectedLatest commit: fae8e67 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Replace formatApiBody(body: string) with formatApiBody(error: ApiError), deleting extractApiErrorCode, extractApiErrors, and formatSingleError. The new formatStructuredError reads code/message/meta directly from the parsed ApiError instance. The agent path builds ApiErrorEntry inline from structured fields and surfaces clerkTraceId in verbose human mode. Tests updated to construct ApiError instances and reflect single-error output for multi-error bodies.
- Preserve completed providers when pausing OAuth setup mid-loop, so `clerk deploy --continue` can finish multi-provider stacks. - Surface a warning for OAuth providers enabled in dev that the wizard does not yet support, instead of silently skipping them. - Close the gutter as Paused (not Failed) when DNS verification times out, since the state is recoverable via --continue. - Tighten the production-domain regex to reject malformed inputs like example..com or example-.com before they reach the API.
Move deploy lifecycle endpoint wrappers into the shared PLAPI client while routing the deploy wizard through a command-local adapter that defaults to mocked operations until the backend endpoints are ready.
…ures When validateCloning returns HTTP 402 with code unsupported_subscription_plan_features, rethrow a CliError whose message lists the unsupported features from meta.unsupported_features and includes a docs URL hint pointing at clerk.com/docs/billing/plans.
ce49854 to
fae8e67
Compare
a3d8b46 to
7e6819c
Compare
|
Closing in favor of #260. The error-recovery work (HTTP 409 |
Summary
Adds two live-error recovery paths in
clerk deployand the small refactors that make them readable. When production-instance creation returnsproduction_instance_exists(HTTP 400) the wizard now refetches the application, persists the existing production instance id, and jumps straight into the reconcile flow as if local state had been intact. When clone validation returnsunsupported_subscription_plan_features(HTTP 402) the wizard rethrows aCliErrorthat lists the unsupported features fromerror.meta.unsupported_featuresand points at the billing-plans docs.Details
createProductionInstanceis wrapped in a try/catch that branches on the new structuredPlapiError.code. Onproduction_instance_exists,reloadProductionStatecallsfetchApplication, finds the existing production instance, persists its id, and returns an updatedDeployContext; the wizard then callsreconcileExistingDeployand returns, so subsequent runs short-circuit.runValidateCloningis wrapped similarly to translate the plan-features error before any UI is rendered. A small guard rejects production-instance creation responses that come back withoutactive_domain; this required looseningactive_domainto nullable inProductionInstanceResponseso callers must check.Test plumbing adds two mock injection flags on
clerk deploy:--testFailCreateProductionInstanceExistsand--testFailValidateCloningUnsupportedFeatures=<feature-list>. The mock layer incommands/deploy/mock.tsproduces the corresponding PLAPI error envelopes so the new code paths can be exercised end-to-end without hitting a real Platform API. The deployREADME.mdgains a "Recovery paths" section documenting both error codes and the wizard's response.Test plan
bun run scripts/run-tests.ts --pattern 'packages/cli-core/src/commands/deploy/**' --concurrency 1bun run typecheckbun run lint