Skip to content

Commit 1a26867

Browse files
Merge pull request #4588 from TheBlueMatt/2026-05-ci-corpus-repo
Switch to ldk-fuzzing-corpus repo rather than CI cache
2 parents 8712856 + efa95b4 commit 1a26867

2 files changed

Lines changed: 148 additions & 30 deletions

File tree

.github/workflows/build.yml

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -82,11 +82,17 @@ jobs:
8282
# Maybe if codecov wasn't broken we wouldn't need to do this...
8383
./codecov --verbose upload-process --disable-search --fail-on-error -f target/codecov.json -t "f421b687-4dc2-4387-ac3d-dc3b2528af57" -F 'tests'
8484
cargo clean
85-
- name: Download honggfuzz corpus
86-
uses: actions/download-artifact@v4
87-
with:
88-
name: hfuzz-corpus
89-
path: fuzz/hfuzz_workspace
85+
- name: Clone fuzzing corpus
86+
run: git clone --depth=1 https://github.com/lightningdevkit/ldk-fuzzing-corpus.git fuzz/ldk-fuzzing-corpus
87+
- name: Symlink corpus into hfuzz_workspace
88+
run: |
89+
set -eu
90+
cd fuzz
91+
for D in ldk-fuzzing-corpus/rust-lightning/*/; do
92+
NAME=$(basename "$D")
93+
mkdir -p "hfuzz_workspace/${NAME}_target"
94+
cp -r "ldk-fuzzing-corpus/rust-lightning/${NAME}" "hfuzz_workspace/${NAME}_target/input"
95+
done
9096
- name: Run fuzz coverage generation
9197
run: |
9298
./contrib/generate_fuzz_coverage.sh --output-dir `pwd` --output-codecov-json
@@ -233,39 +239,59 @@ jobs:
233239
- name: Install Rust ${{ env.TOOLCHAIN }} toolchain
234240
run: |
235241
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --profile=minimal --default-toolchain ${{ env.TOOLCHAIN }}
236-
# This is read-only for PRs. It seeds the fuzzer for a more effective run.
237-
# NOTE: The `key` is unique and will always miss, forcing a fallback to
238-
# the `restore-keys` to find the latest global cache from the `main` branch.
239-
- name: Restore persistent fuzz corpus (PR)
240-
if: ${{ github.ref != 'refs/heads/main' }}
241-
uses: actions/cache/restore@v4
242-
with:
243-
path: fuzz/hfuzz_workspace
244-
key: fuzz-corpus-${{ github.ref }}-${{ github.sha }}
245-
restore-keys: |
246-
fuzz-corpus-refs/heads/main-
247-
# The `restore-keys` performs a prefix search to find the most recent
248-
# cache from a previous `main` run. We then save with a new, unique
249-
# `key` (using the SHA) to ensure the cache is always updated,
250-
# as caches are immutable.
251-
- name: Restore/Save persistent honggfuzz corpus (Main)
252-
if: ${{ github.ref == 'refs/heads/main' }}
253-
uses: actions/cache@v4
254-
with:
255-
path: fuzz/hfuzz_workspace
256-
key: fuzz-corpus-refs/heads/main-${{ github.sha }}
257-
restore-keys: |
258-
fuzz-corpus-refs/heads/main-
242+
- name: Clone fuzzing corpus
243+
run: git clone --depth=1 https://github.com/lightningdevkit/ldk-fuzzing-corpus.git fuzz/ldk-fuzzing-corpus
244+
- name: Symlink corpus into hfuzz_workspace
245+
run: |
246+
set -eu
247+
cd fuzz
248+
for D in ldk-fuzzing-corpus/rust-lightning/*/; do
249+
NAME=$(basename "$D")
250+
mkdir -p "hfuzz_workspace/${NAME}_target"
251+
ln -sfn "../../ldk-fuzzing-corpus/rust-lightning/${NAME}" \
252+
"hfuzz_workspace/${NAME}_target/input"
253+
done
259254
- name: Run fuzzers
260255
run: cd fuzz && ./ci-fuzz.sh && cd ..
261256
env:
262257
FUZZ_MINIMIZE: ${{ contains(github.event.pull_request.labels.*.name, 'fuzz-minimize') }}
263-
- name: Upload honggfuzz corpus
258+
- name: Stage new corpus entries for upload
259+
if: success() || failure()
260+
run: |
261+
set -eu
262+
WORKSPACE="$(pwd)"
263+
rm -rf "$WORKSPACE/new-corpus"
264+
mkdir -p "$WORKSPACE/new-corpus"
265+
266+
cd fuzz/ldk-fuzzing-corpus
267+
while IFS= read -r F; do
268+
mkdir -p "$WORKSPACE/new-corpus/$(dirname "$F")"
269+
cp -a "$F" "$WORKSPACE/new-corpus/$F"
270+
done < <(git ls-files --others --exclude-standard rust-lightning/)
271+
cd "$WORKSPACE"
272+
273+
for D in fuzz/hfuzz_workspace/*_target/; do
274+
[ -d "$D" ] || continue
275+
BASE=$(basename "$D")
276+
NAME="${BASE%_target}"
277+
[ -d "$WORKSPACE/new-corpus/$NAME" ] || continue
278+
for F in "$D"/SIG*; do
279+
FILE="$(basename "$F")"
280+
[ -f "$F" -a ! -f "$WORKSPACE/new-corpus/$NAME/$FILE" ] &&
281+
cp "$F" "$WORKSPACE/new-corpus/$NAME/$FILE"
282+
done
283+
done
284+
285+
NEW=$(find new-corpus -type f 2>/dev/null | wc -l)
286+
echo "Staged $NEW new corpus entries (including any SIG* crashes)"
287+
- name: Upload new corpus entries
288+
if: success() || failure()
264289
uses: actions/upload-artifact@v4
265290
with:
266291
name: hfuzz-corpus
267-
path: fuzz/hfuzz_workspace
292+
path: new-corpus
268293
compression-level: 0
294+
if-no-files-found: ignore
269295

270296
linting:
271297
runs-on: ubuntu-latest
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
name: Push fuzz corpus
2+
3+
# Triggered after the main CI workflow finishes. Because `workflow_run` always
4+
# runs in the *base* repo's context (its workflow file as of `main`, with
5+
# full secrets access) it's safe to handle the corpus push here even for fork
6+
# PRs — none of the PR's modified code or scripts execute in this job.
7+
#
8+
# Caveat: GitHub only fires `workflow_run` for workflow files that live on
9+
# the default branch, so this workflow does nothing until it's merged to
10+
# `master`.
11+
on:
12+
# zizmor flags `workflow_run` as a dangerous trigger because it runs with
13+
# repo secrets in base-branch context. That's exactly why we use it here:
14+
# this workflow never touches any PR-supplied code (no checkout, no script
15+
# execution from the artifact — just cp/git on opaque corpus blobs), so
16+
# the warning is a false positive.
17+
workflow_run: # zizmor: ignore[dangerous-triggers]
18+
workflows: ["Continuous Integration Checks"]
19+
types: [completed]
20+
21+
permissions:
22+
# download-artifact across runs requires `actions: read`.
23+
actions: read
24+
25+
jobs:
26+
push-corpus:
27+
# Run on either success or fuzzer crash; skip on cancellation.
28+
if: >-
29+
github.event.workflow_run.conclusion == 'success' ||
30+
github.event.workflow_run.conclusion == 'failure'
31+
runs-on: ubuntu-latest
32+
steps:
33+
- name: Download fuzz corpus artifact
34+
id: download
35+
# The artifact only exists when the fuzz job got far enough to upload
36+
# it. Don't fail this workflow if the upload was skipped.
37+
continue-on-error: true
38+
uses: actions/download-artifact@v4
39+
with:
40+
name: hfuzz-corpus
41+
path: hfuzz-corpus
42+
run-id: ${{ github.event.workflow_run.id }}
43+
github-token: ${{ secrets.GITHUB_TOKEN }}
44+
45+
- name: Clone fuzzing corpus
46+
if: steps.download.outcome == 'success'
47+
run: git clone --depth=1 https://github.com/lightningdevkit/ldk-fuzzing-corpus.git
48+
49+
- name: Copy new corpus entries into the corpus checkout
50+
if: steps.download.outcome == 'success'
51+
run: |
52+
set -eu
53+
if [ -d hfuzz-corpus/rust-lightning ]; then
54+
cp -rn hfuzz-corpus/rust-lightning/. ldk-fuzzing-corpus/rust-lightning/
55+
fi
56+
57+
- name: Open PR with new corpus entries
58+
if: steps.download.outcome == 'success'
59+
env:
60+
GH_TOKEN: ${{ secrets.CORPUS_PUSH_TOKEN }}
61+
SOURCE_SHA: ${{ github.event.workflow_run.head_sha }}
62+
RUN_URL: ${{ github.event.workflow_run.html_url }}
63+
RUN_ID: ${{ github.event.workflow_run.id }}
64+
run: |
65+
set -eu
66+
cd ldk-fuzzing-corpus
67+
if [ -z "$(git status --porcelain)" ]; then
68+
echo "No new corpus entries to contribute."
69+
exit 0
70+
fi
71+
if [ -z "${GH_TOKEN:-}" ]; then
72+
echo "Found new corpus entries but CORPUS_PUSH_TOKEN is unset; skipping PR."
73+
git status --short
74+
exit 0
75+
fi
76+
BRANCH="ci/new-corpus-${RUN_ID}"
77+
git config user.email "ldk-ci@users.noreply.github.com"
78+
git config user.name "LDK CI"
79+
git checkout -b "$BRANCH"
80+
git add rust-lightning
81+
git commit \
82+
-m "Add corpus entries from rust-lightning CI" \
83+
-m "Source commit: ${SOURCE_SHA}" \
84+
-m "Run: ${RUN_URL}"
85+
REMOTE=$(git config --get remote.origin.url)
86+
PUSH_URL="https://x-access-token:${GH_TOKEN}@${REMOTE#https://}"
87+
git push "$PUSH_URL" "HEAD:$BRANCH"
88+
gh pr create \
89+
--title "New corpus entries from rust-lightning CI run ${RUN_ID}" \
90+
--body "Discovered while running fuzz CI against \`${SOURCE_SHA}\`. Source: ${RUN_URL}" \
91+
--head "$BRANCH" \
92+
--base master

0 commit comments

Comments
 (0)