fmtbuf 0.2.0

Utilities for formatting to a fixed-size buffer
Documentation
name: fuzz

on:
  # Gate every PR that touches fuzz-relevant code, plus the same files on direct push to
  # `trunk` as a backstop. `paths:`-filtered so docs-only / CI-only PRs don't pay the cost.
  # No `schedule:` -- the fuzzer offers no signal when the code hasn't changed.
  # Use `workflow_dispatch` for ad-hoc longer runs (e.g. before tagging a release).
  pull_request:
    branches: [trunk]
    paths:
      - 'src/**'
      - 'fuzz/**'
      - 'Cargo.toml'
      - '.github/workflows/fuzz.yml'
  push:
    branches: [trunk]
    paths:
      - 'src/**'
      - 'fuzz/**'
      - 'Cargo.toml'
      - '.github/workflows/fuzz.yml'
  workflow_dispatch:
    inputs:
      duration_seconds:
        description: 'Per-target fuzzing time in seconds'
        required: false
        default: '150'

env:
  CARGO_TERM_COLOR: always

jobs:
  fuzz:
    runs-on: ubuntu-latest
    strategy:
      # Run targets in parallel rather than serially; each one has its own corpus and shares no
      # state with the other.
      fail-fast: false
      matrix:
        target: [finish_with, write_sequence]
    steps:
    - uses: actions/checkout@v4
    - name: Install nightly toolchain
      run: rustup toolchain install nightly --profile minimal --component rust-src
    - name: Install cargo-fuzz
      run: cargo install cargo-fuzz --locked
    - name: Restore corpus
      # `key` is per-run via `github.run_id` so each job writes a fresh entry;
      # `restore-keys` matches the per-target prefix, so every run bootstraps from whatever
      # corpus the most recent run for the same target left behind.
      uses: actions/cache@v4
      with:
        path: fuzz/corpus/${{ matrix.target }}
        key: fuzz-corpus-${{ matrix.target }}-${{ github.run_id }}
        restore-keys: fuzz-corpus-${{ matrix.target }}-
    - name: Run fuzzer
      run: |
        cargo +nightly fuzz run ${{ matrix.target }} -- \
          -max_total_time=${{ github.event.inputs.duration_seconds || '150' }}
    - name: Upload crash artifacts
      if: failure()
      uses: actions/upload-artifact@v4
      with:
        name: fuzz-artifacts-${{ matrix.target }}
        path: fuzz/artifacts/${{ matrix.target }}/
        if-no-files-found: ignore