From 681654233ed62097e8558010a85878a154095e4d Mon Sep 17 00:00:00 2001 From: Niek Otten Date: Thu, 23 Jul 2026 16:41:57 +0200 Subject: [PATCH] ci: parallelise jobs at runner capacity >1, keep the two heavy jobs apart (closes #127) 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 --- .gitea/workflows/ci.yaml | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 4ec07a3..84e9f79 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -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 -- 2.54.0