-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add nightlyfuzz CI #11934
Merged
Merged
Add nightlyfuzz CI #11934
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
b3b509c
Adds nightlyfuzz CI
vyzaldysanchez 47e6a66
Runs nightly fuzz on the root directory
vyzaldysanchez c6a8a64
Gives proper permissions to fuzz script
vyzaldysanchez 1889db5
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez cc624d3
Changes go_core_fuzz command
vyzaldysanchez b44f197
WIP
vyzaldysanchez 15f3d88
WIP
vyzaldysanchez 231f921
Fixes py script to point to chainlink files
vyzaldysanchez a2f34c8
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 1a53de8
Update fuzz/fuzz_all_native.py
vyzaldysanchez 34c2cb2
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 9bdf380
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 8fb7094
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez f666158
Logs failing fuzz inputs
vyzaldysanchez 1273be6
Bumps actions versions on nightlyfuzz action
vyzaldysanchez 715f9cb
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 774a80c
Sets fix secs amount on CI fuzz run
vyzaldysanchez 11042a6
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez f97ad72
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 5d11ad6
Adds comment on `--seconds` usage
vyzaldysanchez 2872e94
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 81555cc
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 471b058
Merge branch 'develop' into chore/BCF-2571/nightly-fuzz-ci
vyzaldysanchez 97a647d
Fixes sonar exclusion on fuzz
vyzaldysanchez 436cd4a
Fixes sonar exclusion on fuzz
vyzaldysanchez 2613326
Fixes sonar exclusion on fuzz
vyzaldysanchez File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
name: 'nightly/tag fuzz' | ||
on: | ||
schedule: | ||
# Note: The schedule event can be delayed during periods of high | ||
# loads of GitHub Actions workflow runs. High load times include | ||
# the start of every hour. To decrease the chance of delay, | ||
# schedule your workflow to run at a different time of the hour. | ||
- cron: "25 0 * * *" # at 25 past midnight every day | ||
push: | ||
tags: | ||
- '*' | ||
workflow_dispatch: null | ||
jobs: | ||
fuzzrun: | ||
name: "run native fuzzers" | ||
runs-on: "ubuntu20.04-4cores-16GB" | ||
steps: | ||
- name: "Checkout" | ||
uses: "actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11" # v4.1.1 | ||
- name: "Setup go" | ||
uses: "actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491" # v5.0.0 | ||
with: | ||
go-version-file: 'go.mod' | ||
cache: true | ||
cache-dependency-path: 'go.sum' | ||
- name: "Get corpus directory" | ||
id: "get-corpus-dir" | ||
run: echo "corpus_dir=$(go env GOCACHE)/fuzz" >> $GITHUB_OUTPUT | ||
shell: "bash" | ||
- name: "Restore corpus" | ||
uses: "actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2" # v4.0.0 | ||
id: "restore-corpus" | ||
with: | ||
path: "${{ steps.get-corpus-dir.outputs.corpus_dir }}" | ||
# We need to ensure uniqueness of the key, as saving to a key more than once will fail (see Save corpus step). | ||
# We never expect a cache hit with the key but we do expect a hit with the restore-keys prefix that is going | ||
# to match the latest cache that has that prefix. | ||
key: "nightlyfuzz-corpus-${{ github.run_id }}-${{ github.run_attempt }}" | ||
restore-keys: "nightlyfuzz-corpus-" | ||
- name: "Run native fuzzers" | ||
# Fuzz for 1 hour | ||
run: "cd fuzz && ./fuzz_all_native.py --seconds 3600" | ||
- name: "Print failing testcases" | ||
if: failure() | ||
run: find . -type f|fgrep '/testdata/fuzz/'|while read f; do echo $f; cat $f; done | ||
- name: "Save corpus" | ||
uses: "actions/cache/save@13aacd865c20de90d75de3b17ebe84f7a17d57d2" # v4.0.0 | ||
# We save also on failure, so that we can keep the valuable corpus generated that led to finding a crash. | ||
# If the corpus gets clobbered for any reason, we can remove the offending cache from the Github UI. | ||
if: always() | ||
with: | ||
path: "${{ steps.get-corpus-dir.outputs.corpus_dir }}" | ||
key: "${{ steps.restore-corpus.outputs.cache-primary-key }}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
*/fuzzer |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
#!/usr/bin/env python3 | ||
|
||
import argparse | ||
import itertools | ||
import os | ||
import re | ||
import subprocess | ||
import sys | ||
|
||
LIBROOT = "../" | ||
|
||
def main(): | ||
parser = argparse.ArgumentParser( | ||
formatter_class=argparse.RawDescriptionHelpFormatter, | ||
description="\n".join([ | ||
"Fuzz helper to run all native go fuzzers in chainlink", | ||
"", | ||
]), | ||
) | ||
parser.add_argument("--ci", required=False, help="In CI mode we run each parser only briefly once", action="store_true") | ||
parser.add_argument("--seconds", required=False, help="Run for this many seconds of total fuzz time before exiting") | ||
args = parser.parse_args() | ||
|
||
# use float for remaining_seconds so we can represent infinity | ||
if args.seconds: | ||
remaining_seconds = float(args.seconds) | ||
else: | ||
remaining_seconds = float("inf") | ||
|
||
fuzzers = discover_fuzzers() | ||
print(f"🐝 Discovered fuzzers:", file=sys.stderr) | ||
for fuzzfn, path in fuzzers.items(): | ||
print(f"{fuzzfn} in {path}", file=sys.stderr) | ||
|
||
if args.ci: | ||
# only run each fuzzer once for 60 seconds in CI | ||
durations_seconds = [60] | ||
else: | ||
# run forever or until --seconds, with increasingly longer durations per fuzz run | ||
durations_seconds = itertools.chain([5, 10, 30, 90, 270], itertools.repeat(600)) | ||
|
||
for duration_seconds in durations_seconds: | ||
print(f"🐝 Running each fuzzer for {duration_seconds}s before switching to next fuzzer", file=sys.stderr) | ||
for fuzzfn, path in fuzzers.items(): | ||
if remaining_seconds <= 0: | ||
print(f"🐝 Time budget of {args.seconds}s is exhausted. Exiting.", file=sys.stderr) | ||
return | ||
|
||
next_duration_seconds = min(remaining_seconds, duration_seconds) | ||
remaining_seconds -= next_duration_seconds | ||
|
||
print(f"🐝 Running {fuzzfn} in {path} for {next_duration_seconds}s before switching to next fuzzer", file=sys.stderr) | ||
run_fuzzer(fuzzfn, path, next_duration_seconds) | ||
print(f"🐝 Completed running {fuzzfn} in {path} for {next_duration_seconds}s. Total remaining time is {remaining_seconds}s", file=sys.stderr) | ||
|
||
def discover_fuzzers(): | ||
fuzzers = {} | ||
for root, dirs, files in os.walk(LIBROOT): | ||
for file in files: | ||
if not file.endswith("test.go"): continue | ||
with open(os.path.join(root, file), "r") as f: | ||
text = f.read() | ||
# ignore multiline comments | ||
text = re.sub(r"(?s)/[*].*?[*]/", "", text) | ||
# ignore single line comments *except* build tags | ||
text = re.sub(r"//.*", "", text) | ||
# Find every function with a name like FuzzXXX | ||
for fuzzfn in re.findall(r"func\s+(Fuzz\w+)", text): | ||
if fuzzfn in fuzzers: | ||
raise Exception(f"Duplicate fuzz function: {fuzzfn}") | ||
fuzzers[fuzzfn] = os.path.relpath(root, LIBROOT) | ||
return fuzzers | ||
|
||
def run_fuzzer(fuzzfn, dir, duration_seconds): | ||
subprocess.check_call(["go", "test", "-run=^$", f"-fuzz=^{fuzzfn}$", f"-fuzztime={duration_seconds}s", f"./{dir}"], cwd=LIBROOT) | ||
|
||
if __name__ == "__main__": | ||
main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need this giant messy script? IMHO we should prefer to use the tooling as directly as possible, and avoid inheriting all this extra noise.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might not need it, but I need to figure out how to keep the results visible, and downloadable, after each run. Which is what the script does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it does a bunch of other junk and prints confusing messages that aren't about fuzzing, because it was just copied from regular tests. I'm not opposed to aligning these scripts, but we need to be deliberate with what we are doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed.