@@ -172,26 +172,11 @@ jobs:
172172 base="${{ github.event.before }}"; head="${{ github.sha }}"
173173 fi
174174 bash scripts/parity-affected-commands.sh "$base" "$head" >> "$GITHUB_OUTPUT"
175- - uses : actions/setup-go@v6
176- if : steps.affected.outputs.run == 'true'
177- with :
178- go-version-file : go.mod
179- - uses : actions/setup-node@v6
180- if : steps.affected.outputs.run == 'true'
181- with :
182- node-version : " 20"
183- - uses : go-task/setup-task@v2
184- if : steps.affected.outputs.run == 'true'
175+ # Toolchain + runner prep + reference oracle, shared with parity-runtime-full.
176+ - if : steps.affected.outputs.run == 'true'
177+ uses : ./.github/actions/setup-parity-runtime
185178 with :
186- version : 3.x
187179 repo-token : ${{ secrets.GITHUB_TOKEN }}
188- # Free disk + enable the containerd image store (build-cache export). Reuses
189- # the Taskfile so the runner prep is identical to release.yml.
190- - if : steps.affected.outputs.run == 'true'
191- run : task ci:prepare-runner
192-
193- - if : steps.affected.outputs.run == 'true'
194- run : task reference
195180 - if : steps.affected.outputs.run == 'true'
196181 env :
197182 PARITY_COMMAND : ${{ steps.affected.outputs.commands }}
@@ -225,57 +210,161 @@ jobs:
225210 *) echo "one or more runtime shards failed"; exit 1 ;;
226211 esac
227212
228- # Full runtime parity matrix + publish parity. Runs once a day (schedule) and
229- # on manual dispatch — the exhaustive backstop for the scoped push/PR job above.
230- parity-runtime-full :
213+ # Gate the expensive daily lanes on "did the repo change today?". A manual dispatch
214+ # always runs; a scheduled run only proceeds if HEAD has a commit within the last
215+ # day (scripts/daily-changed.sh). On a private/billed repo this skips the full
216+ # runtime matrix + publish on quiet days. Runs on schedule/dispatch so it is never
217+ # skipped for those events — the heavy jobs `needs:` it, and a skipped need would
218+ # skip them regardless of its output.
219+ daily-changes :
231220 if : github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
232221 runs-on : ubuntu-latest
233- needs : lint-and-test
222+ outputs :
223+ run : ${{ steps.check.outputs.run }}
224+ steps :
225+ - uses : actions/checkout@v7
226+ - id : check
227+ run : |
228+ if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
229+ echo "manual dispatch → always run" >&2
230+ echo "run=true" >> "$GITHUB_OUTPUT"
231+ else
232+ bash scripts/daily-changed.sh >> "$GITHUB_OUTPUT"
233+ fi
234+
235+ # Full runtime parity matrix. Runs once a day (schedule, only when the repo changed
236+ # — see daily-changes) and on manual dispatch — the exhaustive backstop for the
237+ # scoped push/PR job above. Sharded across independent runners (same
238+ # PARITY_SHARD_INDEX/TOTAL harness as the push/PR lane) so the 175-case matrix no
239+ # longer contends for one runner's CPU/disk/daemon, which was starving the
240+ # container setups and failing downstream exec cases. PARITY_SHARD_TOTAL MUST equal
241+ # the length of matrix.shard — parity_sharding_workflow_test.go enforces that, so a
242+ # mismatch can't silently drop cases.
243+ parity-runtime-full :
244+ needs : [lint-and-test, daily-changes]
245+ if : needs.daily-changes.outputs.run == 'true'
246+ runs-on : ubuntu-latest
247+ strategy :
248+ # fail-fast off so one shard's failure still reports the others.
249+ fail-fast : false
250+ matrix :
251+ shard : [0, 1, 2, 3]
234252 env :
235253 PARITY_RUNTIME_TIMEOUT : " 10m"
236- # Exhaustive daily run on a dedicated (non-gating) job: raise parallelism to
237- # 3 now that per-case isolation makes concurrent builds safe. Not sharded
238- # here because this lane also measures coverage (single covdata merge).
239- PARITY_PARALLEL : " 3"
254+ # Each shard owns ~a quarter of the matrix, so -parallel 2 per runner matches
255+ # the push/PR shard lane's proven-safe load instead of the old single-runner 3.
256+ PARITY_PARALLEL : " 2"
257+ PARITY_SHARD_INDEX : ${{ matrix.shard }}
258+ PARITY_SHARD_TOTAL : " 4"
240259 steps :
241260 - uses : actions/checkout@v7
242261 with :
243262 submodules : recursive
244- - uses : actions/setup-go@v6
245- with :
246- go-version-file : go.mod
247- - uses : actions/setup-node@v6
248- with :
249- node-version : " 20"
250- - uses : go-task/setup-task@v2
263+ - uses : ./.github/actions/setup-parity-runtime
251264 with :
252- version : 3.x
253265 repo-token : ${{ secrets.GITHUB_TOKEN }}
254- - run : task ci:prepare-runner
255-
256- - run : task reference
257- # The full lanes run the instrumented binary, so this measures coverage AND
258- # gates parity; coverage:merge unions them into one cross-lane report.
266+ # Instrumented binary: measures coverage AND gates parity on this shard's slice.
259267 - run : task coverage:parity-runtime
260- - run : task coverage:parity-publish
261- - name : Merged coverage report
268+ - name : Coverage summary
262269 if : always()
263- run : task coverage:merge | tee -a "$GITHUB_STEP_SUMMARY"
270+ run : bash scripts/ coverage-report.sh artifacts/coverage/data/runtime "parity:runtime shard ${{ matrix.shard }}" >> "$GITHUB_STEP_SUMMARY"
264271 - if : always()
265272 run : |
266273 mkdir -p artifacts
267274 git -C reference rev-parse HEAD > artifacts/reference-commit.txt
268275 - uses : actions/upload-artifact@v7
269276 if : always()
270277 with :
271- name : parity-runtime-full-v0.88.0
272- path : |
273- artifacts/
274- artifacts/coverage/
278+ name : parity-runtime-full-v0.88.0-shard-${{ matrix.shard }}
279+ path : artifacts/
280+ if-no-files-found : error
281+ # covdata slice for the cross-lane merge (distinct name per shard so the merge
282+ # job unions them instead of clobbering).
283+ - uses : actions/upload-artifact@v7
284+ if : always()
285+ with :
286+ name : covdata-runtime-shard-${{ matrix.shard }}
287+ path : artifacts/coverage/data/runtime
275288 if-no-files-found : error
276289 - if : always()
277290 run : task clean
278291
292+ # Publish parity (features/templates → ephemeral OCI registry). Independent of the
293+ # runtime matrix, so it runs as its own job rather than stealing a runtime shard's
294+ # runner. Was folded into the old monolithic parity-runtime-full.
295+ parity-publish-full :
296+ needs : [lint-and-test, daily-changes]
297+ if : needs.daily-changes.outputs.run == 'true'
298+ runs-on : ubuntu-latest
299+ steps :
300+ - uses : actions/checkout@v7
301+ with :
302+ submodules : recursive
303+ - uses : ./.github/actions/setup-parity-runtime
304+ with :
305+ repo-token : ${{ secrets.GITHUB_TOKEN }}
306+ - run : task coverage:parity-publish
307+ - name : Coverage summary
308+ if : always()
309+ run : bash scripts/coverage-report.sh artifacts/coverage/data/publish "parity:publish" >> "$GITHUB_STEP_SUMMARY"
310+ - uses : actions/upload-artifact@v7
311+ if : always()
312+ with :
313+ name : covdata-publish
314+ path : artifacts/coverage/data/publish
315+ if-no-files-found : error
316+ - if : always()
317+ run : task clean
318+
319+ # Daily gate + cross-lane coverage. Aggregates the sharded runtime lane and the
320+ # publish lane into one pass/fail (mirrors the push/PR parity-runtime gate) and
321+ # merges every lane's covdata — unit + e2e + contract (which also run on schedule)
322+ # plus the runtime shards + publish — into the one true cross-lane number.
323+ parity-runtime-full-report :
324+ if : always() && (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
325+ runs-on : ubuntu-latest
326+ needs : [lint-and-test, e2e, parity, parity-runtime-full, parity-publish-full]
327+ steps :
328+ - uses : actions/checkout@v7
329+ - uses : actions/setup-go@v6
330+ with :
331+ go-version-file : go.mod
332+ - uses : go-task/setup-task@v2
333+ with :
334+ version : 3.x
335+ repo-token : ${{ secrets.GITHUB_TOKEN }}
336+ - name : Download all lane covdata
337+ uses : actions/download-artifact@v8
338+ with :
339+ pattern : covdata-*
340+ path : artifacts/coverage/data
341+ # download-artifact nests each artifact under covdata-<lane>/; flatten to <lane>/
342+ # so coverage:merge sees one dir per lane (the runtime shards stay distinct).
343+ - name : Normalize lane dirs
344+ run : |
345+ cd artifacts/coverage/data
346+ for d in covdata-*; do [ -d "$d" ] && mv "$d" "${d#covdata-}"; done
347+ ls -R . || true
348+ - name : Merged coverage report
349+ run : task coverage:merge | tee -a "$GITHUB_STEP_SUMMARY"
350+ - uses : actions/upload-artifact@v7
351+ with :
352+ name : covdata-merged-full
353+ path : artifacts/coverage/data/merged.out
354+ if-no-files-found : warn
355+ # Final verdict last, so the coverage report is posted even when a shard failed.
356+ - name : Gate on all runtime shards + publish
357+ run : |
358+ runtime="${{ needs.parity-runtime-full.result }}"
359+ publish="${{ needs.parity-publish-full.result }}"
360+ echo "runtime shards: $runtime, publish: $publish"
361+ for r in "$runtime" "$publish"; do
362+ case "$r" in
363+ success|skipped) ;;
364+ *) echo "runtime/publish parity failed"; exit 1 ;;
365+ esac
366+ done
367+
279368 # Experimental, NON-gating: arm64 runtime via QEMU emulation. arm64 runtime is
280369 # unsupported for now, so its cases are skipped-arm64 in the gate above. This job
281370 # is SLOW (QEMU) and only runs on a manual trigger (workflow_dispatch), not on
0 commit comments