feat: add vercel-build action input for local Vercel build step - #361
Conversation
Add track for opt-in vercel-build action input that runs vercel pull and vercel build locally before deployment, then routes through the existing prebuilt deploy path. Refs #360
|
Deploy preview for file ready!
Deployed with vercel-action |
|
Deploy preview for static ready!
Deployed with vercel-action |
|
Deploy preview for express-basic-auth ready!
Deployed with vercel-action |
There was a problem hiding this comment.
Code Review
This pull request introduces the vercel-build feature, which enables local execution of the Vercel CLI workflow within GitHub Actions. The changes include a new track entry, metadata, a detailed implementation plan, and a product specification. Feedback focuses on enhancing security by using environment variables for tokens, ensuring team scope propagation with the --scope flag, and supporting custom output directories via the --output flag.
Add a new boolean action input `vercel-build` that opts into running `vercel pull` + `vercel build` locally before deployment. When combined with `prebuilt: true`, the action fails fast at config parse time since the two flags are conceptually mutually exclusive. T001+T002+T003 of auto-vercel-build-20260430. Refs #360
…rator
Add new module src/vercel-build.ts:
- BuildFailedError with stderr-tail capture (last 20 lines, fallback to
stdout when stderr is empty)
- runVercelPull(config): `vercel pull --yes --environment=<target>`
- runVercelBuild(config): `vercel build [--prod]` with buildEnv merged
into the exec environment
- runBuildStep(config): pull → build sequencing, returns
{ prebuilt: true, vercelOutputDir } so callers can route through the
existing prebuilt deploy path
T004–T009 of auto-vercel-build-20260430.
Refs #360
Wire runBuildStep into run() before deployment when vercel-build: true. On success, mutate the config to set prebuilt=true and vercelOutputDir so the existing API client uploads the produced .vercel/output. On BuildFailedError, post a build-failure comment (PR or commit) with the captured stderr tail (last 20 lines), then rethrow so the action exits non-zero. Also export run() and guard the top-level invocation behind `process.env.VITEST` so tests can drive run() without triggering the module-level fire-and-forget call. T010-T013 of auto-vercel-build-20260430. Refs #360
- Integration test (src/__integration__/vercel-build.test.ts): 3 tests covering runBuildStep output, end-to-end deploy via emulator with the prebuilt path, and fail-fast on pull error. - README: `vercel-build` input row in the API inputs table, plus a new "Method 4 - Build inside the action" section with a workflow example and notes on mutual exclusivity, build-env, target=production, and failure-comment behavior. - dist/: regenerated via @vercel/ncc. Coverage: vercel-build.ts 94.39% (NFR-4 target >80%), suite 272 tests passing. T014-T016 of auto-vercel-build-20260430. Refs #360
Address code-review findings on PR #361: - Critical (security): Stop passing the Vercel token via `-t <token>` argv, which @actions/exec echoes verbatim to stdout via toolrunner's [command]... line before the runner's secret mask can claim it. Pass the token through the VERCEL_TOKEN environment variable instead — the documented non-interactive auth path per the Vercel CLI source (packages/cli/src/commands/build/index.ts:309). Also set silent: true on the ExecOptions to suppress the [command] echo entirely. - Important (security): `stderrTail` is interpolated into a Markdown fenced code block in PR/commit comments. Untrusted build output containing triple-backticks could close the fence and inject Markdown. Escape any run of 3+ backticks before interpolation. - Important (tests): Add three orchestration tests in run-build.test.ts: 1. Asserts createBuildFailureCommentOnPullRequest is called with the BuildFailedError's exitCode and stderrTail (AC-4 wiring) 2. Asserts createBuildFailureCommentOnCommit is called for push events instead of the PR helper 3. Asserts no failure comment is posted when github-comment is false - Add 4 vercel-build.test.ts tests asserting the token is NOT in argv and IS in env, plus that exec runs with silent: true. dist/ rebuilt. Suite: 280 tests passing (was 272). Refs #360
|
Deploy preview for angular ready!
Deployed with vercel-action |
Previously, when a user combined `vercel-build: true` with a custom `vercel-output-dir`, the build wrote to the default `.vercel/output` while the prebuilt deploy looked at `config.vercelOutputDir` — silently mismatched. The user's vercel-output-dir was effectively ignored during the build. Fix: - runVercelBuild now passes `--output <dir>` to `vercel build` whenever `config.vercelOutputDir` is set (relative paths resolved against working-directory; absolute paths used as-is). - runBuildStep now returns the user's `vercelOutputDir` (resolved) instead of always defaulting to `<workingDir>/.vercel/output`, so the deploy reads from the same place the build wrote to. - Spec FR-2 + new AC-7 + plan architecture diagram updated to reflect `[--output <dir>]` and the VERCEL_TOKEN env transport. - README documents both the env-var auth path and the --output passthrough. - 5 new unit tests covering --output omission, absolute path, and relative-path resolution. Addresses gemini-code-assist[bot] review threads on PR #361. Refs #360
There was a problem hiding this comment.
Pull request overview
Adds an opt-in vercel-build input to run a local Vercel CLI build (vercel pull → vercel build) inside the GitHub Action, then deploy the resulting .vercel/output via the existing prebuilt upload path, including build-failure PR/commit comments and expanded test coverage.
Changes:
- Introduces
vercel-buildinput + config/type wiring and mutual exclusivity withprebuilt. - Adds
src/vercel-build.tsrunner (pull/build orchestration) and build-failure comment helpers. - Updates docs/tests/integration tests and rebuilds
dist/outputs.
Reviewed changes
Copilot reviewed 16 out of 22 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/vercel-build.ts | New local vercel pull/vercel build runner and BuildFailedError plumbing. |
| src/types.ts | Adds vercelBuild flag to ActionConfig. |
| src/index.ts | Runs build step before deploy and posts build-failure comments; exports run(). |
| src/github-comments.ts | Adds PR/commit build-failure comment helpers with fenced-block escaping. |
| src/config.ts | Parses vercel-build input and enforces vercel-build XOR prebuilt. |
| src/tests/vercel-build.test.ts | Unit tests for build runner behavior, args/env handling, and error tails. |
| src/tests/run-build.test.ts | Orchestration tests ensuring build runs before deploy and failure comments post. |
| src/tests/github-comments.test.ts | Tests for new build-failure comment formatting + escaping. |
| src/tests/config.test.ts | Tests for vercel-build parsing and mutual exclusivity with prebuilt. |
| src/integration/vercel-build.test.ts | emulate.dev integration coverage for the build-step + prebuilt deploy boundary. |
| dist/vercel-build.d.ts | Generated declarations for the new build module. |
| dist/types.d.ts | Generated declarations for updated ActionConfig. |
| dist/index.js | Rebuilt ncc bundle including new feature and exports. |
| dist/index.d.ts | Exposes run() in the published type surface. |
| dist/github-comments.d.ts | Declarations for new build-failure comment functions. |
| action.yml | Adds vercel-build action input. |
| README.md | Documents vercel-build and adds “Method 4 - Build inside the action” example. |
| .please/docs/tracks/active/auto-vercel-build-20260430/spec.md | Track spec documenting requirements/acceptance criteria. |
| .please/docs/tracks/active/auto-vercel-build-20260430/plan.md | Implementation plan and progress log for the track. |
| .please/docs/tracks/active/auto-vercel-build-20260430/metadata.json | Track metadata for #360/#361. |
| .please/docs/tracks.jsonl | Registers the new track as active. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Move track active/ → completed/ - Update metadata: status=review, updated_at, pr=#361 - Update tracks.jsonl: section=completed, phase=finalize - Sync to product-specs: SPEC-001 deployment/vercel-build.md (created) - Append retrospective + tech-debt items (TD-001 vercel-cli token transport, TD-002 e2e gap) Refs #360
There was a problem hiding this comment.
No issues found across 22 files
Requires human review: This is a significant feature addition that modifies the core execution path in src/index.ts and introduces new external CLI orchestration. Such changes require human review.
Architecture diagram
sequenceDiagram
participant GH as GitHub Actions Runner
participant CFG as getActionConfig
participant BR as NEW: runBuildStep (vercel-build.ts)
participant CLI as Vercel CLI (npx)
participant API as Vercel API Client
participant GHA as GitHub API
Note over GH,GHA: Configuration & Initialization
GH->>CFG: Fetch Action Inputs
CFG->>CFG: CHANGED: Validate vercel-build XOR prebuilt
CFG-->>GH: ActionConfig object
alt NEW: vercel-build is true
Note over GH,CLI: Local Build Workflow (FR-2)
GH->>BR: runBuildStep(config)
BR->>CLI: NEW: vercel pull --environment=[target]
Note right of CLI: Auth via VERCEL_TOKEN env var (NFR-3)
CLI-->>BR: project settings
BR->>CLI: NEW: vercel build [--prod] [--output dir]
Note right of CLI: Forward build-env & scope (FR-6, FR-7)
alt Build Success
CLI-->>BR: 0 (Success)
BR-->>GH: { prebuilt: true, vercelOutputDir }
Note over GH: Mutate config to treat as prebuilt
else Build Failure
CLI-->>BR: Non-zero exit code
BR-->>GH: throw BuildFailedError (with stderr tail)
opt github-comment is true
GH->>GHA: NEW: postBuildFailureComment()
Note right of GHA: Truncated tail + escape backticks
end
Note over GH: Action fails (setFailed)
end
end
Note over GH,API: Deployment Phase
GH->>API: createVercelClient(config)
GH->>API: client.deploy(config, context)
alt prebuilt is true (from input OR build step)
API->>API: Upload .vercel/output artifacts
else source deployment (default)
API->>API: Upload source files for remote build
end
API-->>GH: deploymentUrl
There was a problem hiding this comment.
4 issues found across 25 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="src/github-comments.ts">
<violation number="1" location="src/github-comments.ts:139">
P3: The failure comment body is reused for commit comments but contains PR-only wording, which produces incorrect messaging on push events.</violation>
</file>
<file name="README.md">
<violation number="1" location="README.md:70">
P3: The internal README link for `vercel-build` points to the wrong anchor, so navigation to the new section breaks.</violation>
</file>
<file name="dist/index.js">
<violation number="1" location="dist/index.js:99784">
P1: The `!process.env.VITEST` guard will silently prevent the action from executing in any workflow where the `VITEST` environment variable is set — which Vitest sets automatically. Repositories that run Vitest in the same job or share env vars across steps will hit this. Use a more specific guard such as a dedicated internal env var set by the test harness (e.g., `__VERCEL_ACTION_TEST`), or check `require.main === module`.</violation>
</file>
<file name="src/config.ts">
<violation number="1" location="src/config.ts:90">
P1: Missing mutual-exclusivity check: `vercel-build: true` combined with a non-empty `vercel-args` will silently build locally and then deploy via the CLI path (which ignores the prebuilt output). Add a fail-fast validation here, similar to the `prebuilt` check, to reject the `vercel-build` + `vercel-args` combination.</violation>
</file>
Architecture diagram
sequenceDiagram
participant Runner as Action Runner
participant GH as GitHub API
participant CLI as Vercel CLI (npx)
participant Vercel as Vercel API
Note over Runner: NEW: Validate vercel-build XOR prebuilt
alt vercel-build: true
Runner->>CLI: NEW: vercel pull --environment (env: VERCEL_TOKEN)
Note right of CLI: CLI runs with silent: true to hide tokens
CLI-->>Runner: Exit status
Runner->>CLI: NEW: vercel build (env: VERCEL_TOKEN + build-env)
Note right of CLI: Optional --output dir if vercel-output-dir set
CLI-->>Runner: Output + Exit code
alt NEW: Build Failure (Exit > 0)
Runner->>Runner: Capture last 20 lines of stderr
Runner->>GH: NEW: Post failure comment to PR/Commit
Note over Runner,GH: Markdown escaped to prevent fence breakout
Runner-->>Runner: Throw BuildFailedError (Stop)
else Build Success
Runner->>Runner: CHANGED: Mutate config to prebuilt = true
end
end
Runner->>Vercel: deploy() (via @vercel/client)
Note right of Vercel: If prebuilt, uploads .vercel/output artifact
Vercel-->>Runner: Deployment Metadata / URL
Runner-->>Runner: setOutput(preview-url)
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
…ld-step # Conflicts: # .please/docs/tracks.jsonl # dist/index.js # dist/index.js.map
Apply 5 review suggestions from copilot + cubic-dev-ai on PR #361: - src/vercel-build.ts: bound captured stdout/stderr to ~64 KB per stream (appendBounded helper). Long vercel build runs no longer risk runner OOM; the stderrTail tail-line behavior is preserved. - src/index.ts: replace negative `!process.env.VITEST` auto-invoke guard with positive `process.env.GITHUB_ACTIONS === 'true'` check. The previous guard would silently disable the action in any workflow that happens to set VITEST. GITHUB_ACTIONS is the canonical runner-set sentinel. - src/config.ts: add fail-fast mutex between `vercel-build: true` and non-empty `vercel-args`. Without it, the action would build locally via the prebuilt path then route the deploy through the CLI path, silently ignoring the local build output. - src/github-comments.ts: change build-failure comment wording from 'this pull request' to 'this workflow run' so the same body works for both PR comments and commit comments (push events). - README.md: fix broken `vercel-build` anchor link to use the actual GitHub-rendered slug (`#method-4---build-inside-the-action-vercel-build`). 3 new tests: vercel-args mutex (positive + whitespace edge case), huge-stderr bounded buffer. Suite: 305 tests passing (was 302). Lint clean, tsc clean. dist/ rebuilt. Refs #360
There was a problem hiding this comment.
0 issues found across 9 files (changes from recent commits).
Requires human review: This is a significant feature addition that modifies the core deployment execution path and orchestration logic. While opt-in, it requires architectural context to ensure subprocess management and/or
…t auto-invocation on import Agent-Logs-Url: https://github.com/amondnet/vercel-action/sessions/e840b930-a078-4381-91dc-06dc24402e36 Co-authored-by: amondnet <1964421+amondnet@users.noreply.github.com>
There was a problem hiding this comment.
0 issues found across 2 files (changes from recent commits).
Requires human review: This is a significant new feature that adds local process execution and modifies the core orchestration flow. While opt-in, it requires human review of the architectural changes.
|


Track
auto-vercel-build-20260430.please/docs/tracks/active/auto-vercel-build-20260430/spec.md.please/docs/tracks/active/auto-vercel-build-20260430/plan.mdRefs #360
Summary
Add an opt-in
vercel-buildaction input that, when set totrue, executes the official Vercel CLI workflow locally before deployment:vercel pull --environment=<target>→vercel build→ upload.vercel/outputvia the existing prebuilt deploy path.This mirrors the Vercel KB recommended GitHub Actions workflow and lets users build inside CI (with their own secrets and runtime) instead of relying on Vercel's remote build.
Behavior
vercel-buildprebuiltfalse(default)truefalsevercel pull+vercel buildlocally, then deploy.vercel/outputas prebuilttruetrueStatus
Summary by cubic
Adds an opt-in
vercel-buildinput to runvercel pullandvercel buildinside the action, then deploy.vercel/outputor a customvercel-output-dirvia the prebuilt path. Adds failure comments for broken builds, keeps current behavior by default, and hardens token handling. Addresses #360.New Features
vercel-build(default:false): runsvercel pull --environment=<target>→vercel build(--prodfor production; respects--output <dir>whenvercel-output-diris set), then uploads the build output; on failure, exits non-zero and posts a short PR/commit comment (when enabled).prebuiltand with a non-emptyvercel-args; both fail fast with a clear error at config parse time.build-envtovercel buildand passes--scopewhen a team scope is set.Bug Fixes
VERCEL_TOKENwith@actions/execsilent: trueto avoid token leakage; escape triple backticks in failure comments to prevent Markdown injection.GITHUB_ACTIONSin the Vitest unit project to prevent auto-invokingrun()on import.dist/to match source; no behavior change.Written for commit faeeff0. Summary will update on new commits. Review in cubic
Verification Checklist
Manual verification (run after T013):
example/nextjs, setvercel-build: 'true',prebuilt: 'false'. Run the action against a real Vercel project (preview token). Expect: log showsvercel pullthenvercel buildinvocations,.vercel/outputis uploaded, deployment URL returned.target: production+vercel-build: 'true'. Expect:vercel pull --environment=productionandvercel build --prodinvoked.vercel-build: 'true'ANDprebuilt: 'true'. Expect: action fails immediately with a clear conflict message; no API calls made.vercel-build: 'true'+vercel-output-dir: 'custom/out'. Expect:vercel build --output <abs>/custom/outinvoked, deploy reads from same path.vercel buildfails. Expect: action exits non-zero, GitHub Actions log shows the build error, PR comment is posted with truncated tail (whengithub-comment: true).github-comment: falsesuppression: Withvercel-build: 'true'andgithub-comment: 'false', trigger a build failure. Expect: action fails non-zero, no PR/commit comment posted.vercel-buildunset (orfalse), run an existing-style deployment. Expect: identical behavior to current main branch — novercel pull/vercel buildinvocations.VERCEL_TOKENenv var (never via argv).Automated:
pnpm test— all 285 tests passingpnpm test --coverage—src/vercel-build.ts94%+ coveragepnpm run lint— 0 errorspnpm run build— clean dist/ rebuild