name: Fuzz
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
schedule:
- cron: '0 3 * * 1'
workflow_dispatch:
inputs:
seconds:
description: "Seconds to run each fuzz target"
required: true
default: 300
type: number
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
CARGO_TERM_COLOR: always
jobs:
fuzz:
runs-on: ubuntu-24.04
timeout-minutes: 90
env:
FUZZ_TOOLCHAIN: nightly-2026-07-01
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 with:
persist-credentials: false
- name: Install nightly toolchain
uses: dtolnay/rust-toolchain@2c7215f132e9ebf062739d9130488b56d53c060c with:
toolchain: nightly-2026-07-01
- name: Set up build environment
uses: ./.github/actions/setup
with:
cache-workspaces: fuzz
- name: Install cargo-fuzz
uses: taiki-e/cache-cargo-install-action@417450f3c33ee20393705369577571770643d4c7 with:
tool: cargo-fuzz@0.13.2
- name: Restore accumulated corpus
uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 with:
path: fuzz/corpus
key: fuzz-corpus-${{ github.run_id }}
restore-keys: fuzz-corpus-
- name: Pick duration
id: dur
env:
REQUESTED_SECONDS: ${{ inputs.seconds }}
run: |
case "${{ github.event_name }}" in
schedule) echo "seconds=600" >> "$GITHUB_OUTPUT" ;;
workflow_dispatch)
if [[ ! "$REQUESTED_SECONDS" =~ ^[0-9]+$ ]] ||
(( REQUESTED_SECONDS < 1 || REQUESTED_SECONDS > 900 )); then
echo "::error::seconds must be an integer from 1 to 900"
exit 1
fi
echo "seconds=$REQUESTED_SECONDS" >> "$GITHUB_OUTPUT"
;;
*) echo "seconds=60" >> "$GITHUB_OUTPUT" ;;
esac
- name: Run fuzz targets
run: scripts/fuzz.sh "${{ steps.dur.outputs.seconds }}"
- name: Upload crash artifacts
if: failure()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a with:
name: fuzz-artifacts
path: fuzz/artifacts/
if-no-files-found: ignore