@@ -133,94 +133,10 @@ jobs:
133133 path : artifacts/coverage/data/contract
134134 if-no-files-found : error
135135
136- # Runtime lane of the parity matrix (creates real containers via Docker) on
137- # push/PR, SCOPED to the commands affected by the change: the full matrix takes
138- # ~45 min, so the devtool parity-affected mapping reduces the diff to a
139- # PARITY_COMMAND allowlist (or "all"/"none"). The daily parity-runtime-full job
140- # is the backstop that always runs the whole thing.
141- parity-runtime-shard :
142- if : github.event_name == 'push' || github.event_name == 'pull_request'
143- runs-on : ubuntu-latest
144- needs : lint-and-test
145- strategy :
146- # Split the affected runtime cases across independent runners (each with its
147- # own docker daemon). fail-fast off so one shard's failure still reports the
148- # others. The harness selects this shard's slice via PARITY_SHARD_INDEX.
149- fail-fast : false
150- matrix :
151- shard : [0, 1]
152- env :
153- PARITY_RUNTIME_TIMEOUT : " 10m"
154- # Two shards, each running two cases at a time: the per-case isolation
155- # (unique id-labels / COMPOSE_PROJECT_NAME / BUILDX_BUILDER) makes -parallel 2
156- # safe on a 2-core runner now that each runner only owns half the cases.
157- PARITY_PARALLEL : " 2"
158- PARITY_SHARD_INDEX : ${{ matrix.shard }}
159- PARITY_SHARD_TOTAL : " 2"
160- steps :
161- - uses : actions/checkout@v7
162- with :
163- submodules : recursive
164- # Full history so the diff base (PR base / previous push) is present.
165- fetch-depth : 0
166- # devtool (the affected-commands mapping) runs before the composite setup,
167- # so it needs the Go toolchain here.
168- - uses : actions/setup-go@v6
169- with :
170- go-version-file : go.mod
171- - name : Determine affected parity commands
172- id : affected
173- run : |
174- if [ "${{ github.event_name }}" = "pull_request" ]; then
175- base="${{ github.event.pull_request.base.sha }}"; head="${{ github.event.pull_request.head.sha }}"
176- else
177- base="${{ github.event.before }}"; head="${{ github.sha }}"
178- fi
179- go run ./cmd/devtool parity-affected-commands "$base" "$head" >> "$GITHUB_OUTPUT"
180- # Toolchain + runner prep + reference oracle, shared with parity-runtime-full.
181- - if : steps.affected.outputs.run == 'true'
182- uses : ./.github/actions/setup-parity-runtime
183- with :
184- repo-token : ${{ secrets.GITHUB_TOKEN }}
185- - if : steps.affected.outputs.run == 'true'
186- env :
187- PARITY_COMMAND : ${{ steps.affected.outputs.commands }}
188- run : task parity:runtime
189- - if : always() && steps.affected.outputs.run == 'true'
190- run : |
191- mkdir -p artifacts
192- git -C reference rev-parse HEAD > artifacts/reference-commit.txt
193- - uses : actions/upload-artifact@v7
194- if : always() && steps.affected.outputs.run == 'true'
195- with :
196- name : parity-runtime-v0.88.0-shard-${{ matrix.shard }}
197- path : artifacts/
198- if-no-files-found : error
199- - if : always() && steps.affected.outputs.run == 'true'
200- run : task clean
201-
202- # Stable required-check name aggregating the sharded runtime lane, so sharding
203- # does not change the check name branch protection depends on.
204- parity-runtime :
205- if : always() && (github.event_name == 'push' || github.event_name == 'pull_request')
206- runs-on : ubuntu-latest
207- needs : parity-runtime-shard
208- steps :
209- - name : Gate on all runtime shards
210- run : |
211- result="${{ needs.parity-runtime-shard.result }}"
212- echo "parity-runtime-shard aggregate result: $result"
213- case "$result" in
214- success|skipped) exit 0 ;;
215- *) echo "one or more runtime shards failed"; exit 1 ;;
216- esac
217-
218- # Gate the expensive daily lanes on "did the repo change today?". A manual dispatch
219- # always runs; a scheduled run only proceeds if HEAD has a commit within the last
220- # day (devtool daily-changed). On a private/billed repo this skips the full
221- # runtime matrix + publish on quiet days. Runs on schedule/dispatch so it is never
222- # skipped for those events — the heavy jobs `needs:` it, and a skipped need would
223- # skip them regardless of its output.
136+ # "Did the repo change today?" gate for the expensive daily lanes. Manual dispatch
137+ # always runs; a scheduled run only proceeds when HEAD has a commit within the last
138+ # day (devtool daily-changed) — on a private/billed repo this skips the daily matrix
139+ # on quiet days. Runs on schedule/dispatch so the daily lanes' `needs:` is satisfied.
224140 daily-changes :
225141 if : github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
226142 runs-on : ubuntu-latest
@@ -240,66 +156,101 @@ jobs:
240156 go run ./cmd/devtool daily-changed >> "$GITHUB_OUTPUT"
241157 fi
242158
243- # Full runtime parity matrix. Runs once a day (schedule, only when the repo changed
244- # — see daily-changes) and on manual dispatch — the exhaustive backstop for the
245- # scoped push/PR job above. Sharded across independent runners (same
246- # PARITY_SHARD_INDEX/TOTAL harness as the push/PR lane) so the 175-case matrix no
247- # longer contends for one runner's CPU/disk/daemon, which was starving the
248- # container setups and failing downstream exec cases. PARITY_SHARD_TOTAL MUST equal
249- # the length of matrix.shard — parity_sharding_workflow_test.go enforces that, so a
250- # mismatch can't silently drop cases.
251- parity-runtime-full :
159+ # Single sharded runtime parity matrix, parameterized by event:
160+ # push/PR — SCOPED to the commands the diff can affect (devtool parity-affected),
161+ # run with the plain binary: a fast gate (the full matrix is ~45 min).
162+ # daily — the FULL matrix with the instrumented binary, so one run gates parity
163+ # AND measures coverage; daily-changes keeps it off on quiet days.
164+ # 4 shards across independent runners (each its own docker daemon) so the matrix
165+ # never contends for one runner's CPU/disk/daemon. PARITY_SHARD_TOTAL MUST equal the
166+ # length of matrix.shard — parity_sharding_workflow_test.go enforces it so a mismatch
167+ # can't silently drop cases.
168+ parity-runtime :
252169 needs : [lint-and-test, daily-changes]
253- if : needs.daily-changes.outputs.run == 'true'
170+ # Every push/PR, and on schedule/dispatch only when the repo changed. always() so a
171+ # skipped daily-changes (push/PR) doesn't skip this job; the explicit lint-and-test
172+ # check restores the normal "needs succeeded" gate.
173+ if : >-
174+ always()
175+ && needs.lint-and-test.result == 'success'
176+ && (github.event_name == 'push' || github.event_name == 'pull_request'
177+ || needs.daily-changes.outputs.run == 'true')
254178 runs-on : ubuntu-latest
255179 strategy :
256- # fail-fast off so one shard's failure still reports the others.
257180 fail-fast : false
258181 matrix :
259182 shard : [0, 1, 2, 3]
260183 env :
261184 PARITY_RUNTIME_TIMEOUT : " 10m"
262- # Each shard owns ~a quarter of the matrix, so -parallel 2 per runner matches
263- # the push/PR shard lane's proven-safe load instead of the old single-runner 3 .
185+ # Each shard owns ~a quarter of the selected cases; -parallel 2 per 2-core runner
186+ # is the proven-safe load (per-case id-label / COMPOSE_PROJECT_NAME isolation) .
264187 PARITY_PARALLEL : " 2"
265188 PARITY_SHARD_INDEX : ${{ matrix.shard }}
266189 PARITY_SHARD_TOTAL : " 4"
267190 steps :
268191 - uses : actions/checkout@v7
269192 with :
270193 submodules : recursive
271- - uses : ./.github/actions/setup-parity-runtime
194+ # Full history so the push/PR diff base is present for the affected mapping.
195+ fetch-depth : 0
196+ # devtool (the affected mapping) runs before the composite setup, so Go here.
197+ - uses : actions/setup-go@v6
198+ with :
199+ go-version-file : go.mod
200+ - name : Plan this run
201+ id : plan
202+ run : |
203+ if [ "${{ github.event_name }}" = "push" ] || [ "${{ github.event_name }}" = "pull_request" ]; then
204+ if [ "${{ github.event_name }}" = "pull_request" ]; then
205+ base="${{ github.event.pull_request.base.sha }}"; head="${{ github.event.pull_request.head.sha }}"
206+ else
207+ base="${{ github.event.before }}"; head="${{ github.sha }}"
208+ fi
209+ go run ./cmd/devtool parity-affected-commands "$base" "$head" >> "$GITHUB_OUTPUT"
210+ else
211+ # daily: the full matrix (this job only runs when daily-changes said so).
212+ echo "run=true" >> "$GITHUB_OUTPUT"
213+ echo "commands=all" >> "$GITHUB_OUTPUT"
214+ fi
215+ - if : steps.plan.outputs.run == 'true'
216+ uses : ./.github/actions/setup-parity-runtime
272217 with :
273218 repo-token : ${{ secrets.GITHUB_TOKEN }}
274- # Instrumented binary: measures coverage AND gates parity on this shard's slice.
275- - run : task coverage:parity-runtime
219+ # push/PR: scoped, plain binary — a fast gate.
220+ - name : Run parity (scoped, plain)
221+ if : steps.plan.outputs.run == 'true' && (github.event_name == 'push' || github.event_name == 'pull_request')
222+ env :
223+ PARITY_COMMAND : ${{ steps.plan.outputs.commands }}
224+ run : task parity:runtime
225+ # daily: full matrix, instrumented binary — gates parity AND measures coverage.
226+ - name : Run parity (full, instrumented)
227+ if : steps.plan.outputs.run == 'true' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
228+ run : task coverage:parity-runtime
276229 - name : Coverage summary
277- if : always()
230+ if : always() && steps.plan.outputs.run == 'true' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
278231 run : go run ./cmd/devtool coverage-report artifacts/coverage/data/runtime "parity:runtime shard ${{ matrix.shard }}" >> "$GITHUB_STEP_SUMMARY"
279- - if : always()
232+ - if : always() && steps.plan.outputs.run == 'true'
280233 run : |
281234 mkdir -p artifacts
282235 git -C reference rev-parse HEAD > artifacts/reference-commit.txt
283236 - uses : actions/upload-artifact@v7
284- if : always()
237+ if : always() && steps.plan.outputs.run == 'true'
285238 with :
286- name : parity-runtime-full- v0.88.0-shard-${{ matrix.shard }}
239+ name : parity-runtime-v0.88.0-shard-${{ matrix.shard }}
287240 path : artifacts/
288241 if-no-files-found : error
289- # covdata slice for the cross-lane merge (distinct name per shard so the merge
290- # job unions them instead of clobbering).
242+ # daily only: covdata slice for the cross-lane merge (distinct name per shard).
291243 - uses : actions/upload-artifact@v7
292- if : always()
244+ if : always() && steps.plan.outputs.run == 'true' && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
293245 with :
294246 name : covdata-runtime-shard-${{ matrix.shard }}
295247 path : artifacts/coverage/data/runtime
296248 if-no-files-found : error
297- - if : always()
249+ - if : always() && steps.plan.outputs.run == 'true'
298250 run : task clean
299251
300- # Publish parity (features/templates → ephemeral OCI registry). Independent of the
301- # runtime matrix, so it runs as its own job rather than stealing a runtime shard's
302- # runner. Was folded into the old monolithic parity-runtime-full.
252+ # Publish parity (features/templates → ephemeral OCI registry). Daily only, its own
253+ # job so it doesn't steal a runtime shard's runner.
303254 parity-publish-full :
304255 needs : [lint-and-test, daily-changes]
305256 if : needs.daily-changes.outputs.run == 'true'
@@ -324,14 +275,15 @@ jobs:
324275 - if : always()
325276 run : task clean
326277
327- # Daily gate + cross-lane coverage. Aggregates the sharded runtime lane and the
328- # publish lane into one pass/fail (mirrors the push/PR parity-runtime gate) and
329- # merges every lane's covdata — unit + e2e + contract (which also run on schedule)
330- # plus the runtime shards + publish — into the one true cross-lane number.
331- parity-runtime-full-report :
332- if : always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
278+ # Single gate + cross-lane coverage for ALL events (absorbs the old push/PR
279+ # parity-runtime aggregator, the daily report, and the per-PR coverage-report):
280+ # gates the runtime matrix (and, on daily, publish) into one pass/fail, and merges
281+ # every lane's covdata (unit + e2e + contract, plus the daily runtime shards +
282+ # publish) into the one true cross-lane number.
283+ parity-runtime-gate :
284+ if : always()
333285 runs-on : ubuntu-latest
334- needs : [lint-and-test, e2e, parity, parity-runtime-full , parity-publish-full]
286+ needs : [lint-and-test, e2e, parity, parity-runtime, parity-publish-full]
335287 steps :
336288 - uses : actions/checkout@v7
337289 - uses : actions/setup-go@v6
@@ -357,56 +309,23 @@ jobs:
357309 run : task coverage:merge | tee -a "$GITHUB_STEP_SUMMARY"
358310 - uses : actions/upload-artifact@v7
359311 with :
360- name : covdata-merged-full
312+ name : covdata-merged
361313 path : artifacts/coverage/data/merged.out
362314 if-no-files-found : warn
363- # Final verdict last, so the coverage report is posted even when a shard failed.
364- - name : Gate on all runtime shards + publish
315+ # Final verdict last, so coverage is posted even when a shard failed. A skipped
316+ # lane (publish on push/PR, or the whole matrix on a quiet daily) counts as pass.
317+ - name : Gate on runtime + publish
365318 run : |
366- runtime="${{ needs.parity-runtime-full .result }}"
319+ runtime="${{ needs.parity-runtime.result }}"
367320 publish="${{ needs.parity-publish-full.result }}"
368- echo "runtime shards : $runtime, publish: $publish"
321+ echo "runtime: $runtime, publish: $publish"
369322 for r in "$runtime" "$publish"; do
370323 case "$r" in
371324 success|skipped) ;;
372325 *) echo "runtime/publish parity failed"; exit 1 ;;
373326 esac
374327 done
375328
376- # Cross-lane coverage: merge the per-PR lanes' covdata (unit + e2e + contract)
377- # into the one number no single lane shows, and post it to the run summary.
378- coverage-report :
379- if : always() && (github.event_name == 'push' || github.event_name == 'pull_request')
380- runs-on : ubuntu-latest
381- needs : [lint-and-test, e2e, parity]
382- steps :
383- - uses : actions/checkout@v7
384- - uses : actions/setup-go@v6
385- with :
386- go-version-file : go.mod
387- - uses : go-task/setup-task@v2
388- with :
389- version : 3.x
390- repo-token : ${{ secrets.GITHUB_TOKEN }}
391- - name : Download lane covdata
392- uses : actions/download-artifact@v8
393- with :
394- pattern : covdata-*
395- path : artifacts/coverage/data
396- # download-artifact nests each artifact under covdata-<lane>/; flatten to <lane>/.
397- - name : Normalize lane dirs
398- run : |
399- cd artifacts/coverage/data
400- for d in covdata-*; do [ -d "$d" ] && mv "$d" "${d#covdata-}"; done
401- ls -R . || true
402- - name : Merged coverage report
403- run : task coverage:merge | tee -a "$GITHUB_STEP_SUMMARY"
404- - uses : actions/upload-artifact@v7
405- with :
406- name : covdata-merged
407- path : artifacts/coverage/data/merged.out
408- if-no-files-found : warn
409-
410329 cross-compile :
411330 runs-on : ubuntu-latest
412331 needs : lint-and-test
0 commit comments