Main Fuzz Saturate #7
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # .github/workflows/main-fuzz.yml | |
| name: Main Fuzz Saturate | |
| on: | |
| workflow_dispatch: | |
| schedule: | |
| - cron: "0 2 * * 6" | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| concurrency: | |
| group: fuzz-main | |
| cancel-in-progress: true | |
| jobs: | |
| discover: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| outputs: | |
| results: ${{ steps.q.outputs.results }} | |
| count: ${{ steps.q.outputs.count }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| - uses: ./.github/actions/setup | |
| with: | |
| fetch-depth: 1 | |
| cache-pnpm: false | |
| - id: q | |
| uses: ./.github/actions/moon-q-projects | |
| with: | |
| task: fuzz-ci | |
| saturate: | |
| needs: discover | |
| if: fromJson(needs.discover.outputs.count) > 0 | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 360 | |
| permissions: | |
| contents: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| project: ${{ fromJson(needs.discover.outputs.results) }} | |
| env: | |
| FUZZ_MAXTIME: "14400" | |
| FUZZ_JOBS: "4" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| - uses: ./.github/actions/setup | |
| with: | |
| fetch-depth: 1 | |
| cache-pnpm: false | |
| - name: Resolve paths | |
| id: paths | |
| run: | | |
| SOURCE="${{ matrix.project.source }}" | |
| CORPUS="${{ matrix.project.metadata.corpus-path }}" | |
| REGRESSIONS="${{ matrix.project.metadata.regressions-path }}" | |
| echo "corpus=${SOURCE}/${CORPUS:-corpus}" >> "$GITHUB_OUTPUT" | |
| echo "regressions=${SOURCE}/${REGRESSIONS:-regressions}" >> "$GITHUB_OUTPUT" | |
| - uses: ./.github/actions/fuzz-cache | |
| with: | |
| mode: pull | |
| project-id: ${{ matrix.project.id }} | |
| corpus-path: ${{ steps.paths.outputs.corpus }} | |
| - name: Fuzz | |
| id: fuzz | |
| continue-on-error: true | |
| uses: ./.github/actions/moon-run | |
| with: | |
| task: ${{ matrix.project.id }}:fuzz-ci | |
| - uses: ./.github/actions/fuzz-cache | |
| if: always() && steps.fuzz.outcome != 'skipped' | |
| with: | |
| mode: push | |
| project-id: ${{ matrix.project.id }} | |
| corpus-path: ${{ steps.paths.outputs.corpus }} | |
| - name: Triage | |
| if: steps.fuzz.outcome == 'failure' | |
| uses: ./.github/actions/moon-run | |
| with: | |
| task: ${{ matrix.project.id }}:fuzz-triage | |
| - uses: actions/upload-artifact@v4 | |
| if: steps.fuzz.outcome == 'failure' | |
| with: | |
| name: fuzz-regressions-${{ matrix.project.id }} | |
| path: ${{ steps.paths.outputs.regressions }}/ | |
| retention-days: 90 | |
| - name: Fail if crashes | |
| if: steps.fuzz.outcome == 'failure' | |
| run: exit 1 | |
| create-pr: | |
| needs: [discover, saturate] | |
| if: failure() | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: write | |
| pull-requests: write | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 1 | |
| - name: Build target map | |
| id: targets | |
| run: | | |
| TARGETS=$(echo '${{ needs.discover.outputs.results }}' \ | |
| | jq -c '[.[] | { | |
| key: .id, | |
| value: (.source + "/" + (.metadata["regressions-path"] // "regressions")) | |
| }] | from_entries') | |
| echo "map=${TARGETS}" >> "$GITHUB_OUTPUT" | |
| - id: stage | |
| uses: ./.github/actions/git-stage-artifacts | |
| with: | |
| artifact-prefix: fuzz-regressions | |
| targets: ${{ steps.targets.outputs.map }} | |
| - name: Build PR metadata | |
| if: steps.stage.outputs.file-count != '0' | |
| id: meta | |
| run: | | |
| PROJECTS="${{ steps.stage.outputs.projects }}" | |
| FILECOUNT="${{ steps.stage.outputs.file-count }}" | |
| PROJECT_COUNT=$(echo "$PROJECTS" | tr ',' '\n' | wc -l) | |
| RUN_URL="${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" | |
| if [[ "$PROJECT_COUNT" -eq 1 ]]; then | |
| TITLE="chore(${PROJECTS}): add ${FILECOUNT} fuzz regression files" | |
| else | |
| TITLE="chore(fuzz): add ${FILECOUNT} regression files across ${PROJECTS}" | |
| fi | |
| { | |
| echo "title=${TITLE}" | |
| echo "body<<EOF" | |
| echo "Automated saturation run found new crashes." | |
| echo "" | |
| echo "**${FILECOUNT} regression files** across \`${PROJECTS}\`." | |
| echo "Triaged and minimized. Merge to add them to the test suite." | |
| echo "" | |
| echo "[View fuzz run](${RUN_URL})" | |
| echo "EOF" | |
| } >> "$GITHUB_OUTPUT" | |
| - uses: ./.github/actions/pr-create | |
| if: steps.stage.outputs.file-count != '0' | |
| with: | |
| add-paths: "**/regressions/" | |
| branch: chore/fuzz-regressions | |
| title: ${{ steps.meta.outputs.title }} | |
| body: ${{ steps.meta.outputs.body }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} |