-
-
Notifications
You must be signed in to change notification settings - Fork 252
190 lines (169 loc) · 6.82 KB
/
Copy pathmutation-affected.yml
File metadata and controls
190 lines (169 loc) · 6.82 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
name: Mutation Affected
# PR-side half of the decision-kernel mutation lane (issue #1415).
#
# Graduation, not a flag day: this job runs on every PR that touches a kernel
# module, but `scripts/mutation/run.ts` only exits non-zero once the committed
# baseline reports `gating: true` — earned by two consecutive stable weekly
# sweeps (mutation-weekly.yml). Until then it is a report with the same numbers,
# so the gate's first failing day is not also its first running day.
#
# Cost control: before graduation an affected run is a report nobody acts on, so
# `select` returns an empty matrix and no mutants run — except when the diff
# touches the lane's own tooling, the one case where a pre-graduation run buys
# something (the gate has to be proven before it can bite).
#
# Scope is the AFFECTED modules only, and affectedness is DERIVED from the import
# graph (scripts/mutation/ownership.ts): a kernel source, or any test that reaches
# one. Reaching a kernel is a superset of killing its mutants, so the `select` job
# frequently returns several modules — sharded like the weekly sweep so the PR's
# wall clock is one module, not their sum. The weekly run stays the full sweep.
on:
pull_request:
paths:
# Kernel sources, every src/package test (ownership is derived, so any
# test may own a kernel — `select` decides, not this filter), and the
# lane's own tooling. scripts/mutation/workflow.test.ts asserts this
# covers the registry.
- 'packages/kernel/src/errors.ts'
- 'src/daemon/ref-frame.ts'
- 'src/commands/interaction/runtime/settle.ts'
- 'src/utils/scroll-edge-state.ts'
- 'packages/selectors/src/**'
- 'packages/ad-script/src/internal/target-annotation-serde.ts'
- 'src/snapshot/snapshot-occlusion.ts'
- 'src/**/*.test.ts'
- 'packages/*/src/**/*.test.ts'
- 'scripts/mutation/**'
- 'scripts/lib/**'
- 'stryker.config.json'
- 'mutation-baselines/**'
- '.github/workflows/mutation-affected.yml'
permissions:
contents: read
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
select:
name: Select affected kernels
runs-on: ubuntu-latest
timeout-minutes: 10
outputs:
modules: ${{ steps.select.outputs.result }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Setup toolchain
uses: ./.github/actions/setup-node-pnpm
- name: Ratchet self-test
uses: ./.github/actions/run-gate
with: { gate: mutation-model }
- id: select
name: Derive the affected shard matrix
uses: ./.github/actions/run-gate
with:
gate: mutation-affected
args: |
--list-affected
--base
origin/${{ github.event.pull_request.base.ref }}
# The self-test and the derivation run before any mutant, so a failure here
# would leave the lane with no envelope at all (#1430).
- name: Record a failed lane envelope
if: failure()
run: |
pnpm gate mutation --affected --fail-envelope \
"affected selection failed before any mutant ran (run ${{ github.run_id }})" || true
- name: Upload selection envelope
if: failure()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: mutation-affected-select
path: .tmp/mutation/lane-envelope.json
if-no-files-found: warn
mutants:
name: Mutants (${{ matrix.name }})
needs: select
if: needs.select.outputs.modules != '[]'
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.select.outputs.modules) }}
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Setup toolchain
uses: ./.github/actions/setup-node-pnpm
- name: Run mutants for ${{ matrix.name }}
uses: ./.github/actions/run-gate
with:
gate: mutation
args: |
--modules
${{ matrix.module }}
${{ matrix.shard && '--shard' || '' }}
${{ matrix.shard || '' }}
- name: Record a failed shard envelope
if: failure()
run: |
pnpm gate mutation --affected --modules ${{ matrix.module }} --fail-envelope \
"shard ${{ matrix.name }} failed before producing a report (run ${{ github.run_id }})" || true
- name: Upload shard report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: mutation-affected-shard-${{ matrix.name }}
path: |
.tmp/mutation/mutation.json
.tmp/mutation/mutation.html
.tmp/mutation/lane-envelope.json
if-no-files-found: warn
ratchet:
name: Affected decision-kernel mutants
needs: [select, mutants]
if: always() && needs.select.result == 'success'
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
- name: Setup toolchain
uses: ./.github/actions/setup-node-pnpm
- name: Download shard reports
if: needs.select.outputs.modules != '[]'
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
with:
pattern: mutation-affected-shard-*
path: .tmp/mutation/shards
# No shards means no affected kernel: run.ts reports "nothing to mutate"
# and still writes the envelope, so the lane is never silently absent.
- name: Ratchet the affected modules
run: |
if [ -d .tmp/mutation/shards ]; then
expected=$(echo '${{ needs.select.outputs.modules }}' | jq length)
pnpm gate mutation-check --report-dir .tmp/mutation/shards --affected \
--expect-shards "$expected" \
--base "origin/${{ github.event.pull_request.base.ref }}"
else
pnpm gate mutation-affected --base "origin/${{ github.event.pull_request.base.ref }}"
fi
- name: Record a failed lane envelope
if: failure()
run: |
pnpm gate mutation --affected --fail-envelope \
"affected ratchet failed before producing a verdict (run ${{ github.run_id }})" || true
- name: Upload mutation report
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: mutation-affected
path: |
.tmp/mutation/shards
.tmp/mutation/lane-envelope.json
if-no-files-found: ignore