| id | SPEC-002 | |
|---|---|---|
| level | V_M | |
| domain | deployment | |
| feature | spec | |
| depends | ||
| conflicts | ||
| traces | ||
| created_at | 2026-04-30 00:58:55 UTC | |
| updated_at | 2026-04-30 00:58:55 UTC | |
| source_tracks |
|
Defines how the action selects and runs a Vercel deployment. The default path is the stable Vercel CLI; an opt-in experimental API path using @vercel/client is available for users who accept the risk of an internal Vercel package without semver guarantees.
The system MUST expose an experimental-api boolean action input that defaults to false.
- GIVEN the action is invoked from a workflow
- WHEN the user does not set
experimental-api - THEN the action behaves as if
experimental-api: falsehad been set explicitly
The system MUST route to the Vercel CLI client (VercelCliClient) whenever experimental-api is false or unset, regardless of whether vercel-args is provided.
- GIVEN
experimental-apiisfalseor unset - WHEN the action selects a deployment client
- THEN it returns
VercelCliClientand logsUsing CLI-based deployment
The system MUST route to the API client (VercelApiClient) only when experimental-api is true, and MUST emit a single core.warning per run stating that API mode is experimental and may break across @vercel/client updates.
- GIVEN
experimental-apiistrue - WHEN the action selects a deployment client
- THEN it returns
VercelApiClientand emits exactly onecore.warningreferencing@vercel/clientand the experimental nature
The system MUST fail fast at config-parse time with a clear error naming both inputs when experimental-api is true and vercel-args is non-empty.
- GIVEN
experimental-api: trueandvercel-args: --prodare both set - WHEN the action parses inputs
- THEN it throws a configuration error before any deployment side effects, mentioning both
experimental-apiandvercel-args
The system MUST honor the existing vercel-args CLI passthrough when experimental-api is false, routing to VercelCliClient and forwarding the args verbatim.
- GIVEN
experimental-apiisfalseandvercel-argscontains a non-empty string - WHEN the action runs
- THEN
VercelCliClientis constructed and the provided args are passed to the underlyingvercelCLI invocation
The system MUST surface the deployment mode on ActionConfig as a discriminated union ({ kind: 'cli', vercelArgs } or { kind: 'experimental-api' }) so that the (experimental-api, vercel-args) mutual-exclusion is unrepresentable at the type level.
- GIVEN
getActionConfig()parses raw action inputs - WHEN the parsing succeeds
- THEN the returned
ActionConfig.deploymentis exactly one variant of the union and the variant matches the user's input
The system MUST keep action.yml input descriptions and deprecation messages aligned with the current routing semantics — vercel-args and scope are not deprecated under the CLI-default model, while legacy zeit-* / now-* inputs remain deprecated.
- GIVEN a user reads
action.ymlin their editor or browser - WHEN they look at
vercel-args,scope, andexperimental-api - THEN each has a meaningful description, no misleading deprecation copy on
vercel-args/scope, and theexperimental-apidescription names the mutual-exclusion rule
The system MUST provide README documentation that explains the CLI default, the experimental-api opt-in, the experimental warning, the mutual-exclusion rule, and a migration note for users coming from the previous API-default behavior.
- GIVEN a user opens README.md to learn how to deploy
- WHEN they read the "Deployment Mode" section
- THEN they see CLI documented as the default,
experimental-api: truedocumented as the opt-in, the warning text quoted, the mutual-exclusion rule stated, and a migration note for previous v42 users
The system SHOULD preserve deployment output parity (preview-url, preview-name, deployment-id) between API mode and the previous API-default behavior whenever experimental-api: true is set.
The system SHOULD ship the routing-default change as a semver MINOR release. No public API contract is broken; only default behavior shifts. The migration is documented in release notes and the README.
The system SHOULD maintain ≥80% test coverage for the routing factory and the new config-parsing logic, including the four-case routing matrix and the mutual-exclusion error.