66 branches :
77 - main
88concurrency :
9- group : " ${{ github.workflow }}-${{ github.head_ref || github.ref }}"
9+ group : ' ${{ github.workflow }}-${{ github.head_ref || github.ref }}'
1010 cancel-in-progress : true
1111
12+ # These jobs only check out the repo and run checks, so read access to the
13+ # repo contents is all the GITHUB_TOKEN needs.
14+ permissions :
15+ contents : read
16+
1217jobs :
1318 linting :
1419 name : Run linters
1520 runs-on : ubuntu-latest
21+ strategy :
22+ fail-fast : false
23+ matrix :
24+ job : [lint, prettier, typecheck]
1625 steps :
1726 - name : Check out Git repository
1827 uses : actions/checkout@v5
19- - name : Verify Node version pins match .nvmrc
28+ - name : Verify Node version pins match package.json
2029 run : |
2130 set -euo pipefail
22- expected=$(tr -d '[:space:]' < .nvmrc )
31+ expected=$(node -p "require('./package.json').engines.node.replace(/[^0-9.]/g, '')" )
2332 rc=0
2433 check() {
2534 if [ "$2" != "$expected" ]; then
26- echo "::error file=$1::Node version mismatch: $1 pins '$2' but .nvmrc is '$expected'"
35+ echo "::error file=$1::Node version mismatch: $1 pins '$2' but package.json is '$expected'"
2736 rc=1
2837 fi
2938 }
30- # FROM node:X.Y.Z — service runtime images
39+ # FROM node:X.Y.Z - service runtime images
3140 for f in Dockerfile.bskylink Dockerfile.bskyogcard; do
3241 v=$(grep -oE 'FROM node:[0-9]+\.[0-9]+\.[0-9]+' "$f" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -u)
3342 check "$f" "$v"
3443 done
35- # ENV NODE_VERSION=X.Y.Z — Go images that nvm-install Node for the JS build stage
44+ # ENV NODE_VERSION=X.Y.Z - Go images that nvm-install Node for the JS build stage
3645 for f in Dockerfile.embedr; do
3746 v=$(grep -oE 'NODE_VERSION=[0-9]+\.[0-9]+\.[0-9]+' "$f" | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | sort -u)
3847 check "$f" "$v"
@@ -53,17 +62,33 @@ jobs:
5362 command : pnpm install --frozen-lockfile
5463 attempt_limit : 3
5564 attempt_delay : 2000
56- - name : Lint check
57- run : pnpm lint
58- - name : Prettier check
59- run : pnpm prettier --check .
6065 - name : Check & compile i18n
6166 run : pnpm intl:build
62- - name : Type check
63- run : pnpm typecheck
67+ - name : Lint checks
68+ run : pnpm ${{ matrix.job }}
69+ # Aggregates the matrix results into a single stable check name so branch
70+ # protection can require "Run linters" regardless of how many matrix jobs run.
71+ # The result is asserted in `run` (not `if`) so a malformed expression can
72+ # never silently skip the check and report a false pass.
73+ linting-summary :
74+ name : Run linters
75+ if : always()
76+ needs : [linting]
77+ runs-on : ubuntu-latest
78+ steps :
79+ - name : Require linting to have succeeded
80+ env :
81+ RESULT : ${{ needs.linting.result }}
82+ run : |
83+ echo "linting result: $RESULT"
84+ test "$RESULT" = "success"
6485 testing :
6586 name : Run tests
6687 runs-on : ubuntu-latest
88+ strategy :
89+ fail-fast : false
90+ matrix :
91+ shard : [1, 2, 3, 4]
6792 steps :
6893 - name : Check out Git repository
6994 uses : actions/checkout@v5
@@ -83,4 +108,20 @@ jobs:
83108 run : pnpm intl:build
84109 - name : Run tests
85110 run : |
86- NODE_ENV=test pnpm test --forceExit
111+ NODE_ENV=test pnpm test --forceExit --shard=${{ matrix.shard }}/${{ strategy.job-total }}
112+ # Aggregates the sharded test results into a single stable check name so branch
113+ # protection can require "Run tests" regardless of how many shards run.
114+ # The result is asserted in `run` (not `if`) so a malformed expression can
115+ # never silently skip the check and report a false pass.
116+ testing-summary :
117+ name : Run tests
118+ if : always()
119+ needs : [testing]
120+ runs-on : ubuntu-latest
121+ steps :
122+ - name : Require testing to have succeeded
123+ env :
124+ RESULT : ${{ needs.testing.result }}
125+ run : |
126+ echo "testing result: $RESULT"
127+ test "$RESULT" = "success"
0 commit comments