Skip to content

fuzz-nightly

fuzz-nightly #1

Workflow file for this run

name: fuzz-nightly
on:
schedule:
- cron: '0 18 * * *' # 18:00 UTC = 02:00 China next day
workflow_dispatch:
inputs:
budget:
description: 'Fuzz budget in seconds'
required: false
default: '600'
permissions:
contents: read
issues: write
jobs:
fuzz:
runs-on: ubuntu-22.04
env:
OPENRESTY_PREFIX: "/usr/local/openresty"
FUZZ_BUDGET: ${{ github.event.inputs.budget || '600' }}
steps:
- name: Check out code
uses: actions/checkout@v4
- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential libncurses5-dev libreadline-dev libssl-dev perl lua5.1 liblua5.1-0-dev
- name: Install OpenResty
run: |
wget -qO - https://openresty.org/package/pubkey.gpg | sudo gpg --dearmor -o /usr/share/keyrings/openresty.gpg
echo "deb [signed-by=/usr/share/keyrings/openresty.gpg] http://openresty.org/package/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/openresty.list
sudo apt-get update
sudo apt-get install -y openresty
- name: Install LuaRocks
run: |
LUAROCKS_VER=3.12.0
wget -q "https://github.com/luarocks/luarocks/archive/v${LUAROCKS_VER}.tar.gz"
tar xzf "v${LUAROCKS_VER}.tar.gz"
cd "luarocks-${LUAROCKS_VER}"
./configure --with-lua=$OPENRESTY_PREFIX/luajit
make build && sudo make install
cd .. && rm -rf "luarocks-${LUAROCKS_VER}" "v${LUAROCKS_VER}.tar.gz"
# Configure OpenSSL paths for rocks that need it
OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl3
if [ ! -d "$OPENSSL_PREFIX" ]; then
OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl111
fi
if [ ! -d "$OPENSSL_PREFIX" ]; then
OPENSSL_PREFIX=$OPENRESTY_PREFIX/openssl
fi
if [ -d "$OPENSSL_PREFIX" ]; then
luarocks config variables.OPENSSL_LIBDIR ${OPENSSL_PREFIX}/lib
luarocks config variables.OPENSSL_INCDIR ${OPENSSL_PREFIX}/include
fi
- name: Install Lua dependencies
run: |
sudo luarocks install jsonschema
sudo luarocks install lua-resty-radixtree
- name: Run mutation fuzzer
id: fuzz
continue-on-error: true
run: |
export PATH=$OPENRESTY_PREFIX/nginx/sbin:$OPENRESTY_PREFIX/bin:$PATH
case "$FUZZ_BUDGET" in
''|*[!0-9]*)
echo "FUZZ_BUDGET must be an integer number of seconds" >&2
exit 2
;;
esac
make fuzz "FUZZ_BUDGET=$FUZZ_BUDGET"
- name: Upload findings
if: steps.fuzz.outcome == 'failure'
uses: actions/upload-artifact@v4
with:
name: fuzz-findings-${{ github.run_id }}
path: fuzz/out/
retention-days: 90
- name: Open / update tracking issue
if: steps.fuzz.outcome == 'failure'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
DATE=$(date -u +%Y-%m-%d)
TITLE="Nightly fuzz failure: $DATE"
RUN_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
SUMMARY=$(cat fuzz/out/summary.json 2>/dev/null || echo '{}')
FIRST5=$(head -n 5 fuzz/out/crashes.jsonl 2>/dev/null || echo '(no crashes.jsonl found)')
BODY=$(cat <<EOF
The nightly fuzz run failed.
- Run: $RUN_URL
- Summary: \`$SUMMARY\`
- Findings artifact: \`fuzz-findings-${{ github.run_id }}\` (attached to the run, retained 90 days)
First 5 findings:
\`\`\`
$FIRST5
\`\`\`
To reproduce locally:
\`\`\`
make fuzz FUZZ_BUDGET=$FUZZ_BUDGET
\`\`\`
EOF
)
# De-dup: reuse any open issue with the fuzz-nightly label.
existing=$(gh issue list --label fuzz-nightly --state open \
--json number --jq '.[0].number // empty' || echo "")
if [ -n "$existing" ]; then
gh issue comment "$existing" --body "$BODY"
gh issue edit "$existing" --add-assignee jarvis9443 || true
else
# Ensure label exists (idempotent).
gh label create fuzz-nightly --color FBCA04 \
--description "Findings from the nightly fuzz job" 2>/dev/null || true
gh issue create --title "$TITLE" \
--label fuzz-nightly,bug \
--assignee jarvis9443 \
--body "$BODY"
fi
- name: Fail the job if fuzz failed
if: steps.fuzz.outcome == 'failure'
run: exit 1