diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1721270..078121c2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -152,6 +152,10 @@ jobs: needs: [checks] if: needs.checks.result == 'success' timeout-minutes: 20 + env: + VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} + VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} + VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} steps: - uses: actions/checkout@v4 with: @@ -170,10 +174,6 @@ jobs: echo "stale=false" >> "$GITHUB_OUTPUT" - name: Require Vercel credentials if: steps.tip.outputs.stale != 'true' - env: - VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} run: | set -euo pipefail missing=() @@ -184,17 +184,29 @@ jobs: echo "::error::Missing repo secrets for gated deploy: ${missing[*]}. Add them under Settings → Secrets, then re-run this workflow." exit 1 fi + # Fail closed on obvious paste mistakes (must be team_/prj_ from .vercel/project.json). + case "$VERCEL_ORG_ID" in team_*) ;; *) + echo "::error::VERCEL_ORG_ID must look like team_… (from .vercel/project.json after vercel link)." + exit 1 + ;; + esac + case "$VERCEL_PROJECT_ID" in prj_*) ;; *) + echo "::error::VERCEL_PROJECT_ID must look like prj_… (from .vercel/project.json after vercel link)." + exit 1 + ;; + esac + - name: Install Vercel CLI + if: steps.tip.outputs.stale != 'true' + run: npm install --global vercel@41 - name: Deploy production if: steps.tip.outputs.stale != 'true' - env: - VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} - VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }} - VERCEL_PROJECT_ID: ${{ secrets.VERCEL_PROJECT_ID }} run: | set -euo pipefail - npx --yes vercel@41 pull --yes --environment=production --token="$VERCEL_TOKEN" - npx --yes vercel@41 build --prod --token="$VERCEL_TOKEN" - npx --yes vercel@41 deploy --prebuilt --prod --token="$VERCEL_TOKEN" + # Canonical CI link (Vercel KB): env VERCEL_*_ID + pull → build → deploy --prebuilt. + # "Could not retrieve Project Settings" usually means bad/expired token or wrong IDs (403). + vercel pull --yes --environment=production --token="$VERCEL_TOKEN" + vercel build --prod --token="$VERCEL_TOKEN" + vercel deploy --prebuilt --prod --token="$VERCEL_TOKEN" requeue: runs-on: ubuntu-latest diff --git a/docs/CUTOVER-MAIN-ONLY.md b/docs/CUTOVER-MAIN-ONLY.md index a2559166..ee5109c8 100644 --- a/docs/CUTOVER-MAIN-ONLY.md +++ b/docs/CUTOVER-MAIN-ONLY.md @@ -5,9 +5,10 @@ Status after agent delivery (2026-07-31): - [x] Code PR opened (main-only cutover) — see PR targeting `main` - [x] `pnpm configure:branch-protection` applied on `main` (required: `checks` + `migration-lock`, `strict=false`, 0 reviews) - [x] No open PRs targeting `stage` at cutover time -- [ ] Repo secrets still needed: - - `VERCEL_TOKEN`, `VERCEL_ORG_ID`, `VERCEL_PROJECT_ID` (deploy job fail-closed until set) - - `POOL_GITHUB_TOKEN` (PAT: `actions:write` + `issues:write` + `contents:read`) — `PROMOTE_GITHUB_TOKEN` already exists; reuse/rename if scopes cover Actions variables, else mint a new PAT +- [x] Repo secrets present (`VERCEL_*`, `POOL_GITHUB_TOKEN`) +- [x] `VERCEL_ORG_ID` / `VERCEL_PROJECT_ID` synced from local `.vercel/project.json` (`vercel link`) +- [ ] Confirm `ci.yml` deploy job green after token+IDs are correct + - Misleading CLI error *"Could not retrieve Project Settings"* usually means **403** (bad/expired `VERCEL_TOKEN` or wrong IDs) — regenerate token at vercel.com/account/tokens if deploy still fails After the cutover PR merges to `main`: