From 186fbfd89332e3f5bb56e9d930be38d333b045c1 Mon Sep 17 00:00:00 2001 From: Alexey Karimov Date: Mon, 10 Aug 2026 18:56:49 +0500 Subject: [PATCH] ci: validate pull requests before they merge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The workflow only triggered on pushes to main, so a content PR could not be checked until AFTER it merged. That is not hypothetical: #13 merged clean and immediately turned main red, because three spelling issues had no opportunity to surface earlier. Pull requests now run the same checkout / install / spell-check / build steps a deploy runs, and stop before touching AWS. Reusing the one job rather than adding a separate validation workflow means the PR necessarily runs what the deploy will run — a second workflow could drift from it. The three AWS steps are guarded with `github.event_name != 'pull_request'`, so a PR run performs no OIDC exchange, no S3 sync and no CloudFront invalidation. No paths-ignore on the PR trigger, unlike push: skipping a deploy for a change that cannot affect the built site is worthwhile, but skipping VALIDATION is not — a workflow or config change is exactly the kind of thing worth checking on the PR, and the run is cheap. Concurrency is unaffected: github.ref is refs/pull//merge on a PR, so validation runs get their own group and cannot cancel a deploy of main. Note the id-token: write permission stays declared at workflow level and is simply unused on PR runs. Scoping it to a deploy-only job would need either a second build or artifact passing between jobs; happy to do that if the broader permission on PR runs is a concern. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Change-Id: I5cdc568b682e61723dfe0c2ca2142b660cd1b153 --- .github/workflows/deploy.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index ba4b934..7aa0a5f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,6 +1,13 @@ name: Build and Deploy on: + # Pull requests run the SAME checkout / install / spell-check / build steps as a + # deploy, but stop before touching AWS. Without this the workflow only ran on + # pushes to main, so a content PR could not be validated until AFTER it merged — + # which is exactly how a spelling error reached main and broke the deploy. + # Deliberately no paths-ignore here: validating a workflow or config change on the + # PR is cheap and catches breakage before it can affect a deploy. + pull_request: push: branches: [main] # Skip deploys for changes that can't affect the built site. @@ -15,11 +22,14 @@ on: workflow_dispatch: # Required for GitHub OIDC -> AWS IAM role assumption (no stored AWS keys). +# Unused on pull_request runs, where every AWS step is skipped. permissions: id-token: write contents: read concurrency: + # github.ref is refs/pull//merge on a PR, so PR validation runs get their own + # group and never cancel an in-flight deploy of main. group: deploy-${{ github.ref }} cancel-in-progress: true @@ -49,12 +59,14 @@ jobs: node scripts/copy-raw-markdown.mjs - name: Configure AWS credentials (OIDC) + if: github.event_name != 'pull_request' uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }} aws-region: ${{ vars.AWS_REGION }} - name: Sync to S3 + if: github.event_name != 'pull_request' # --acl public-read mirrors the existing s3cmd `-P` behavior. Remove it if the # bucket uses a bucket policy with ACLs disabled (Object Ownership = enforced). run: | @@ -63,6 +75,7 @@ jobs: --acl public-read - name: Invalidate CloudFront + if: github.event_name != 'pull_request' run: | aws cloudfront create-invalidation \ --distribution-id "${{ vars.CLOUDFRONT_ID }}" \