1818 SOCKET_SECURITY_MODE : monitor # Options: monitor (non-blocking) or block (fails on vulnerabilities)
1919
2020jobs :
21+ # Detect which file groups changed so downstream jobs can skip when irrelevant.
22+ # Only runs on pull_request — on push/workflow_dispatch it is skipped, which causes
23+ # downstream jobs (via `needs.changes.result == 'skipped'`) to run unconditionally.
24+ changes :
25+ runs-on : ubuntu-latest
26+ if : github.event_name == 'pull_request'
27+ outputs :
28+ source : ${{ steps.filter.outputs.source }}
29+ docker : ${{ steps.filter.outputs.docker }}
30+ vendor : ${{ steps.filter.outputs.vendor }}
31+ steps :
32+ - uses : dorny/paths-filter@fbd0ab8f3e69293af611ebaee6363fc25e6d187d # v4.0.1
33+ id : filter
34+ with :
35+ filters : |
36+ source:
37+ - 'modules/**'
38+ - 'package.json'
39+ - 'yarn.lock'
40+ - 'tsconfig*.json'
41+ - 'lerna.json'
42+ docker:
43+ - 'Dockerfile'
44+ - '.dockerignore'
45+ - 'modules/**'
46+ - 'package.json'
47+ - 'yarn.lock'
48+ - 'lerna.json'
49+ vendor:
50+ - 'modules/argon2/**'
51+
2152 unit-test :
2253 runs-on : ubuntu-latest
54+ needs : [changes]
55+ if : always() && (needs.changes.result == 'skipped' || needs.changes.outputs.source == 'true')
2356
2457 strategy :
2558 fail-fast : false
@@ -146,6 +179,8 @@ jobs:
146179
147180 browser-test :
148181 runs-on : ubuntu-22.04
182+ needs : [changes]
183+ if : always() && (needs.changes.result == 'skipped' || needs.changes.outputs.source == 'true')
149184
150185 steps :
151186 - uses : socketdev/action@v1
@@ -242,6 +277,8 @@ jobs:
242277
243278 docker-build :
244279 runs-on : ubuntu-latest
280+ needs : [changes]
281+ if : always() && (needs.changes.result == 'skipped' || needs.changes.outputs.docker == 'true')
245282
246283 steps :
247284 - uses : actions/checkout@v6
@@ -314,6 +351,8 @@ jobs:
314351
315352 verify-vendor-integrity :
316353 runs-on : ubuntu-latest
354+ needs : [changes]
355+ if : always() && (needs.changes.result == 'skipped' || needs.changes.outputs.vendor == 'true')
317356
318357 steps :
319358 - uses : actions/checkout@v6
@@ -336,6 +375,8 @@ jobs:
336375
337376 dockerfile-check :
338377 runs-on : ubuntu-latest
378+ needs : [changes]
379+ if : always() && (needs.changes.result == 'skipped' || needs.changes.outputs.docker == 'true')
339380
340381 steps :
341382 - uses : socketdev/action@v1
@@ -372,3 +413,27 @@ jobs:
372413 git diff -- . ':!yarn.lock'
373414 exit 1
374415 fi
416+
417+ # Umbrella job that branch protection should require instead of individual jobs.
418+ # Passes when every dependency either succeeded or was intentionally skipped,
419+ # so CI-only PRs (where tests are skipped by path filters) can still merge.
420+ # `changes` is included in needs so a failure there (not a skip) is caught and
421+ # blocks the merge — preventing test jobs from being falsely skipped.
422+ all-checks :
423+ runs-on : ubuntu-latest
424+ if : always()
425+ needs :
426+ - changes
427+ - unit-test
428+ - browser-test
429+ - docker-build
430+ - dockerfile-check
431+ - verify-vendor-integrity
432+ - verify-npm-packages
433+ - code-quality
434+ steps :
435+ - name : All checks passed or skipped
436+ run : |
437+ results='${{ toJSON(needs) }}'
438+ echo "$results"
439+ echo "$results" | jq -e '[.[].result] | all(. == "success" or . == "skipped")'
0 commit comments