kinjo 0.3.8

Kinjo: mDNS TUI and commands launch for local network services
Documentation
name: Fuzz

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
  schedule:
    # Monday 03:00 UTC — longer soak run.
    - 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 # v7
        with:
          persist-credentials: false

      - name: Install nightly toolchain
        uses: dtolnay/rust-toolchain@2c7215f132e9ebf062739d9130488b56d53c060c # master
        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 # v3
        with:
          tool: cargo-fuzz@0.13.2

      # Restore the newest corpus from earlier runs and save this run's
      # additions under a fresh key, so coverage accumulates across runs
      # instead of restarting from the seed inputs every time.
      - name: Restore accumulated corpus
        uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6
        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 # v7
        with:
          name: fuzz-artifacts
          path: fuzz/artifacts/
          if-no-files-found: ignore