-
Notifications
You must be signed in to change notification settings - Fork 12
321 lines (281 loc) · 11.9 KB
/
ci.yml
File metadata and controls
321 lines (281 loc) · 11.9 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
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
name: CI
on:
pull_request:
push:
branches: [main]
jobs:
changes:
name: Detect changes
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
outputs:
non-md: ${{ steps.filter.outputs.non-md }}
docs-templates: ${{ steps.filter.outputs.docs-templates }}
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Detect non-Markdown changes
id: filter
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PUSH_BEFORE: ${{ github.event.before }}
PUSH_SHA: ${{ github.sha }}
run: |
set +e
ZERO_SHA="0000000000000000000000000000000000000000"
if [ -n "$BASE_SHA" ] && [ -n "$HEAD_SHA" ]; then
# Three-dot mirrors GitHub's PR diff (merge-base..head).
files=$(git diff --name-only "$BASE_SHA...$HEAD_SHA")
rc=$?
elif [ -n "$PUSH_BEFORE" ] && [ -n "$PUSH_SHA" ] && [ "$PUSH_BEFORE" != "$ZERO_SHA" ]; then
files=$(git diff --name-only "$PUSH_BEFORE" "$PUSH_SHA")
rc=$?
else
echo "No valid diff range; defaulting to non-md=true and docs-templates=true"
echo "non-md=true" >> "$GITHUB_OUTPUT"
echo "docs-templates=true" >> "$GITHUB_OUTPUT"
exit 0
fi
if [ "$rc" -ne 0 ]; then
echo "git diff failed; defaulting to non-md=true and docs-templates=true"
echo "non-md=true" >> "$GITHUB_OUTPUT"
echo "docs-templates=true" >> "$GITHUB_OUTPUT"
exit 0
fi
echo "Changed files:"
echo "$files"
if [ -z "$files" ] || echo "$files" | grep -qv '\.md$'; then
echo "non-md=true" >> "$GITHUB_OUTPUT"
else
echo "non-md=false" >> "$GITHUB_OUTPUT"
fi
# Spec 041 §5.2: tier-drift triggers when a template or doc-app
# changes. Templates live under docs/_pipeline/templates/, apps
# under docs/_pipeline/apps/, and the doc-pipeline CLI itself
# under src/Reactor.Cli/Docs/.
if echo "$files" | grep -qE '^(docs/_pipeline/templates/|docs/_pipeline/apps/|src/Reactor\.Cli/Docs/)'; then
echo "docs-templates=true" >> "$GITHUB_OUTPUT"
else
echo "docs-templates=false" >> "$GITHUB_OUTPUT"
fi
unit-tests:
name: Unit Tests
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Restore
run: dotnet restore tests/Reactor.Tests/Reactor.Tests.csproj -p:Platform=x64
- name: Test
run: dotnet test tests/Reactor.Tests/Reactor.Tests.csproj --no-restore -p:Platform=x64 --logger "console;verbosity=normal"
integration-tests:
name: Integration Tests
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Restore
run: dotnet restore Reactor.slnx
- name: Test
run: dotnet test tests/Reactor.IntegrationTests/Reactor.IntegrationTests.csproj --no-restore --logger "console;verbosity=normal"
selftests:
name: Selftests
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Restore
run: dotnet restore tests/Reactor.SelfTests/Reactor.SelfTests.csproj -p:Platform=x64
- name: Test
run: dotnet test tests/Reactor.SelfTests/Reactor.SelfTests.csproj --no-restore -p:Platform=x64 --logger "console;verbosity=normal"
build-solution:
name: Build solution
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Restore
run: dotnet restore Reactor.slnx
- name: Build
run: dotnet build Reactor.slnx --no-restore --configuration Release
fuzz-smoke:
name: Fuzz smoke
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
# Fuzz-free pass: walk the seed corpus once through both harness bodies.
# Guards against harness rot (parser API drift, broken seed inputs) without
# needing the libfuzzer-dotnet driver or SharpFuzz instrumentation tool in
# the CI image. Using `dotnet run` keeps the invocation independent of the
# TFM / RID / Platform output-path layout, which has changed twice already.
- name: Smoke run
run: dotnet run --project tests/Reactor.Fuzz/Reactor.Fuzz.csproj -c Release -p:Platform=x64 -- smoke
vulnerable-packages:
name: Vulnerable packages
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Restore
run: dotnet restore Reactor.slnx
# Fail the build on transitive vulnerable packages at High/Critical
# severity. `dotnet list package --vulnerable` exits 0 regardless of
# findings (the table is text output), so we parse the severity column
# ourselves. Matches `> Package … High` / `Critical` rows; Moderate/Low
# surface as warnings only.
- name: Check for vulnerable packages
shell: pwsh
run: |
$output = (dotnet list Reactor.slnx package --vulnerable --include-transitive 2>&1 | Out-String)
$listExit = $LASTEXITCODE
Write-Host $output
# If the tool itself failed (restore error, NU* error, broken sdk),
# we cannot trust the empty-findings result — fail loudly rather
# than silently green-light the gate.
if ($listExit -ne 0) {
Write-Error "dotnet list package --vulnerable failed (exit $listExit). Cannot verify vulnerability status."
exit $listExit
}
$bad = $output -split "`n" | Where-Object {
$_ -match '^\s*>\s+\S+' -and $_ -match '\b(High|Critical)\b'
}
if ($bad) {
Write-Error "High or Critical vulnerable package(s) detected:`n$($bad -join "`n")"
exit 1
}
Write-Host "No High/Critical vulnerable packages."
aot-selftests:
name: AOT Selftests
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
timeout-minutes: 30
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
# Publish the selftest host with NativeAOT. PublishAotInternal=true,
# Platform=x64, and rid=win-x64 are the canonical knobs documented in
# docs/aot-support.md and used by tests/Reactor.AppTests.Host/probe-aot-skips.ps1.
# `-o` pins the publish folder so the run step doesn't depend on the
# default TFM/RID/Platform path layout.
- name: Publish AOT host
run: >
dotnet publish tests/Reactor.AppTests.Host
-p:PublishAotInternal=true
-p:Platform=x64
-r win-x64
-c Release
-o ${{ runner.temp }}/aot-publish
--nologo
# Run the published exe directly (not via `dotnet test`) so we exercise
# the NativeAOT binary. SelfTestRunner.DefaultAotSkipPatterns gates the
# known reflection-bound failures (40 fixtures across Devtools/MCP,
# PropertyGrid auto-discovery, Issue142 XAML metadata, and two framework
# cases); any *new* failure surfaces as exit code 1 and fails the job.
# See docs/aot-support.md for the skip-list debugging workflow.
- name: Run AOT selftests
shell: pwsh
run: |
$exe = Join-Path '${{ runner.temp }}/aot-publish' 'Reactor.AppTests.Host.exe'
if (-not (Test-Path $exe)) {
Write-Error "AOT-published host not found at $exe"
exit 1
}
& $exe --self-test 2>&1 | Tee-Object -FilePath aot-selftest-output.tap
exit $LASTEXITCODE
- name: Upload TAP output
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: aot-selftest-tap
path: aot-selftest-output.tap
if-no-files-found: ignore
docs-check-tier:
name: Docs tier-drift
needs: changes
if: needs.changes.outputs.docs-templates == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
# Spec 041 §5.2 — fast tier-drift gate. Fails when a template's
# declared tier no longer matches the §11 structural checklist. The
# narrower `check-tier` surface runs in ~seconds vs. the full
# `docs compile` (no build, capture, diagrams, or reference-gen).
# `--ci` is not yet flipped on: the existing 24 W001
# winui-ref-not-declared warnings are intentional noise on
# internals/meta pages and are being addressed separately as a
# Phase 5 lint-quality item. Errors (REACTOR_DOC_TIER_001..012)
# still fail the job. See docs/contributing/doc-pipeline.md §8.
- name: Tier-lint
run: dotnet run --project src/Reactor.Cli -- docs check-tier
docs-build:
name: Docs build
needs: changes
if: needs.changes.outputs.non-md == 'true'
runs-on: windows-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup .NET
uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
with:
dotnet-version: 10.0.x
- name: Compile docs
run: dotnet run --project src/Reactor.Cli -- docs compile --no-screenshots --ci
- uses: actions/setup-python@v6
with:
python-version: '3.12'
cache: pip
cache-dependency-path: docs/requirements.txt
- name: Install MkDocs
run: pip install -r docs/requirements.txt
# Strict link/anchor check against the docs just compiled above,
# mirroring the Pages publish workflow (.github/workflows/docs.yml).
# `--strict` turns a broken cross-link or missing nav file into a
# failure, so it fails the PR instead of the post-merge publish (the
# only place --strict ran before). Folded into this job so there is a
# single docs build.
- name: mkdocs build --strict
run: python -m mkdocs build --strict