name: workflow hygiene # Properties of the workflows themselves, checked rather than remembered. # # Today that is one property: every workflow declares a concurrency group that # varies by ref. None of them did until 2026-10-05, and the consequence was not # a slow build — it was that CI stopped being usable for anyone. A session # pushing four versions of a branch queued four complete sets of runs, all of # which had to drain; one PR's 21 contexts settled none in 70 minutes behind a # backlog of 25, and two PRs were merged on locally-executed equivalents # because the gate could not run. One omitted block reintroduces that for the # whole repo, invisibly: the workflow still passes, it just queues forever # under load. # # This job runs on `linux`, which is jetson-hub — deliberately not the dev Mac, # which already serves 13 of this repo's 21 contexts through two runners. It # needs no toolchain and finishes in seconds. on: push: branches: [main] pull_request: paths: - '.github/workflows/**' - 'scripts/check-workflow-concurrency.sh' concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: concurrency-groups: name: every workflow supersedes its own queue runs-on: linux steps: - uses: actions/checkout@v4 # The check must be able to fail, or it is decoration. The self-test # breaks the property both ways against a scratch copy and asserts the # check rejects each. It lives in a script because embedding its Python # in this `run:` block made the file invalid YAML, which would have meant # no CI at all. - name: The check fails closed (self-test) run: ./scripts/check-workflow-concurrency-selftest.sh - name: Every workflow is grouped per ref run: ./scripts/check-workflow-concurrency.sh