Skip to content

Commit a576914

Browse files
committed
add workflow to compute and publish the fuzz coverage
1 parent ae8f926 commit a576914

File tree

2 files changed

+183
-0
lines changed

2 files changed

+183
-0
lines changed

.github/workflows/coverage.yaml

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
name: Fuzz Coverage
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "corpus/**"
9+
10+
schedule:
11+
- cron: "0 3 * * *" # Daily at 03:00 UTC
12+
workflow_dispatch:
13+
14+
permissions:
15+
contents: write
16+
pages: write
17+
id-token: write
18+
19+
jobs:
20+
coverage:
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
- name: Checkout corpus repo
25+
uses: actions/checkout@v4
26+
27+
- name: Checkout fuzz targets repo
28+
uses: actions/checkout@v4
29+
with:
30+
repository: stratum-mining/stratum
31+
path: stratum
32+
33+
- name: Install Rust
34+
uses: dtolnay/rust-toolchain@nightly
35+
with:
36+
profile: minimal
37+
toolchain: nightly
38+
override: true
39+
components: llvm-tools-preview
40+
41+
- name: Add Rust LLVM tools to PATH
42+
run: |
43+
LLVM_TOOLS=$(rustc +nightly --print sysroot)/lib/rustlib/$(rustc --print host-tuple)/bin
44+
echo "$LLVM_TOOLS" >> $GITHUB_PATH
45+
ls -al "$LLVM_TOOLS"
46+
47+
- name: Install cargo-fuzz
48+
run: cargo install cargo-fuzz
49+
50+
- name: Copy corpus into fuzz targets repo
51+
run: |
52+
mkdir -p stratum/fuzz/corpus
53+
mv corpus/* stratum/fuzz/corpus
54+
55+
- name: Run fuzz coverage
56+
run: |
57+
chmod +x ./scripts/fuzz_coverage.sh
58+
cp ./scripts/fuzz_coverage.sh stratum/fuzz_coverage.sh
59+
cd stratum/
60+
ls fuzz/
61+
./fuzz_coverage.sh
62+
63+
- name: Move coverage results into this repo
64+
run: |
65+
rm -rf coverage
66+
mkdir -p coverage
67+
cp -r stratum/coverage_html coverage/
68+
69+
- name: Upload pages artifact
70+
uses: actions/upload-pages-artifact@v3
71+
with:
72+
path: coverage/coverage_html
73+
74+
deploy:
75+
needs: coverage
76+
runs-on: ubuntu-latest
77+
environment:
78+
name: github-pages
79+
url: ${{ steps.deploy.outputs.page_url }}
80+
81+
steps:
82+
- name: Deploy to GitHub Pages
83+
id: deploy
84+
uses: actions/deploy-pages@v4
85+

scripts/fuzz_coverage.sh

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
############################################
5+
# Tools must be available directly in PATH:
6+
# llvm-profdata
7+
# llvm-cov
8+
############################################
9+
10+
PROJECT_ROOT="$(pwd)"
11+
HOST_TARGET=$(rustc +nightly --print host-tuple)
12+
13+
echo "[+] Project root: $PROJECT_ROOT"
14+
echo "[+] Host target: $HOST_TARGET"
15+
16+
############################################
17+
# 1. Run coverage for all fuzz targets
18+
############################################
19+
20+
echo "[+] Running fuzz coverage"
21+
for target in $(cargo +nightly fuzz list); do
22+
echo "$target"
23+
cargo +nightly fuzz coverage "$target"
24+
done
25+
26+
############################################
27+
# 2. Merge all .profdata
28+
############################################
29+
30+
echo "[+] Merging coverage profiles"
31+
llvm-profdata merge -sparse \
32+
fuzz/coverage/*/coverage.profdata \
33+
-o fuzz/coverage/merged.profdata
34+
35+
############################################
36+
# 3. Collect fuzz target coverage binaries
37+
############################################
38+
39+
echo "[+] Collecting fuzz binaries"
40+
41+
OBJECTS=""
42+
FIRST_TARGET=""
43+
44+
for target in $(cargo fuzz list); do
45+
BIN="target/$HOST_TARGET/coverage/$HOST_TARGET/release/$target"
46+
47+
if [ ! -f "$BIN" ]; then
48+
echo "ERROR: expected binary not found: $BIN"
49+
exit 1
50+
fi
51+
52+
if [ -z "$FIRST_TARGET" ]; then
53+
FIRST_TARGET="$BIN"
54+
else
55+
OBJECTS="$OBJECTS -object $BIN"
56+
fi
57+
done
58+
59+
############################################
60+
# 4. Filtering rules:
61+
# - ignore stdlib (/rustc/…)
62+
# - ignore crates.io (~/.cargo/registry/…)
63+
# - ignore everything outside the project dir
64+
############################################
65+
66+
IGNORE_FLAGS=(
67+
"-ignore-filename-regex=/.*/rustc/.*"
68+
"-ignore-filename-regex=/.cargo/registry/.*"
69+
"-ignore-filename-regex=^/(?!${PROJECT_ROOT}).*$"
70+
)
71+
72+
############################################
73+
# 5. Generate text summary
74+
############################################
75+
76+
echo "[+] Generating text summary"
77+
llvm-cov report \
78+
"${IGNORE_FLAGS[@]}" \
79+
-instr-profile=fuzz/coverage/merged.profdata \
80+
$FIRST_TARGET $OBJECTS \
81+
> coverage_summary.txt
82+
83+
############################################
84+
# 6. Generate HTML report
85+
############################################
86+
87+
echo "[+] Generating HTML report"
88+
llvm-cov show \
89+
"${IGNORE_FLAGS[@]}" \
90+
-instr-profile=fuzz/coverage/merged.profdata \
91+
$FIRST_TARGET $OBJECTS \
92+
-format=html \
93+
-output-dir=coverage_html
94+
95+
echo "[✓] Done!"
96+
echo "HTML → coverage_html/index.html"
97+
echo "TXT → coverage_summary.txt"
98+

0 commit comments

Comments
 (0)