generated from bitcoin-sv/template
-
-
Notifications
You must be signed in to change notification settings - Fork 1
266 lines (241 loc) · 11.6 KB
/
fortress-test-fuzz.yml
File metadata and controls
266 lines (241 loc) · 11.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
# ------------------------------------------------------------------------------------
# Fuzz Testing (Reusable Workflow) (GoFortress)
#
# Purpose: Execute Go fuzz tests to detect edge cases and potential security
# vulnerabilities through automated input generation and testing.
#
# This workflow handles:
# - Fuzz test execution on primary runner with primary Go version
# - Panic and error detection from fuzz test output
# - Failure analysis and structured reporting
# - Statistics collection and artifact uploading
# - Cache performance tracking
#
# Maintainer: @mrz1836
#
# ------------------------------------------------------------------------------------
name: GoFortress (Fuzz Tests)
on:
workflow_call:
inputs:
env-json:
description: "JSON string of environment variables"
required: true
type: string
primary-runner:
description: "Primary runner OS"
required: true
type: string
go-primary-version:
description: "Primary Go version"
required: true
type: string
go-secondary-version:
description: "Secondary Go version"
required: true
type: string
fuzz-testing-enabled:
description: "Whether fuzz testing is enabled"
required: true
type: string
go-sum-file:
description: "Path to go.sum file for dependency verification"
required: true
type: string
secrets:
github-token:
description: "GitHub token for private module authentication (optional, only needed when GOPRIVATE is set)"
required: false
# Security: Restrict default permissions (jobs must explicitly request what they need)
permissions: {}
jobs:
# ----------------------------------------------------------------------------------
# Fuzz Testing
# ----------------------------------------------------------------------------------
fuzz-tests:
name: 🧪 Fuzz Tests
if: inputs.fuzz-testing-enabled == 'true'
timeout-minutes: 15 # Fuzz tests have shorter timeout
permissions:
contents: read # Read repository content for testing
runs-on: ${{ inputs.primary-runner }}
steps:
# --------------------------------------------------------------------
# Checkout code (required for local actions)
# --------------------------------------------------------------------
- name: 📥 Checkout code
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
# --------------------------------------------------------------------
# Parse environment variables
# --------------------------------------------------------------------
- name: 🔧 Parse environment variables
uses: ./.github/actions/parse-env
with:
env-json: ${{ inputs.env-json }}
# --------------------------------------------------------------------
# Setup Go with caching and version management (primary version only)
# --------------------------------------------------------------------
- name: 🏗️ Setup Go with Cache
id: setup-go-fuzz
uses: ./.github/actions/setup-go-with-cache
with:
go-version: ${{ inputs.go-primary-version }}
matrix-os: ${{ inputs.primary-runner }}
go-primary-version: ${{ inputs.go-primary-version }}
go-secondary-version: ${{ inputs.go-secondary-version }}
go-sum-file: ${{ inputs.go-sum-file }}
enable-multi-module: ${{ env.ENABLE_MULTI_MODULE_TESTING }}
github-token: ${{ secrets.github-token }}
# --------------------------------------------------------------------
# Extract Go module directory from GO_SUM_FILE path
# --------------------------------------------------------------------
- name: 🔧 Extract Go module directory
uses: ./.github/actions/extract-module-dir
with:
go-sum-file: ${{ inputs.go-sum-file }}
# --------------------------------------------------------------------
# Setup MAGE-X (required for magex test commands)
# --------------------------------------------------------------------
- name: 🔧 Setup MAGE-X
uses: ./.github/actions/setup-magex
with:
magex-version: ${{ env.MAGE_X_VERSION }}
runner-os: ${{ inputs.primary-runner }}
use-local: ${{ env.MAGE_X_USE_LOCAL }}
# --------------------------------------------------------------------
# Start fuzz test timer
# --------------------------------------------------------------------
- name: ⏱️ Start fuzz test timer
id: fuzz-timer
run: |
echo "fuzz-start=$(date +%s)" >> $GITHUB_OUTPUT
echo "🕒 Fuzz test timer started at: $(date -u +%Y-%m-%dT%H:%M:%SZ)"
# --------------------------------------------------------------------
# Run fuzz tests
# --------------------------------------------------------------------
- name: 🧪 Run fuzz tests
id: run-fuzz-tests
continue-on-error: true
run: |
echo "🧪 Running fuzz tests in parallel..."
FUZZ_TIMEOUT="${TEST_TIMEOUT_FUZZ:-5m}"
GO_MODULE_DIR="${{ env.GO_MODULE_DIR }}"
if [ -n "$GO_MODULE_DIR" ]; then
echo "🔧 Running magex test:fuzz from directory: $GO_MODULE_DIR"
(cd "$GO_MODULE_DIR" && magex test:fuzz time=5s -timeout $FUZZ_TIMEOUT) 2>&1 | tee fuzz-output.log
else
echo "🔧 Running magex test:fuzz from repository root"
magex test:fuzz time=5s -timeout $FUZZ_TIMEOUT 2>&1 | tee fuzz-output.log
fi
FUZZ_EXIT_CODE=${PIPESTATUS[0]}
echo "🔧 Fuzz tests completed with timeout: $FUZZ_TIMEOUT"
# Store the exit code for later steps
echo "FUZZ_EXIT_CODE=$FUZZ_EXIT_CODE" >> $GITHUB_ENV
echo "fuzz-exit-code=$FUZZ_EXIT_CODE" >> $GITHUB_OUTPUT
if [[ $FUZZ_EXIT_CODE -eq 0 ]]; then
echo "✅ Fuzz tests completed successfully"
else
echo "❌ Fuzz tests failed with exit code $FUZZ_EXIT_CODE"
fi
# --------------------------------------------------------------------
# Fuzz test failure analysis and reporting (using magex CI mode JSONL output)
# --------------------------------------------------------------------
- name: 🚨 Create Fuzz Test Failure Summary
if: failure()
run: |
echo "## 🚨 Fuzz Test Failures" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "- **OS**: ${{ inputs.primary-runner }}" >> $GITHUB_STEP_SUMMARY
echo "- **Go Version**: ${{ inputs.go-primary-version }}" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
# Use magex CI mode JSONL output if available
JSONL_FILE=".mage-x/ci-results-fuzz.jsonl"
if [ -f "$JSONL_FILE" ]; then
FAIL_COUNT=$(grep -c '"type":"failure"' "$JSONL_FILE" 2>/dev/null || echo "0")
echo "- **Failed Fuzz Tests**: $FAIL_COUNT" >> $GITHUB_STEP_SUMMARY
if [ "$FAIL_COUNT" -gt 0 ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔍 Failed Fuzz Tests" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
grep '"type":"failure"' "$JSONL_FILE" | head -5 | jq -r '.failure.test + " - " + (.failure.error // "test failed")' >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
fi
elif [ -f fuzz-output.log ]; then
# Fallback to log file parsing
FAIL_COUNT=$(grep -c -E "^--- FAIL:" fuzz-output.log 2>/dev/null || echo "0")
echo "- **Failed Fuzz Tests**: $FAIL_COUNT" >> $GITHUB_STEP_SUMMARY
if [ "$FAIL_COUNT" -gt 0 ]; then
echo "" >> $GITHUB_STEP_SUMMARY
echo "### 🔍 Failed Fuzz Tests" >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
grep -E "^--- FAIL:" fuzz-output.log | head -5 >> $GITHUB_STEP_SUMMARY
echo '```' >> $GITHUB_STEP_SUMMARY
fi
else
echo "⚠️ No fuzz test output found" >> $GITHUB_STEP_SUMMARY
fi
# --------------------------------------------------------------------
# Create GitHub annotations for fuzz test failures
# --------------------------------------------------------------------
- name: 📋 Annotate Key Fuzz Test Failures
if: failure()
run: |
# Use magex CI mode JSONL output if available
JSONL_FILE=".mage-x/ci-results-fuzz.jsonl"
if [ -f "$JSONL_FILE" ]; then
FAIL_COUNT=$(grep -c '"type":"failure"' "$JSONL_FILE" 2>/dev/null || echo "0")
echo "::error title=Fuzz Test Suite Failed::$FAIL_COUNT fuzz tests failed on ${{ inputs.primary-runner }} Go ${{ inputs.go-primary-version }}"
# Annotate first 3 failures from JSONL
if [ "$FAIL_COUNT" -gt 0 ]; then
grep '"type":"failure"' "$JSONL_FILE" | head -3 | while read -r line; do
TEST=$(echo "$line" | jq -r '.failure.test')
ERROR=$(echo "$line" | jq -r '.failure.error // "test failed"')
echo "::error title=Failed Fuzz Test::$TEST - $ERROR"
done
fi
elif [ -f fuzz-output.log ]; then
# Fallback to log file parsing
FAIL_COUNT=$(grep -c -E "^--- FAIL:" fuzz-output.log 2>/dev/null || echo "0")
echo "::error title=Fuzz Test Suite Failed::$FAIL_COUNT fuzz tests failed on ${{ inputs.primary-runner }} Go ${{ inputs.go-primary-version }}"
if [ "$FAIL_COUNT" -gt 0 ]; then
grep -E "^--- FAIL:" fuzz-output.log | head -3 | while read -r line; do
echo "::error title=Failed Fuzz Test::$line"
done
fi
fi
# --------------------------------------------------------------------
# Collect performance cache statistics
# --------------------------------------------------------------------
- name: 📊 Collect performance cache statistics
uses: ./.github/actions/collect-cache-stats
with:
workflow-name: fuzz
job-name: fuzz-tests
os: ${{ inputs.primary-runner }}
go-version: ${{ inputs.go-primary-version }}
cache-prefix: cache-stats
gomod-cache-hit: ${{ steps.setup-go-fuzz.outputs.module-cache-hit }}
gobuild-cache-hit: ${{ steps.setup-go-fuzz.outputs.build-cache-hit }}
# --------------------------------------------------------------------
# Upload performance cache statistics for completion report
# --------------------------------------------------------------------
- name: 📤 Upload performance cache statistics
if: always()
uses: ./.github/actions/upload-statistics
with:
artifact-name: cache-stats-fuzz
artifact-path: cache-stats-fuzz.json
retention-days: "1"
# --------------------------------------------------------------------
# Upload fuzz test outputs and failures for validation
# --------------------------------------------------------------------
- name: 📤 Upload fuzz test outputs
if: always()
uses: ./.github/actions/upload-artifact-resilient
with:
artifact-name: test-results-fuzz-${{ inputs.primary-runner }}-${{ inputs.go-primary-version }}
artifact-path: |
.mage-x/ci-results-fuzz.jsonl
fuzz-output.log
retention-days: "7"
if-no-files-found: ignore