Skip to content

Commit 012191e

Browse files
aledbfclaude
andcommitted
refactor(coverage,ci): extract Taskfile bash to scripts, unify coverage, reuse in CI
Coverage was five disjoint profiles that never combined, so the headline number only reflected hermetic unit tests and the per-package gate ran on that subset. The parity coverage tasks were also near-identical copies with inline awk/bash. Scripts (all bash lives in scripts/ now, simplified + more robust): - pkgcov.awk weighted per-package aggregation, shared by report + gate - coverage-report.sh per-package Markdown table + total from a profile or covdata dir - coverage-gate.sh total + per-package floor enforcement (replaces inline awk) - coverage-merge.sh union every per-lane covdata dir into the true cross-lane number - docker-cache-export.sh the buildx cache-export precondition (was duplicated inline) - ci-prepare-runner.sh free disk + containerd store (was duplicated in 4 CI jobs) - parity-affected-commands.sh the PR diff→PARITY_COMMAND step (was inline in the workflow) - parity-affected.sh moved from .github/scripts so all scripts sit together Taskfile: - coverage keeps coverage.out byte-identical (gate unchanged) but also emits binary covdata via -test.gocoverdir so lanes can be merged. - every lane writes covdata under artifacts/coverage/data/<lane>; the 3 coverage:parity-* tasks collapse into one internal coverage:_parity-lane. - new coverage:merge prints the union across all lanes; new ci:prepare-runner. CI reuses the Taskfile instead of duplicating bash: docker prep → task ci:prepare-runner, the affected-commands step → scripts/parity-affected-commands.sh, each coverage lane posts its table to $GITHUB_STEP_SUMMARY and uploads its covdata, and a new coverage-report job merges the PR lanes (unit+e2e+contract) into one summary. The daily full job merges its runtime+publish lanes the same way. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 0ea5308 commit 012191e

11 files changed

Lines changed: 357 additions & 155 deletions

.github/workflows/go-cli.yml

Lines changed: 72 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ jobs:
3232
- run: task vuln
3333
- run: task test:race
3434
- run: task coverage
35+
- name: Coverage summary
36+
if: always()
37+
run: bash scripts/coverage-report.sh coverage.out "unit (hermetic)" >> "$GITHUB_STEP_SUMMARY"
3538
- run: task test:integration
3639
- run: task build
3740
- run: ./devcontainer --version
@@ -49,11 +52,12 @@ jobs:
4952
language: Go
5053
label: code-coverage/go
5154

55+
# Binary covdata for the cross-lane merge (coverage-report job).
5256
- uses: actions/upload-artifact@v7
5357
if: always()
5458
with:
55-
name: unit-coverage
56-
path: coverage.out
59+
name: covdata-unit
60+
path: artifacts/coverage/data/unit
5761
if-no-files-found: error
5862

5963
e2e:
@@ -70,11 +74,14 @@ jobs:
7074
repo-token: ${{ secrets.GITHUB_TOKEN }}
7175

7276
- run: task coverage:e2e
77+
- name: Coverage summary
78+
if: always()
79+
run: bash scripts/coverage-report.sh artifacts/coverage/data/e2e "e2e" >> "$GITHUB_STEP_SUMMARY"
7380
- uses: actions/upload-artifact@v7
7481
if: always()
7582
with:
76-
name: e2e-coverage
77-
path: artifacts/coverage/e2e.out
83+
name: covdata-e2e
84+
path: artifacts/coverage/data/e2e
7885
if-no-files-found: error
7986
- if: always()
8087
run: task clean
@@ -106,6 +113,9 @@ jobs:
106113
# functional parity run above release-like, and avoid conflating subprocess
107114
# coverage with the hermetic unit profile.
108115
- run: task coverage:parity-contract
116+
- name: Coverage summary
117+
if: always()
118+
run: bash scripts/coverage-report.sh artifacts/coverage/data/contract "parity:contract" >> "$GITHUB_STEP_SUMMARY"
109119
- if: always()
110120
run: |
111121
mkdir -p artifacts
@@ -116,10 +126,16 @@ jobs:
116126
name: parity-contract-network-v0.88.0
117127
path: artifacts/
118128
if-no-files-found: error
129+
- uses: actions/upload-artifact@v7
130+
if: always()
131+
with:
132+
name: covdata-contract
133+
path: artifacts/coverage/data/contract
134+
if-no-files-found: error
119135

120136
# Runtime lane of the parity matrix (creates real containers via Docker) on
121137
# push/PR, SCOPED to the commands affected by the change: the full matrix takes
122-
# ~45 min, so .github/scripts/parity-affected.sh maps the diff to a
138+
# ~45 min, so scripts/parity-affected.sh maps the diff to a
123139
# PARITY_COMMAND allowlist (or "all"/"none"). The daily parity-runtime-full job
124140
# is the backstop that always runs the whole thing.
125141
parity-runtime:
@@ -141,46 +157,11 @@ jobs:
141157
id: affected
142158
run: |
143159
if [ "${{ github.event_name }}" = "pull_request" ]; then
144-
base="${{ github.event.pull_request.base.sha }}"
145-
head="${{ github.event.pull_request.head.sha }}"
146-
else
147-
base="${{ github.event.before }}"
148-
head="${{ github.sha }}"
149-
fi
150-
# New branch / unknown base (e.g. all-zero before-SHA) → run everything.
151-
if [ -z "$base" ] || ! git cat-file -e "${base}^{commit}" 2>/dev/null; then
152-
echo "commands=all" >> "$GITHUB_OUTPUT"; echo "run=true" >> "$GITHUB_OUTPUT"
153-
echo "unknown base → running the full matrix"; exit 0
154-
fi
155-
files=$(git diff --name-only "$base" "$head")
156-
echo "changed files:"; echo "$files"
157-
cmds=$(printf '%s\n' "$files" | .github/scripts/parity-affected.sh)
158-
echo "affected parity commands: $cmds"
159-
echo "commands=$cmds" >> "$GITHUB_OUTPUT"
160-
if [ "$cmds" = "none" ]; then
161-
echo "run=false" >> "$GITHUB_OUTPUT"
162-
echo "no runtime-relevant changes → skipping the runtime matrix"
160+
base="${{ github.event.pull_request.base.sha }}"; head="${{ github.event.pull_request.head.sha }}"
163161
else
164-
echo "run=true" >> "$GITHUB_OUTPUT"
162+
base="${{ github.event.before }}"; head="${{ github.sha }}"
165163
fi
166-
# The runtime matrix builds real images serially; they accumulate and
167-
# exhaust the runner's root disk ("No space left on device" — the runner then
168-
# dies hard, losing logs). /mnt is the SAME filesystem as / on these runners,
169-
# so it buys nothing; instead free the big preinstalled SDKs (Go/Node are
170-
# reinstalled by the setup steps that follow) for ~25-30GB of headroom. Also
171-
# enable the containerd image store (needed for cache export / --platform).
172-
- name: Free disk space + configure Docker (containerd store)
173-
if: steps.affected.outputs.run == 'true'
174-
run: |
175-
echo "before:"; df -h / | tail -1
176-
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android \
177-
/opt/hostedtoolcache/CodeQL /usr/share/swift \
178-
/usr/local/share/boost /usr/lib/jvm || true
179-
sudo docker image prune -af >/dev/null 2>&1 || true
180-
echo "after:"; df -h / | tail -1
181-
echo '{"features":{"containerd-snapshotter":true}}' | sudo tee /etc/docker/daemon.json
182-
sudo systemctl restart docker
183-
docker info -f 'driver={{.DriverStatus}}'
164+
bash scripts/parity-affected-commands.sh "$base" "$head" >> "$GITHUB_OUTPUT"
184165
- uses: actions/setup-go@v6
185166
if: steps.affected.outputs.run == 'true'
186167
with:
@@ -194,6 +175,10 @@ jobs:
194175
with:
195176
version: 3.x
196177
repo-token: ${{ secrets.GITHUB_TOKEN }}
178+
# Free disk + enable the containerd image store (build-cache export). Reuses
179+
# the Taskfile so the runner prep is identical to release.yml.
180+
- if: steps.affected.outputs.run == 'true'
181+
run: task ci:prepare-runner
197182

198183
- if: steps.affected.outputs.run == 'true'
199184
run: task reference
@@ -227,17 +212,6 @@ jobs:
227212
- uses: actions/checkout@v7
228213
with:
229214
submodules: recursive
230-
- name: Free disk space + configure Docker (containerd store)
231-
run: |
232-
echo "before:"; df -h / | tail -1
233-
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android \
234-
/opt/hostedtoolcache/CodeQL /usr/share/swift \
235-
/usr/local/share/boost /usr/lib/jvm || true
236-
sudo docker image prune -af >/dev/null 2>&1 || true
237-
echo "after:"; df -h / | tail -1
238-
echo '{"features":{"containerd-snapshotter":true}}' | sudo tee /etc/docker/daemon.json
239-
sudo systemctl restart docker
240-
docker info -f 'driver={{.DriverStatus}}'
241215
- uses: actions/setup-go@v6
242216
with:
243217
go-version-file: go.mod
@@ -248,10 +222,16 @@ jobs:
248222
with:
249223
version: 3.x
250224
repo-token: ${{ secrets.GITHUB_TOKEN }}
225+
- run: task ci:prepare-runner
251226

252227
- run: task reference
228+
# The full lanes run the instrumented binary, so this measures coverage AND
229+
# gates parity; coverage:merge unions them into one cross-lane report.
253230
- run: task coverage:parity-runtime
254231
- run: task coverage:parity-publish
232+
- name: Merged coverage report
233+
if: always()
234+
run: task coverage:merge | tee -a "$GITHUB_STEP_SUMMARY"
255235
- if: always()
256236
run: |
257237
mkdir -p artifacts
@@ -260,7 +240,9 @@ jobs:
260240
if: always()
261241
with:
262242
name: parity-runtime-full-v0.88.0
263-
path: artifacts/
243+
path: |
244+
artifacts/
245+
artifacts/coverage/
264246
if-no-files-found: error
265247
- if: always()
266248
run: task clean
@@ -285,13 +267,6 @@ jobs:
285267
uses: docker/setup-qemu-action@v3
286268
with:
287269
platforms: arm64
288-
- name: Free disk space + configure Docker (containerd store)
289-
run: |
290-
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android \
291-
/opt/hostedtoolcache/CodeQL /usr/share/swift \
292-
/usr/local/share/boost /usr/lib/jvm || true
293-
echo '{"features":{"containerd-snapshotter":true}}' | sudo tee /etc/docker/daemon.json
294-
sudo systemctl restart docker
295270
- uses: actions/setup-go@v6
296271
with:
297272
go-version-file: go.mod
@@ -302,12 +277,47 @@ jobs:
302277
with:
303278
version: 3.x
304279
repo-token: ${{ secrets.GITHUB_TOKEN }}
280+
- run: task ci:prepare-runner
305281
- run: task reference
306282
- run: task parity:runtime
307283
- if: always()
308284
run: task clean
309285

310286

287+
# Cross-lane coverage: merge the per-PR lanes' covdata (unit + e2e + contract)
288+
# into the one number no single lane shows, and post it to the run summary.
289+
coverage-report:
290+
if: always() && (github.event_name == 'push' || github.event_name == 'pull_request')
291+
runs-on: ubuntu-latest
292+
needs: [lint-and-test, e2e, parity]
293+
steps:
294+
- uses: actions/checkout@v7
295+
- uses: actions/setup-go@v6
296+
with:
297+
go-version-file: go.mod
298+
- uses: go-task/setup-task@v2
299+
with:
300+
version: 3.x
301+
repo-token: ${{ secrets.GITHUB_TOKEN }}
302+
- name: Download lane covdata
303+
uses: actions/download-artifact@v7
304+
with:
305+
pattern: covdata-*
306+
path: artifacts/coverage/data
307+
# download-artifact nests each artifact under covdata-<lane>/; flatten to <lane>/.
308+
- name: Normalize lane dirs
309+
run: |
310+
cd artifacts/coverage/data
311+
for d in covdata-*; do [ -d "$d" ] && mv "$d" "${d#covdata-}"; done
312+
ls -R . || true
313+
- name: Merged coverage report
314+
run: task coverage:merge | tee -a "$GITHUB_STEP_SUMMARY"
315+
- uses: actions/upload-artifact@v7
316+
with:
317+
name: covdata-merged
318+
path: artifacts/coverage/merged.out
319+
if-no-files-found: warn
320+
311321
cross-compile:
312322
runs-on: ubuntu-latest
313323
needs: lint-and-test

.github/workflows/release.yml

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -45,22 +45,6 @@ jobs:
4545
- uses: actions/checkout@v7
4646
with:
4747
submodules: recursive
48-
# parity:runtime exports build cache (build.cache-to-*, build.output-oci-*),
49-
# which the default docker driver cannot do — its precondition fails ~1s in.
50-
# Enable the containerd image store exactly like the go-cli.yml runtime job,
51-
# or a tagged release stalls on a runner with the default driver. Also free
52-
# the big preinstalled SDKs so the serial image builds don't exhaust the disk.
53-
- name: Free disk space + configure Docker (containerd store)
54-
run: |
55-
echo "before:"; df -h / | tail -1
56-
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android \
57-
/opt/hostedtoolcache/CodeQL /usr/share/swift \
58-
/usr/local/share/boost /usr/lib/jvm || true
59-
sudo docker image prune -af >/dev/null 2>&1 || true
60-
echo "after:"; df -h / | tail -1
61-
echo '{"features":{"containerd-snapshotter":true}}' | sudo tee /etc/docker/daemon.json
62-
sudo systemctl restart docker
63-
docker info -f 'driver={{.DriverStatus}}'
6448
- uses: actions/setup-go@v6
6549
with:
6650
go-version-file: go.mod
@@ -71,6 +55,11 @@ jobs:
7155
with:
7256
version: 3.x
7357
repo-token: ${{ secrets.GITHUB_TOKEN }}
58+
# parity:runtime exports build cache (build.cache-to-*, build.output-oci-*),
59+
# which the default docker driver cannot do — its precondition fails ~1s in.
60+
# Reuse the same runner prep as the go-cli.yml runtime job, or a tagged
61+
# release stalls on a default-driver runner.
62+
- run: task ci:prepare-runner
7463

7564
- run: task reference
7665
- run: task test:e2e

0 commit comments

Comments
 (0)