Skip to content

Commit

Permalink
consolidate to one reusable workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
rfratto committed Apr 27, 2024
1 parent fb85a35 commit b92bea2
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 127 deletions.
61 changes: 0 additions & 61 deletions .github/workflows/fuzz-find-go.yml

This file was deleted.

15 changes: 2 additions & 13 deletions .github/workflows/fuzz-go-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,8 @@ name: Run Go fuzz tests (PR)
on:
pull_request:
jobs:
find-tests:
name: Find fuzz tests
uses: ./.github/workflows/fuzz-find-go.yml

fuzz:
name: "${{ matrix.package }}: ${{ matrix.function }}"
needs: [find-tests]
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.find-tests.outputs.tests) }}
uses: ./.github/workflows/fuzz-run-go.yml
uses: ./.github/workflows/fuzz-go.yml
with:
package-path: ${{ matrix.package }}
test-name: ${{ matrix.function }}
fuzz-time: 5m

14 changes: 1 addition & 13 deletions .github/workflows/fuzz-go-scheduled.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,8 @@ on:
- cron: '0 0 * * *'

jobs:
find-tests:
name: Find fuzz tests
uses: ./.github/workflows/fuzz-find-go.yml

fuzz:
name: "${{ matrix.package }}: ${{ matrix.function }}"
needs: [find-tests]
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.find-tests.outputs.tests) }}
uses: ./.github/workflows/fuzz-run-go.yml
uses: ./.github/workflows/fuzz-go.yml
with:
package-path: ${{ matrix.package }}
test-name: ${{ matrix.function }}
fuzz-time: 30m
create-issue: true
99 changes: 59 additions & 40 deletions .github/workflows/fuzz-run-go.yml → .github/workflows/fuzz-go.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,12 @@
# Run Go fuzz test is a reusable workflow that runs a single Go fuzz test.
#
# The workflow runs until fuzz-time has elapsed or a test case which causes the
# test to fail is found. If a new failure is found, the workflow will fail and
# upload the failing test case as an artifact.
#
# The workflow assumes that the code has already been checked out.

name: Run Go fuzz test
name: Run Go fuzz tests

on:
workflow_call:
inputs:
package-path:
description: "Directory of the Go package to run a Fuzz test in."
required: true
type: string
test-name:
description: "Full name of the Fuzz test to run."
required: true
directory:
description: "Directory to search for Go fuzz tests in."
default: '.'
required: false
type: string
fuzz-time:
description: "Time to run the Fuzz test for. (for example, 5m)"
Expand All @@ -28,23 +18,52 @@ on:
default: false
type: boolean

jobs:
find-tests:
runs-on: ubuntu-latest
outputs:
arifact-name:
description: "Name of the artifact that was uploaded. Only use when the workflow fails."
value: ${{ jobs.fuzz.outputs.artifact-name }}
failure-name:
description: "Name of the test case that failed. Only use when the workflow fails."
value: ${{ jobs.fuzz.outputs.failure-name }}
failure-path:
description: "Path to place the failure artifact. Only use when the workflow fails."
value: ${{ inputs.package-path }}/testdata/fuzz/${{ inputs.test-name }}
tests: ${{ steps.find-tests.outputs.tests }}
steps:
- uses: actions/checkout@v4
- name: Find fuzz tests
id: find-tests
run: |
TEST_FILES=$(find "${{ inputs.directory }}" -name '*_test.go' -not -path './vendor/*')
RESULTS=()
for FILE in $TEST_FILES; do
FUZZ_FUNC=$(grep -E 'func Fuzz\w*' $FILE | sed 's/func //' | sed 's/(.*$//')
if [ -z "$FUZZ_FUNC" ]; then
continue
fi
PACKAGE_PATH=$(dirname ${FILE#${{ inputs.directory }}/})
RESULTS+=("{\"package\":\"$PACKAGE_PATH\",\"function\":\"$FUZZ_FUNC\"}")
echo "Found $FUZZ_FUNC in $PACKAGE_PATH"
done
NUM_RESULTS=${#RESULTS[@]}
INCLUDE_STRING=""
for (( i=0; i<$NUM_RESULTS; i++ )); do
INCLUDE_STRING+="${RESULTS[$i]}"
if [[ $i -lt $(($NUM_RESULTS-1)) ]]; then
INCLUDE_STRING+=","
fi
done
echo 'tests=['$INCLUDE_STRING']' >> $GITHUB_OUTPUT
jobs:
fuzz:
name: "${{ matrix.package }}: ${{ matrix.function }}"
runs-on: ubuntu-latest
outputs:
artifact-name: failure-${{ steps.new-failure.outputs.package }}-${{ steps.new-failure.outputs.function }}
failure-name: ${{ steps.new-failure.outputs.name }}
needs: [find-tests]
strategy:
fail-fast: false
matrix:
include: ${{ fromJson(needs.find-tests.outputs.tests) }}
steps:
- uses: actions/checkout@v4

Expand All @@ -62,17 +81,17 @@ jobs:
uses: actions/cache@v4
with:
path: ${{ env.FUZZ_CACHE }}
key: fuzz-${{ inputs.package-path }}-${{ inputs.test-name }}-${{ github.sha }}
key: fuzz-${{ matrix.package }}-${{ matrix.function }}-${{ github.sha }}
restore-keys: |
fuzz-${{ inputs.package-path }}-${{ inputs.test-name }}-
fuzz-${{ matrix.package }}-${{ matrix.function }}-
- name: Fuzz
run: |
# Change directory to the package first, since go test doesn't
# support cross-module testing, and the provided directory may be in
# a different module.
cd "${{ inputs.package-path }}"
go test -fuzz="${{ inputs.test-name }}\$" -run="${{ inputs.test-name }}\$" -fuzztime="${{ inputs.fuzz-time }}" .
cd "${{ matrix.package }}"
go test -fuzz="${{ matrix.function }}\$" -run="${{ matrix.function }}\$" -fuzztime="${{ inputs.fuzz-time }}" .
# Fuzzing may have failed because of an existing bug, or it may have
# found a new one and written a new test case file in testdata/ relative
Expand All @@ -92,8 +111,8 @@ jobs:
echo "Found new fuzz failure: $UNTRACKED"
echo "file=$UNTRACKED" >> $GITHUB_OUTPUT
echo "name=$(basename $UNTRACKED)" >> $GITHUB_OUTPUT
echo "package=$(echo ${{ inputs.package-path }} | sed 's/\//_/g')" >> $GITHUB_OUTPUT
echo "function=${{ inputs.test-name }}" >> $GITHUB_OUTPUT
echo "package=$(echo ${{ matrix.package }} | sed 's/\//_/g')" >> $GITHUB_OUTPUT
echo "function=${{ matrix.function }}" >> $GITHUB_OUTPUT
- name: Upload fuzz failure as artifact
id: artifact
Expand All @@ -109,11 +128,11 @@ jobs:
cat >>$GITHUB_STEP_SUMMARY <<EOF
## Fuzz test failed
A new fuzz test failure was found in ${{ inputs.package-path }}.
A new fuzz test failure was found in ${{ matrix.package }}.
To reproduce the failure locally, run the following command using the GitHub CLI to download the failed test case:
<pre lang="bash">gh run download --repo ${{ github.repository }} ${{ github.run_id }} -n failure-${{ steps.new-failure.outputs.package }}-${{ steps.new-failure.outputs.function }} --dir ${{ inputs.package-path }}/testdata/fuzz/${{ inputs.test-name }}</pre>
<pre lang="bash">gh run download --repo ${{ github.repository }} ${{ github.run_id }} -n failure-${{ steps.new-failure.outputs.package }}-${{ steps.new-failure.outputs.function }} --dir ${{ matrix.package }}/testdata/fuzz/${{ matrix.function }}</pre>
When opening a PR with the fix, please include the test case file in your PR to prevent regressions.
EOF
Expand All @@ -124,7 +143,7 @@ jobs:
with:
script: |
const failureName = "${{ steps.new-failure.outputs.name }}";
const issueTitle = `${{ inputs.package-path }}: ${{ inputs.test-name }} failed (${failureName})`;
const issueTitle = `${{ matrix.package }}: ${{ matrix.function }} failed (${failureName})`;
// Look for existing issue first with the same title.
const issues = await github.rest.search.issuesAndPullRequests({
Expand All @@ -141,11 +160,11 @@ jobs:
repo: context.repo.repo,
title: issueTitle,
body: `
A new fuzz test failure was found in <code>${{ inputs.package-path }}</code>.
A new fuzz test failure was found in <code>${{ matrix.package }}</code>.
To reproduce the failure locally, run the following command using the GitHub CLI to download the failed test case:
<pre lang="bash">gh run download --repo ${{ github.repository }} ${{ github.run_id }} -n failure-${{ steps.new-failure.outputs.package }}-${{ steps.new-failure.outputs.function }} --dir ${{ inputs.package-path }}/testdata/fuzz/${{ inputs.test-name }}</pre>
<pre lang="bash">gh run download --repo ${{ github.repository }} ${{ github.run_id }} -n failure-${{ steps.new-failure.outputs.package }}-${{ steps.new-failure.outputs.function }} --dir ${{ matrix.package }}/testdata/fuzz/${{ matrix.function }}</pre>
When opening a PR with the fix, please include the test case file in your PR to prevent regressions.
Expand Down

0 comments on commit b92bea2

Please sign in to comment.