|
4 | 4 |
|
5 | 5 | Guides a user through deploying their Clerk application to production. |
6 | 6 |
|
| 7 | +When the CLI reaches the DNS configuration step, it displays the required CNAME records and a Domain Connect URL, then prompts the user to export those records as a BIND zone file (`./clerk-<domain>.zone`). The prompt defaults to "no" and the file is overwritten silently on subsequent runs. This applies to both new deploys and resumed deploys, so users who return to finish an interrupted deploy see the same records preamble that the initial run shows. |
| 8 | + |
| 9 | +Once DNS records are added and the user proceeds to verification, the CLI runs a chain of three per-component spinners covering mail, DNS, and SSL in sequence. Each spinner resolves independently and emits a confirmation line as its component flips true, so the user sees incremental progress instead of a single opaque wait. All three spinners share the same five-minute wall-clock cap. |
| 10 | + |
7 | 11 | ## Usage |
8 | 12 |
|
9 | 13 | ```sh |
@@ -34,16 +38,18 @@ Agent mode does not call PLAPI and exits before the human-mode wizard starts. |
34 | 38 |
|
35 | 39 | Human mode reads and writes deploy state through the Platform API on every run. The CLI does not persist deploy progress locally — the only profile write is the ordinary `instances.production` value once the production instance has been created. |
36 | 40 |
|
37 | | -| Step | Endpoint | Behavior | |
38 | | -| -------------------------- | ---------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | |
39 | | -| Validate cloning | `POST /v1/platform/applications/{appID}/validate_cloning` | 204 on success. 402 `unsupported_subscription_plan_features` → `ERROR_CODE.PLAN_INSUFFICIENT` listing missing features. | |
40 | | -| Create production instance | `POST /v1/platform/applications/{appID}/production_instance` | Returns `instance_id`, `environment_type`, `active_domain`, `publishable_key`, `secret_key` (once), and `cname_targets[]`. | |
41 | | -| | | 409 `production_instance_exists` → CLI re-derives state via `fetchApplication` and falls through to `reconcileExistingDeploy`. | |
42 | | -| Trigger DNS check | `POST /v1/platform/applications/{appID}/domains/{domainIDOrName}/dns_check` | Fired best-effort once per "Check DNS now" selection to actively kick the check job. Idempotent (no-op if a check is in flight). | |
43 | | -| Poll deploy status | `GET /v1/platform/applications/{appID}/instances/{envOrInsID}/deploy_status` | Returns `status` plus the three component booleans `dns_ok`, `ssl_ok`, `mail_ok`. CLI polls every 3s up to ~5 minutes. | |
44 | | -| Retry SSL provisioning | `POST /v1/platform/applications/{appID}/domains/{domainIDOrName}/ssl_retry` | 204 on success. 409 `ssl_retry_throttled` carries `meta.retry_after_seconds` (12-min per-domain throttle). | |
45 | | -| Retry mail verification | `POST /v1/platform/applications/{appID}/domains/{domainIDOrName}/mail_retry` | 204 on success. 409 `mail_retry_inflight` → poll `deploy_status`. 403 `operation_not_allowed_on_satellite_domain` for satellites. | |
46 | | -| Save OAuth credentials | `PATCH /v1/platform/applications/{appID}/instances/{instanceID}/config` | Returns the updated config snapshot. Used to persist production `connection_oauth_*` credentials. | |
| 41 | +| Step | Endpoint | Behavior | |
| 42 | +| -------------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| 43 | +| Validate cloning | `POST /v1/platform/applications/{appID}/validate_cloning` | 204 on success. 402 `unsupported_subscription_plan_features` → `ERROR_CODE.PLAN_INSUFFICIENT` listing missing features. | |
| 44 | +| Create production instance | `POST /v1/platform/applications/{appID}/production_instance` | Returns `instance_id`, `environment_type`, `active_domain`, `publishable_key`, `secret_key` (once), and `cname_targets[]`. | |
| 45 | +| | | 409 `production_instance_exists` → CLI re-derives state via `fetchApplication` and falls through to `reconcileExistingDeploy`. | |
| 46 | +| Trigger DNS check | `POST /v1/platform/applications/{appID}/domains/{domainIDOrName}/dns_check` | Fired best-effort once per "Check DNS now" selection to actively kick the check job. Idempotent (no-op if a check is in flight). | |
| 47 | +| Poll deploy status | `GET /v1/platform/applications/{appID}/instances/{envOrInsID}/deploy_status` | Returns `status` plus the three component booleans `dns_ok`, `ssl_ok`, `mail_ok`. The CLI drives three sequential per-component spinners (mail, DNS, SSL) that all share the same five-minute wall-clock cap; each spinner emits a success line as its boolean flips true. A `proxy_ok` defensive check guards the DNS spinner. Polls every 3s. | |
| 48 | +| Retry SSL provisioning | `POST /v1/platform/applications/{appID}/domains/{domainIDOrName}/ssl_retry` | 204 on success. 409 `ssl_retry_throttled` carries `meta.retry_after_seconds` (12-min per-domain throttle). | |
| 49 | +| Retry mail verification | `POST /v1/platform/applications/{appID}/domains/{domainIDOrName}/mail_retry` | 204 on success. 409 `mail_retry_inflight` → poll `deploy_status`. 403 `operation_not_allowed_on_satellite_domain` for satellites. | |
| 50 | +| Save OAuth credentials | `PATCH /v1/platform/applications/{appID}/instances/{instanceID}/config` | Returns the updated config snapshot. Used to persist production `connection_oauth_*` credentials. | |
| 51 | + |
| 52 | +After displaying the DNS records block, when CNAME records are present the CLI prompts "Export DNS records as a BIND zone file? (y/N)". On yes, it writes `./clerk-<domain>.zone` in the current working directory. The file is a standard BIND fragment containing `$ORIGIN`, `$TTL 300`, and one fully-qualified CNAME per record. The default is "no" and the file is overwritten silently on subsequent runs. Most major DNS providers (Cloudflare, Route 53, Google Cloud DNS, and others) support importing BIND zone fragments. The same prompt appears on both new deploys and resumed deploys. |
47 | 53 |
|
48 | 54 | PLAPI errors are translated to typed `CliError`s by `commands/deploy/errors.ts`. The CLI does not auto-retry SSL or mail provisioning — when `deploy_status` polling times out with `ssl_ok` or `mail_ok` still false, the CLI surfaces the component status and instructs the user to rerun `clerk deploy` once DNS propagates. |
49 | 55 |
|
@@ -123,19 +129,19 @@ sequenceDiagram |
123 | 129 |
|
124 | 130 | All endpoints are on the **Platform API** (`/v1/platform/...`) and are live HTTP calls. The deploy command calls the helpers in `lib/plapi.ts` directly. |
125 | 131 |
|
126 | | -| Step | Method | Endpoint | Helper | |
127 | | -| -------------------------- | ------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | |
128 | | -| Auth | n/a | Local config | Token stored from `clerk auth login` or `CLERK_PLATFORM_API_KEY`. | |
129 | | -| Read instance config | `GET` | `/v1/platform/applications/{appID}/instances/{instanceID}/config` | `fetchInstanceConfig` from `lib/plapi.ts`. Discovers enabled `connection_oauth_*` providers. | |
130 | | -| Patch instance config | `PATCH` | `/v1/platform/applications/{appID}/instances/{instanceID}/config` | `patchInstanceConfig`. Writes production OAuth credentials. | |
131 | | -| Read application | `GET` | `/v1/platform/applications/{appID}` | `fetchApplication`. Resolves development and production instance IDs. | |
132 | | -| List production domains | `GET` | `/v1/platform/applications/{appID}/domains` | `listApplicationDomains`. Recovers production domain name and CNAME targets on each run. | |
133 | | -| Validate cloning | `POST` | `/v1/platform/applications/{appID}/validate_cloning` | `validateCloning`. Pre-flights subscription/feature support. | |
134 | | -| Create production instance | `POST` | `/v1/platform/applications/{appID}/production_instance` | `createProductionInstance`. Returns prod instance, primary domain, keys, and `cname_targets[]`. | |
135 | | -| Trigger DNS check | `POST` | `/v1/platform/applications/{appID}/domains/{domainIDOrName}/dns_check` | `triggerDomainDnsCheck`. Fired best-effort when the user picks "Check DNS now" to actively kick the check job. | |
136 | | -| Poll deploy status | `GET` | `/v1/platform/applications/{appID}/instances/{envOrInsID}/deploy_status` | `getDeployStatus`. Polls every 3s; surfaces `dns_ok`/`ssl_ok`/`mail_ok` to the user on timeout. | |
137 | | -| Retry SSL provisioning | `POST` | `/v1/platform/applications/{appID}/domains/{domainIDOrName}/ssl_retry` | `retryApplicationDomainSSL`. Exposed on the API surface; not invoked from the deploy flow yet (handled by re-running). | |
138 | | -| Retry mail verification | `POST` | `/v1/platform/applications/{appID}/domains/{domainIDOrName}/mail_retry` | `retryApplicationDomainMail`. Same — rejected on satellite domains with 403 `operation_not_allowed_on_satellite_domain`. | |
| 132 | +| Step | Method | Endpoint | Helper | |
| 133 | +| -------------------------- | ------- | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | |
| 134 | +| Auth | n/a | Local config | Token stored from `clerk auth login` or `CLERK_PLATFORM_API_KEY`. | |
| 135 | +| Read instance config | `GET` | `/v1/platform/applications/{appID}/instances/{instanceID}/config` | `fetchInstanceConfig` from `lib/plapi.ts`. Discovers enabled `connection_oauth_*` providers. | |
| 136 | +| Patch instance config | `PATCH` | `/v1/platform/applications/{appID}/instances/{instanceID}/config` | `patchInstanceConfig`. Writes production OAuth credentials. | |
| 137 | +| Read application | `GET` | `/v1/platform/applications/{appID}` | `fetchApplication`. Resolves development and production instance IDs. | |
| 138 | +| List production domains | `GET` | `/v1/platform/applications/{appID}/domains` | `listApplicationDomains`. Recovers production domain name and CNAME targets on each run. | |
| 139 | +| Validate cloning | `POST` | `/v1/platform/applications/{appID}/validate_cloning` | `validateCloning`. Pre-flights subscription/feature support. | |
| 140 | +| Create production instance | `POST` | `/v1/platform/applications/{appID}/production_instance` | `createProductionInstance`. Returns prod instance, primary domain, keys, and `cname_targets[]`. | |
| 141 | +| Trigger DNS check | `POST` | `/v1/platform/applications/{appID}/domains/{domainIDOrName}/dns_check` | `triggerDomainDnsCheck`. Fired best-effort when the user picks "Check DNS now" to actively kick the check job. | |
| 142 | +| Poll deploy status | `GET` | `/v1/platform/applications/{appID}/instances/{envOrInsID}/deploy_status` | `getDeployStatus`. Drives the mail, DNS, and SSL sequential spinners in `pollDeployStatus`; each spinner resolves independently within the shared five-minute cap. | |
| 143 | +| Retry SSL provisioning | `POST` | `/v1/platform/applications/{appID}/domains/{domainIDOrName}/ssl_retry` | `retryApplicationDomainSSL`. Exposed on the API surface; not invoked from the deploy flow yet (handled by re-running). | |
| 144 | +| Retry mail verification | `POST` | `/v1/platform/applications/{appID}/domains/{domainIDOrName}/mail_retry` | `retryApplicationDomainMail`. Same — rejected on satellite domains with 403 `operation_not_allowed_on_satellite_domain`. | |
139 | 145 |
|
140 | 146 | ## OAuth Provider Config Format |
141 | 147 |
|
|
0 commit comments