ci: parallelise jobs at runner capacity >1, keep the two heavy jobs apart (closes #127)
CI / lint (pull_request) Successful in 2m5s
CI / build (pull_request) Successful in 1m33s
CI / unit (pull_request) Successful in 1m48s
CI / frontend (pull_request) Successful in 3m57s
CI / mutation (pull_request) Successful in 7m14s
CI / verify-stack (pull_request) Successful in 9m1s

The six jobs have no data dependencies, so they now schedule concurrently on the
capacity-2 runner. Guard against the two memory-heavy jobs (mutation + verify-stack)
co-scheduling and re-triggering the e2e OOM (#126): order verify-stack after mutation
via needs, with if: !cancelled() so it still runs when the ratchet fails. Add a
concurrency group so a new push supersedes the previous run instead of wasting a slot.

closes #127
This commit is contained in:
not
2026-07-23 16:41:57 +02:00
parent 88338396f6
commit 681654233e
+18 -4
View File
@@ -9,6 +9,12 @@ on:
permissions:
contents: read
# Supersede stale runs: a new push to the same branch/PR cancels the previous run, so the runner's
# concurrency slots aren't spent on commits nobody is waiting for (refs #127).
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# Self-hosted runner — see docs/runbooks/ci.md for the runner setup.
# `uses:` are absolute, tag-pinned URLs (CLAUDE.md §8.7 / §15).
@@ -129,12 +135,20 @@ jobs:
path: services/bff/StrykerOutput/**/reports/mutation-report.html
if-no-files-found: warn
# One stage for every check that needs the live stack. On the single self-hosted
# runner jobs run sequentially, so booting OpenZaak once (instead of once per job)
# is the cheapest layout (issue #58). No setup-dotnet: the ACL test runs in a built
# image and everything reaches services by container IP. Needs Docker + egress
# One stage for every check that needs the live stack. Booting OpenZaak once (instead
# of once per job) is the cheapest layout (issue #58). No setup-dotnet: the ACL test runs
# in a built image and everything reaches services by container IP. Needs Docker + egress
# (base images, nuget, selectielijst.openzaak.nl).
#
# `needs: [mutation]` is NOT a data dependency — it serialises the two memory-heavy jobs so
# they never co-schedule now the runner has capacity >1. A concurrent Stryker run + full-stack
# bring-up + Playwright browser on one host is what OOMs the e2e (commit d5e5fa2, #126). The
# light .NET/frontend jobs have no `needs`, so they still parallelise up to runner capacity.
# `if: !cancelled()` keeps verify-stack running even when the mutation ratchet fails (so we don't
# lose its signal) while still honouring run cancellation from the concurrency group above.
verify-stack:
needs: [mutation]
if: ${{ !cancelled() }}
runs-on: ubuntu-latest
steps:
- uses: https://github.com/actions/checkout@v4