flowsdk 0.5.3

Safety-first, realistic, behavior-predictable messaging SDK for MQTT and more.
Documentation
name: ClusterFuzzLite Continuous Fuzzing

on:
  # Run on pull requests for PR fuzzing
  pull_request:
    branches: [main]
    paths:
      - 'src/**'
      - 'fuzz/**'
      - '.clusterfuzzlite/**'

  # Run on pushes to main for batch fuzzing
  push:
    branches: [main]
    paths:
      - 'src/**'
      - 'fuzz/**'
      - '.clusterfuzzlite/**'

  # Allow manual triggering
  workflow_dispatch:

  # Run on a schedule for continuous fuzzing
  schedule:
    # Run daily at 2 AM UTC
    - cron: '0 2 * * *'

permissions:
  contents: read
  issues: write
  pull-requests: write
  security-events: write

jobs:
  # PR fuzzing - quick checks on pull requests
  pr-fuzzing:
    name: PR Fuzzing
    runs-on: ubuntu-latest
    if: github.event_name == 'pull_request'
    strategy:
      fail-fast: false
      matrix:
        sanitizer: [address]
    steps:
      - name: Build Fuzzers (${{ matrix.sanitizer }})
        id: build
        uses: google/clusterfuzzlite/actions/build_fuzzers@v1
        with:
          sanitizer: ${{ matrix.sanitizer }}
          language: rust

      - name: Run Fuzzers (${{ matrix.sanitizer }})
        id: run
        uses: google/clusterfuzzlite/actions/run_fuzzers@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          fuzz-seconds: 300  # 5 minutes per target
          mode: 'code-change'
          sanitizer: ${{ matrix.sanitizer }}
          output-sarif: true

      - name: Upload SARIF
        if: always() && steps.run.outcome == 'failure'
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ${{ steps.run.outputs.sarif }}

  # Batch fuzzing - longer runs on main branch
  batch-fuzzing:
    name: Batch Fuzzing
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    strategy:
      fail-fast: false
      matrix:
        #sanitizer: [address, undefined]
        sanitizer: [address]
    steps:
      - name: Build Fuzzers (${{ matrix.sanitizer }})
        id: build
        uses: google/clusterfuzzlite/actions/build_fuzzers@v1
        with:
          sanitizer: ${{ matrix.sanitizer }}
          language: rust

      - name: Run Fuzzers (${{ matrix.sanitizer }})
        id: run
        uses: google/clusterfuzzlite/actions/run_fuzzers@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          fuzz-seconds: 600  # 10 minutes per target
          mode: 'batch'
          sanitizer: ${{ matrix.sanitizer }}
          output-sarif: true

      - name: Upload SARIF
        if: always() && steps.run.outcome == 'failure'
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ${{ steps.run.outputs.sarif }}

  # Continuous fuzzing - long runs on schedule
  continuous-fuzzing:
    name: Continuous Fuzzing
    runs-on: ubuntu-latest
    if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
    strategy:
      fail-fast: false
      matrix:
        #sanitizer: [address, undefined, memory]
        sanitizer: [address]
    steps:
      - name: Build Fuzzers (${{ matrix.sanitizer }})
        id: build
        uses: google/clusterfuzzlite/actions/build_fuzzers@v1
        with:
          sanitizer: ${{ matrix.sanitizer }}
          language: rust

      - name: Run Fuzzers (${{ matrix.sanitizer }})
        id: run
        uses: google/clusterfuzzlite/actions/run_fuzzers@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          fuzz-seconds: 3600  # 1 hour per target
          mode: 'batch'
          sanitizer: ${{ matrix.sanitizer }}
          output-sarif: true

      - name: Upload SARIF
        if: always() && steps.run.outcome == 'failure'
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: ${{ steps.run.outputs.sarif }}

  # Corpus pruning - minimize corpus size
  prune:
    name: Prune Corpus
    runs-on: ubuntu-latest
    if: github.event_name == 'schedule'
    steps:
      - name: Build Fuzzers
        id: build
        uses: google/clusterfuzzlite/actions/build_fuzzers@v1
        with:
          language: rust

      - name: Run Fuzzers (Prune)
        id: run
        uses: google/clusterfuzzlite/actions/run_fuzzers@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          fuzz-seconds: 600
          mode: 'prune'

  # Coverage report
  coverage:
    name: Code Coverage
    runs-on: ubuntu-latest
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    steps:
      - name: Build Fuzzers
        id: build
        uses: google/clusterfuzzlite/actions/build_fuzzers@v1
        with:
          sanitizer: coverage
          language: rust

      - name: Run Fuzzers (Coverage)
        id: run
        uses: google/clusterfuzzlite/actions/run_fuzzers@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          fuzz-seconds: 600
          mode: 'coverage'