From ce4b6bf38783f114e3792b5e0aa5135694493943 Mon Sep 17 00:00:00 2001 From: aaronmedina-dev Date: Wed, 26 Aug 2026 10:17:57 +0930 Subject: [PATCH] Scope Vercel concurrency groups by project ID The vercel-preview and vercel-production concurrency groups were keyed only on the PR number and the ref respectively. A repo that calls either workflow once per Vercel project put every call into the same group, so the projects fought each other instead of deploying independently. vercel-preview used cancel-in-progress: true, so the second job cancelled the first and only one project ever got a preview. vercel-production used cancel-in-progress: false, so the jobs queued; because GitHub keeps only one pending entry per group, a second push while the first run was in flight evicted the still-pending deploy and dropped it silently. Adding vercel-project-id to both group keys gives each project an independent group. Same-project behaviour is unchanged: previews still supersede on a new commit, production deploys for one project still queue in order. The PR comment marker had the same problem and is now scoped per project, so each project keeps its own comment instead of overwriting another's. --- .github/workflows/vercel-preview.yml | 10 ++++--- .github/workflows/vercel-production.yml | 4 ++- docs/vercel-preview.md | 35 +++++++++++++++++++++++++ docs/vercel-production.md | 33 +++++++++++++++++++++++ 4 files changed, 78 insertions(+), 4 deletions(-) diff --git a/.github/workflows/vercel-preview.yml b/.github/workflows/vercel-preview.yml index ed4bde9..d29e7b1 100644 --- a/.github/workflows/vercel-preview.yml +++ b/.github/workflows/vercel-preview.yml @@ -26,8 +26,10 @@ on: description: "Vercel deployment token" required: true +# Scoped per project so a repo deploying several Vercel projects from one PR +# gets an independent group per project instead of the jobs cancelling each other. concurrency: - group: vercel-preview-${{ github.event.pull_request.number }} + group: vercel-preview-${{ github.event.pull_request.number }}-${{ inputs.vercel-project-id }} cancel-in-progress: true jobs: @@ -73,6 +75,8 @@ jobs: echo "inspect_url=$inspect_url" >> "$GITHUB_OUTPUT" # Posts (or updates in place) a single comment on the PR with the preview URL. + # The marker is scoped per project so each Vercel project keeps its own + # comment rather than overwriting another project's. - name: Comment preview URL on PR env: GH_TOKEN: ${{ github.token }} @@ -82,7 +86,7 @@ jobs: INSPECT_URL: ${{ steps.deploy.outputs.inspect_url }} COMMIT_SHA: ${{ github.event.pull_request.head.sha }} run: | - marker='' + marker="" body="$marker ### ⚡ Preview environment is deploying @@ -91,7 +95,7 @@ jobs: **Preview URL:** ${DEPLOY_URL} **Inspect:** ${INSPECT_URL} - _Deployed commit ${COMMIT_SHA}_" + _Project ${VERCEL_PROJECT_ID}, deployed commit ${COMMIT_SHA}_" comment_id="$(gh api "repos/${REPO}/issues/${PR_NUMBER}/comments" \ --jq "[.[] | select(.body | startswith(\"${marker}\"))][0].id")" diff --git a/.github/workflows/vercel-production.yml b/.github/workflows/vercel-production.yml index 9eb80f9..1e210ee 100644 --- a/.github/workflows/vercel-production.yml +++ b/.github/workflows/vercel-production.yml @@ -26,8 +26,10 @@ on: description: "Vercel deployment token" required: true +# Scoped per project so a repo deploying several Vercel projects from one push +# gets an independent group per project instead of the jobs queueing behind each other. concurrency: - group: vercel-production-${{ github.ref }} + group: vercel-production-${{ github.ref }}-${{ inputs.vercel-project-id }} cancel-in-progress: false jobs: diff --git a/docs/vercel-preview.md b/docs/vercel-preview.md index 63a9ae2..079b767 100644 --- a/docs/vercel-preview.md +++ b/docs/vercel-preview.md @@ -17,6 +17,12 @@ pull request with the preview and inspect URLs. Intended to be called from a |---------------|----------|--------------------------| | vercel-token | ✅ | Vercel deployment token | +#### Concurrency + +Runs are grouped by pull request **and** `vercel-project-id`, with +`cancel-in-progress: true`. A new commit supersedes the in-flight preview for +that project, while previews for other projects are left alone. + #### Example Usage ```yaml @@ -34,3 +40,32 @@ jobs: secrets: vercel-token: ${{ secrets.VERCEL_TOKEN }} ``` + +#### Deploying more than one Vercel project + +Call the workflow once per project. Give each call a distinct +`environment-name`, otherwise every job writes its deployment status and URL to +the same GitHub Environment and the last one to finish wins. + +```yaml +jobs: + deploy-storefront-preview: + uses: aligent/workflows/.github/workflows/vercel-preview.yml@main + with: + vercel-org-id: ${{ vars.VERCEL_ORG_ID }} + vercel-project-id: ${{ vars.VERCEL_PROJECT_ID }} + environment-name: Preview + secrets: + vercel-token: ${{ secrets.VERCEL_TOKEN }} + + deploy-admin-preview: + uses: aligent/workflows/.github/workflows/vercel-preview.yml@main + with: + vercel-org-id: ${{ vars.VERCEL_ORG_ID }} + vercel-project-id: ${{ vars.VERCEL_ADMIN_PROJECT_ID }} + environment-name: Preview - admin + secrets: + vercel-token: ${{ secrets.VERCEL_TOKEN }} +``` + +Each project gets its own PR comment, keyed on the project ID. diff --git a/docs/vercel-production.md b/docs/vercel-production.md index 908513d..05f1651 100644 --- a/docs/vercel-production.md +++ b/docs/vercel-production.md @@ -16,6 +16,12 @@ Deploys a production build to Vercel. Intended to be called from a `push` (or |---------------|----------|--------------------------| | vercel-token | ✅ | Vercel deployment token | +#### Concurrency + +Runs are grouped by ref **and** `vercel-project-id`, with +`cancel-in-progress: false`. Deploys for the same project queue in order, while +deploys for different projects run in parallel. + #### Example Usage ```yaml @@ -34,3 +40,30 @@ jobs: secrets: vercel-token: ${{ secrets.VERCEL_TOKEN }} ``` + +#### Deploying more than one Vercel project + +Call the workflow once per project. Give each call a distinct +`environment-name`, otherwise every job writes its deployment status and URL to +the same GitHub Environment and the last one to finish wins. + +```yaml +jobs: + deploy-storefront-production: + uses: aligent/workflows/.github/workflows/vercel-production.yml@main + with: + vercel-org-id: ${{ vars.VERCEL_ORG_ID }} + vercel-project-id: ${{ vars.VERCEL_PROJECT_ID }} + environment-name: Production + secrets: + vercel-token: ${{ secrets.VERCEL_TOKEN }} + + deploy-admin-production: + uses: aligent/workflows/.github/workflows/vercel-production.yml@main + with: + vercel-org-id: ${{ vars.VERCEL_ORG_ID }} + vercel-project-id: ${{ vars.VERCEL_ADMIN_PROJECT_ID }} + environment-name: Production - admin + secrets: + vercel-token: ${{ secrets.VERCEL_TOKEN }} +```