# Runs fuzzing nightly.
name: Fuzz Tests
on:
  workflow_dispatch:  # allow running workflow manually
  schedule:
    - cron: '0 3 * * *'
  pull_request:
    branches:
      - v0.38.x
    paths:
      - "test/fuzz/**/*.go"

jobs:
  fuzz-nightly-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-go@v5
        with:
          go-version: '1.22'

      - uses: actions/checkout@v4

      - name: Install go-fuzz
        working-directory: test/fuzz
        run: go install github.com/dvyukov/go-fuzz/go-fuzz@latest github.com/dvyukov/go-fuzz/go-fuzz-build@latest

      - name: Fuzz mempool
        working-directory: test/fuzz
        run: timeout -s SIGINT --preserve-status 10m make fuzz-mempool
        continue-on-error: true

      - name: Fuzz p2p-addrbook
        working-directory: test/fuzz
        run: timeout -s SIGINT --preserve-status 10m make fuzz-p2p-addrbook
        continue-on-error: true

      - name: Fuzz p2p-pex
        working-directory: test/fuzz
        run: timeout -s SIGINT --preserve-status 10m make fuzz-p2p-pex
        continue-on-error: true

      - name: Fuzz p2p-sc
        working-directory: test/fuzz
        run: timeout -s SIGINT --preserve-status 10m make fuzz-p2p-sc
        continue-on-error: true

      - name: Fuzz p2p-rpc-server
        working-directory: test/fuzz
        run: timeout -s SIGINT --preserve-status 10m make fuzz-rpc-server
        continue-on-error: true

      - name: Archive crashers
        uses: actions/upload-artifact@v4
        with:
          name: crashers
          path: test/fuzz/**/crashers
          retention-days: 3

      - name: Archive suppressions
        uses: actions/upload-artifact@v4
        with:
          name: suppressions
          path: test/fuzz/**/suppressions
          retention-days: 3

      - name: Set crashers count
        working-directory: test/fuzz
        run: echo "count=$(find . -type d -name 'crashers' | xargs -I % sh -c 'ls % | wc -l' | awk '{total += $1} END {print total}')" >> $GITHUB_OUTPUT
        id: set-crashers-count

    outputs:
      crashers-count: ${{ steps.set-crashers-count.outputs.count }}

  fuzz-nightly-fail:
    needs: fuzz-nightly-test
    if: ${{ needs.fuzz-nightly-test.outputs.crashers-count != 0 }}
    runs-on: ubuntu-latest
    steps:
      - name: Notify Slack on failure
        uses: slackapi/slack-github-action@v2.0.0
        env:
          BRANCH: ${{ github.ref_name }}
          CRASHERS: ${{ needs.fuzz-nightly-test.outputs.crashers-count }}
          RUN_URL: "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
        with:
          webhook: ${{ secrets.SLACK_WEBHOOK_URL }}
          webhook-type: incoming-webhook
          payload: |
            blocks:
              - type: "section"
                text:
                  type: "mrkdwn"
                  text: ":skull: Nightly fuzz tests for `${{ env.BRANCH }}` failed with ${{ env.CRASHERS }} crasher(s). See the <${{ env.RUN_URL }}|run details>."
