From f80f5a6123fba03038e0bd8268bc40f1010f997b Mon Sep 17 00:00:00 2001 From: sidgaikwad Date: Fri, 4 Sep 2026 11:55:06 +0530 Subject: [PATCH 1/2] ci: add permissions, a concurrency group, and pin actions to SHAs - permissions: contents: read. Both jobs only read the repo; the Codecov upload authenticates with its own token, not the workflow token. - concurrency: cancel superseded PR runs. Pushing twice to a PR left the earlier 6-job matrix occupying runners for a result nobody reads. Guarded on pull_request so main pushes still run to completion. - Pin actions/checkout, actions/setup-node and codecov/codecov-action to commit SHAs with version comments. The pins are the exact commits the v4/v4/v5 tags resolve to today, so this changes nothing about what runs. Dependabot already watches the github-actions ecosystem, so it keeps the SHAs current automatically. Co-Authored-By: Claude Opus 5 --- .github/workflows/ci.yml | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a80c7c1..da11333 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,13 +5,24 @@ on: branches: [main] pull_request: +# These jobs only read the repository; the Codecov upload authenticates with +# its own token rather than the workflow token. +permissions: + contents: read + +# Superseded runs on a PR are pointless — the 6-job matrix keeps runners busy +# for a result nobody will look at. Pushes to main still run to completion. +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + jobs: checks: name: Lint, typecheck & build runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: 22 cache: npm @@ -20,7 +31,7 @@ jobs: - run: npm run typecheck - run: npm run build - run: npm run test:coverage - - uses: codecov/codecov-action@v5 + - uses: codecov/codecov-action@0fb7174895f61a3b6b78fc075e0cd60383518dac # v5.5.5 with: files: coverage/lcov.info token: ${{ secrets.CODECOV_TOKEN }} @@ -35,8 +46,8 @@ jobs: node: [20, 22, 24] react: [18, 19] steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ matrix.node }} cache: npm From aad9a6f63bbbbb4f55f02c2f9043b9c98c581ec6 Mon Sep 17 00:00:00 2001 From: sidgaikwad Date: Sat, 12 Sep 2026 22:33:48 +0530 Subject: [PATCH 2/2] ci: give non-PR events their own concurrency group cancel-in-progress: false protects a run that is already executing, but it does not protect a queued one: only a single run per concurrency group may sit pending, so a third push replaces the second push's pending run. With every event sharing a ref-keyed group, two quick pushes to main could lose a CI run outright. Key the group on github.ref for pull_request and on github.run_id for everything else. PRs keep the shared group that makes supersede work; a push to main now gets a group of its own and can neither be cancelled by, nor queued behind, another run. --- .github/workflows/ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da11333..4464505 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,9 +11,15 @@ permissions: contents: read # Superseded runs on a PR are pointless — the 6-job matrix keeps runners busy -# for a result nobody will look at. Pushes to main still run to completion. +# for a result nobody will look at. +# +# PRs share a group keyed on the ref, so a new push supersedes the run it +# replaces. Every other event — notably a push to main — gets a group of its +# own keyed on run_id, because only one run per group may sit pending: with a +# shared group, a third push would discard the second one's queued run even +# though cancel-in-progress is off for pushes. concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.run_id }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: