code-foundry 1.28.14 → 1.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/actions/setup/action.yml +39 -0
- package/.github/workflows/ci.yml +36 -12
- package/.github/workflows/codeql.yml +6 -0
- package/.github/workflows/eval.yml +9 -3
- package/.github/workflows/test.yml +46 -16
- package/CHANGELOG.md +14 -0
- package/docs/CONFIGURATION.md +31 -0
- package/package.json +1 -1
- package/src/lib/task-filters.mjs +143 -0
- package/src/runtime-core.mjs +17 -2
- package/src/runtime.mjs +20 -0
|
@@ -89,6 +89,15 @@ runs:
|
|
|
89
89
|
if [ -f .github/code-foundry.yml ]; then
|
|
90
90
|
configured_toolchain="$(awk -F': ' '/^toolchain:/ {print $2; exit}' .github/code-foundry.yml)"
|
|
91
91
|
[ -n "$configured_toolchain" ] && toolchain="$configured_toolchain"
|
|
92
|
+
for flag in rust_sccache rust_nextest; do
|
|
93
|
+
if grep -Eq "^${flag}:\\s*[\"']?true[\"']?\\s*$" .github/code-foundry.yml; then
|
|
94
|
+
printf '%s=true\n' "$flag" >> "$GITHUB_OUTPUT"
|
|
95
|
+
else
|
|
96
|
+
printf '%s=false\n' "$flag" >> "$GITHUB_OUTPUT"
|
|
97
|
+
fi
|
|
98
|
+
done
|
|
99
|
+
else
|
|
100
|
+
printf 'rust_sccache=false\nrust_nextest=false\n' >> "$GITHUB_OUTPUT"
|
|
92
101
|
fi
|
|
93
102
|
if [ "$toolchain" = auto ] && [ -f .mise.toml ]; then
|
|
94
103
|
toolchain=mise
|
|
@@ -746,6 +755,36 @@ runs:
|
|
|
746
755
|
# primary saves but reuse a prior workflow's dependency artifacts.
|
|
747
756
|
restore-keys: |
|
|
748
757
|
${{ runner.os }}-rust-build-v2-
|
|
758
|
+
# sccache is opt-in (`rust_sccache: true` in code-foundry.yml): it caches
|
|
759
|
+
# per-compilation objects keyed by content, so dependency artifacts
|
|
760
|
+
# survive Cargo.toml/Cargo.lock churn that busts the target/ cache above.
|
|
761
|
+
- name: Cache sccache artifacts
|
|
762
|
+
if: inputs.install == 'true' && inputs.install-rust == 'true' && steps.profile.outputs.rust == 'true' && steps.profile.outputs.rust_sccache == 'true'
|
|
763
|
+
uses: ./.github/actions/cache
|
|
764
|
+
with:
|
|
765
|
+
save: ${{ inputs.cache-save }}
|
|
766
|
+
path: ~/.cache/sccache
|
|
767
|
+
key: ${{ runner.os }}-rust-sccache-${{ github.workflow }}-${{ github.job }}-${{ hashFiles('rust-toolchain.toml', 'rust-toolchain', '.cargo/config*', '.mise.toml', 'mise.lock') }}
|
|
768
|
+
restore-keys: |
|
|
769
|
+
${{ runner.os }}-rust-sccache-
|
|
770
|
+
- name: Install sccache
|
|
771
|
+
if: inputs.install == 'true' && inputs.install-rust == 'true' && steps.profile.outputs.rust == 'true' && steps.profile.outputs.rust_sccache == 'true'
|
|
772
|
+
uses: taiki-e/install-action@cb33e69fad06166ca28a42b2575e4dadabf62ee8 # v2
|
|
773
|
+
with:
|
|
774
|
+
tool: sccache
|
|
775
|
+
- name: Wrap rustc with sccache
|
|
776
|
+
if: inputs.install == 'true' && inputs.install-rust == 'true' && steps.profile.outputs.rust == 'true' && steps.profile.outputs.rust_sccache == 'true'
|
|
777
|
+
shell: bash
|
|
778
|
+
run: |
|
|
779
|
+
echo 'RUSTC_WRAPPER=sccache' >> "$GITHUB_ENV"
|
|
780
|
+
echo "SCCACHE_DIR=$HOME/.cache/sccache" >> "$GITHUB_ENV"
|
|
781
|
+
# cargo-nextest is opt-in (`rust_nextest: true`): the runtime uses
|
|
782
|
+
# `cargo nextest run` when the binary is present.
|
|
783
|
+
- name: Install cargo-nextest
|
|
784
|
+
if: inputs.install == 'true' && inputs.install-rust == 'true' && steps.profile.outputs.rust == 'true' && steps.profile.outputs.rust_nextest == 'true'
|
|
785
|
+
uses: taiki-e/install-action@cb33e69fad06166ca28a42b2575e4dadabf62ee8 # v2
|
|
786
|
+
with:
|
|
787
|
+
tool: cargo-nextest
|
|
749
788
|
- name: Setup
|
|
750
789
|
if: ${{ steps.profile.outputs.mise_required == 'true' }}
|
|
751
790
|
uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
|
package/.github/workflows/ci.yml
CHANGED
|
@@ -78,9 +78,15 @@ jobs:
|
|
|
78
78
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
79
79
|
- name: Detect
|
|
80
80
|
id: applicability
|
|
81
|
+
env:
|
|
82
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
83
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
84
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
85
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
86
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
81
87
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run format >> "$GITHUB_OUTPUT"
|
|
82
88
|
- name: Setup
|
|
83
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
89
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
84
90
|
uses: ./.github/actions/setup
|
|
85
91
|
with:
|
|
86
92
|
# Repository format scripts normally call a project-local formatter
|
|
@@ -93,13 +99,13 @@ jobs:
|
|
|
93
99
|
task: format
|
|
94
100
|
- name: Format
|
|
95
101
|
id: execute
|
|
96
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
102
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
97
103
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci format
|
|
98
104
|
- name: Retain task receipt
|
|
99
105
|
if: >-
|
|
100
106
|
always() &&
|
|
101
107
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
102
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
108
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
103
109
|
hashFiles('.code-foundry/results/format.json') != ''
|
|
104
110
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
105
111
|
with:
|
|
@@ -138,9 +144,15 @@ jobs:
|
|
|
138
144
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
139
145
|
- name: Detect
|
|
140
146
|
id: applicability
|
|
147
|
+
env:
|
|
148
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
149
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
150
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
151
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
152
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
141
153
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run lint >> "$GITHUB_OUTPUT"
|
|
142
154
|
- name: Setup
|
|
143
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
155
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
144
156
|
uses: ./.github/actions/setup
|
|
145
157
|
with:
|
|
146
158
|
install: 'true'
|
|
@@ -148,13 +160,13 @@ jobs:
|
|
|
148
160
|
task: lint
|
|
149
161
|
- name: Lint
|
|
150
162
|
id: execute
|
|
151
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
163
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
152
164
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci lint
|
|
153
165
|
- name: Retain task receipt
|
|
154
166
|
if: >-
|
|
155
167
|
always() &&
|
|
156
168
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
157
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
169
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
158
170
|
hashFiles('.code-foundry/results/lint.json') != ''
|
|
159
171
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
160
172
|
with:
|
|
@@ -193,9 +205,15 @@ jobs:
|
|
|
193
205
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
194
206
|
- name: Detect
|
|
195
207
|
id: applicability
|
|
208
|
+
env:
|
|
209
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
210
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
211
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
212
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
213
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
196
214
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run type_check >> "$GITHUB_OUTPUT"
|
|
197
215
|
- name: Setup
|
|
198
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
216
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
199
217
|
uses: ./.github/actions/setup
|
|
200
218
|
with:
|
|
201
219
|
install: 'true'
|
|
@@ -203,13 +221,13 @@ jobs:
|
|
|
203
221
|
task: type_check
|
|
204
222
|
- name: Type-Check
|
|
205
223
|
id: execute
|
|
206
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
224
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
207
225
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci type_check
|
|
208
226
|
- name: Retain task receipt
|
|
209
227
|
if: >-
|
|
210
228
|
always() &&
|
|
211
229
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
212
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
230
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
213
231
|
hashFiles('.code-foundry/results/type_check.json') != ''
|
|
214
232
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
215
233
|
with:
|
|
@@ -253,9 +271,15 @@ jobs:
|
|
|
253
271
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
254
272
|
- name: Detect
|
|
255
273
|
id: applicability
|
|
274
|
+
env:
|
|
275
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
276
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
277
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
278
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
279
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
256
280
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run build >> "$GITHUB_OUTPUT"
|
|
257
281
|
- name: Setup
|
|
258
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
282
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
259
283
|
uses: ./.github/actions/setup
|
|
260
284
|
with:
|
|
261
285
|
install: 'true'
|
|
@@ -263,13 +287,13 @@ jobs:
|
|
|
263
287
|
task: build
|
|
264
288
|
- name: Build
|
|
265
289
|
id: execute
|
|
266
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
290
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
267
291
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci build
|
|
268
292
|
- name: Retain task receipt
|
|
269
293
|
if: >-
|
|
270
294
|
always() &&
|
|
271
295
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
272
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
296
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
273
297
|
hashFiles('.code-foundry/results/build.json') != ''
|
|
274
298
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
275
299
|
with:
|
|
@@ -195,11 +195,17 @@ jobs:
|
|
|
195
195
|
runs-on: ${{ inputs.runner }}
|
|
196
196
|
timeout-minutes: 30
|
|
197
197
|
steps:
|
|
198
|
+
# Analyze the pull request head, not the ephemeral merge ref. The
|
|
199
|
+
# codeql-action records commit_oid from `git rev-parse HEAD` on the
|
|
200
|
+
# checkout — the `sha` upload input is only a fallback when git is
|
|
201
|
+
# unavailable — so checking out the head is what actually keeps the
|
|
202
|
+
# recorded commit stable across mergeability evaluations.
|
|
198
203
|
- name: Checkout
|
|
199
204
|
if: ${{ matrix.entry.changed == true }}
|
|
200
205
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
201
206
|
with:
|
|
202
207
|
persist-credentials: false
|
|
208
|
+
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }}
|
|
203
209
|
- name: Runtime
|
|
204
210
|
if: ${{ matrix.entry.changed == true }}
|
|
205
211
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
@@ -75,9 +75,15 @@ jobs:
|
|
|
75
75
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
76
76
|
- name: Detect
|
|
77
77
|
id: applicability
|
|
78
|
+
env:
|
|
79
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
80
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
81
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
82
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
83
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
78
84
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run eval >> "$GITHUB_OUTPUT"
|
|
79
85
|
- name: Setup
|
|
80
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
86
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
81
87
|
uses: ./.github/actions/setup
|
|
82
88
|
with:
|
|
83
89
|
# Eval harnesses run through the repository's own package scripts and
|
|
@@ -87,13 +93,13 @@ jobs:
|
|
|
87
93
|
task: eval
|
|
88
94
|
- name: Eval
|
|
89
95
|
id: execute
|
|
90
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
96
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
91
97
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci eval
|
|
92
98
|
- name: Retain task receipt
|
|
93
99
|
if: >-
|
|
94
100
|
always() &&
|
|
95
101
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
96
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
102
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
97
103
|
hashFiles('.code-foundry/results/eval.json') != ''
|
|
98
104
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
99
105
|
with:
|
|
@@ -92,9 +92,15 @@ jobs:
|
|
|
92
92
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
93
93
|
- name: Detect
|
|
94
94
|
id: applicability
|
|
95
|
+
env:
|
|
96
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
97
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
98
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
99
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
100
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
95
101
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile unit >> "$GITHUB_OUTPUT"
|
|
96
102
|
- name: Setup
|
|
97
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
103
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
98
104
|
uses: ./.github/actions/setup
|
|
99
105
|
with:
|
|
100
106
|
install: true
|
|
@@ -110,13 +116,13 @@ jobs:
|
|
|
110
116
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
111
117
|
- name: Unit
|
|
112
118
|
id: execute
|
|
113
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
119
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
114
120
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci unit
|
|
115
121
|
- name: Retain task receipt
|
|
116
122
|
if: >-
|
|
117
123
|
always() &&
|
|
118
124
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
119
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
125
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
120
126
|
hashFiles('.code-foundry/results/unit.json') != ''
|
|
121
127
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
122
128
|
with:
|
|
@@ -172,9 +178,15 @@ jobs:
|
|
|
172
178
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
173
179
|
- name: Detect
|
|
174
180
|
id: applicability
|
|
181
|
+
env:
|
|
182
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
183
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
184
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
185
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
186
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
175
187
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile performance >> "$GITHUB_OUTPUT"
|
|
176
188
|
- name: Setup
|
|
177
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
189
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
178
190
|
uses: ./.github/actions/setup
|
|
179
191
|
with:
|
|
180
192
|
install: true
|
|
@@ -191,13 +203,13 @@ jobs:
|
|
|
191
203
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
192
204
|
- name: Performance
|
|
193
205
|
id: execute
|
|
194
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
206
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
195
207
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci performance
|
|
196
208
|
- name: Retain task receipt
|
|
197
209
|
if: >-
|
|
198
210
|
always() &&
|
|
199
211
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
200
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
212
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
201
213
|
hashFiles('.code-foundry/results/performance.json') != ''
|
|
202
214
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
203
215
|
with:
|
|
@@ -252,9 +264,15 @@ jobs:
|
|
|
252
264
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
253
265
|
- name: Detect
|
|
254
266
|
id: applicability
|
|
267
|
+
env:
|
|
268
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
269
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
270
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
271
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
272
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
255
273
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile integration >> "$GITHUB_OUTPUT"
|
|
256
274
|
- name: Setup
|
|
257
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
275
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
258
276
|
uses: ./.github/actions/setup
|
|
259
277
|
with:
|
|
260
278
|
install: true
|
|
@@ -270,13 +288,13 @@ jobs:
|
|
|
270
288
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
271
289
|
- name: Integration
|
|
272
290
|
id: execute
|
|
273
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
291
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
274
292
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci integration
|
|
275
293
|
- name: Retain task receipt
|
|
276
294
|
if: >-
|
|
277
295
|
always() &&
|
|
278
296
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
279
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
297
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
280
298
|
hashFiles('.code-foundry/results/integration.json') != ''
|
|
281
299
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
282
300
|
with:
|
|
@@ -316,9 +334,15 @@ jobs:
|
|
|
316
334
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
317
335
|
- name: Detect
|
|
318
336
|
id: applicability
|
|
337
|
+
env:
|
|
338
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
339
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
340
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
341
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
342
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
319
343
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile e2e >> "$GITHUB_OUTPUT"
|
|
320
344
|
- name: Cache browser binaries
|
|
321
|
-
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.browser == 'true'
|
|
345
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false' && steps.applicability.outputs.browser == 'true'
|
|
322
346
|
uses: ./.github/actions/cache
|
|
323
347
|
with:
|
|
324
348
|
save: ${{ github.event_name == 'push' }}
|
|
@@ -330,7 +354,7 @@ jobs:
|
|
|
330
354
|
restore-keys: |
|
|
331
355
|
${{ runner.os }}-e2e-browsers-
|
|
332
356
|
- name: Setup
|
|
333
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
357
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
334
358
|
uses: ./.github/actions/setup
|
|
335
359
|
with:
|
|
336
360
|
install: true
|
|
@@ -346,13 +370,13 @@ jobs:
|
|
|
346
370
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
347
371
|
- name: E2E
|
|
348
372
|
id: execute
|
|
349
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
373
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
350
374
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci e2e
|
|
351
375
|
- name: Retain task receipt
|
|
352
376
|
if: >-
|
|
353
377
|
always() &&
|
|
354
378
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
355
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
379
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
356
380
|
hashFiles('.code-foundry/results/e2e.json') != ''
|
|
357
381
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
358
382
|
with:
|
|
@@ -392,9 +416,15 @@ jobs:
|
|
|
392
416
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
393
417
|
- name: Detect
|
|
394
418
|
id: applicability
|
|
419
|
+
env:
|
|
420
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
421
|
+
BASE_REF: ${{ github.event.pull_request.base.ref }}
|
|
422
|
+
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
|
423
|
+
HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
|
|
424
|
+
BEFORE_SHA: ${{ github.event.before }}
|
|
395
425
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile smoke >> "$GITHUB_OUTPUT"
|
|
396
426
|
- name: Setup
|
|
397
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
427
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
398
428
|
uses: ./.github/actions/setup
|
|
399
429
|
with:
|
|
400
430
|
install: true
|
|
@@ -410,13 +440,13 @@ jobs:
|
|
|
410
440
|
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
411
441
|
- name: Smoke
|
|
412
442
|
id: execute
|
|
413
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
443
|
+
if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
|
|
414
444
|
run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci smoke
|
|
415
445
|
- name: Retain task receipt
|
|
416
446
|
if: >-
|
|
417
447
|
always() &&
|
|
418
448
|
(steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
|
|
419
|
-
steps.applicability.outputs.applicable == 'false') &&
|
|
449
|
+
steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
|
|
420
450
|
hashFiles('.code-foundry/results/smoke.json') != ''
|
|
421
451
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
422
452
|
with:
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.29.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.28.15...v1.29.0) (2026-09-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* opt-in lane path filters, sccache, and nextest for Rust CI ([#626](https://github.com/0xPlayerOne/code-foundry/issues/626)) ([691ccad](https://github.com/0xPlayerOne/code-foundry/commit/691ccad529d88cde4ddd134b30cfb86988a1cb0a))
|
|
9
|
+
|
|
10
|
+
## [1.28.15](https://github.com/0xPlayerOne/code-foundry/compare/v1.28.14...v1.28.15) (2026-09-17)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **codeql:** analyze the pull request head commit ([#624](https://github.com/0xPlayerOne/code-foundry/issues/624)) ([ce05d1f](https://github.com/0xPlayerOne/code-foundry/commit/ce05d1f4f6c5df3a2d9134dd4657f478a265cb85))
|
|
16
|
+
|
|
3
17
|
## [1.28.14](https://github.com/0xPlayerOne/code-foundry/compare/v1.28.13...v1.28.14) (2026-09-11)
|
|
4
18
|
|
|
5
19
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -105,6 +105,9 @@ See [Merge queue validation](merge-queues.md) before enabling it.
|
|
|
105
105
|
| `coverage_minimum` | `0`–`100` | Minimum percentage; defaults to `80`. |
|
|
106
106
|
| `coverage_metrics` | `lines`, `functions`, `branches`, `statements` | Metrics checked by the coverage gate. |
|
|
107
107
|
| `coverage_report` | comma-separated repository paths | Istanbul JSON summary or LCOV evidence files. |
|
|
108
|
+
| `filter_<task>` | comma-separated repository path globs | Skip a lane when no changed path matches; see [Lane path filters](#lane-path-filters). |
|
|
109
|
+
| `rust_sccache` | `true`, `false` | Install sccache and wrap rustc so compile artifacts survive manifest/lockfile churn. |
|
|
110
|
+
| `rust_nextest` | `true`, `false` | Install cargo-nextest and prefer `cargo nextest run` over `cargo test` in Rust test lanes. |
|
|
108
111
|
|
|
109
112
|
Supported task capabilities are `format`, `lint`, `type_check`, `build`, `unit`,
|
|
110
113
|
`integration`, `e2e`, `smoke`, `eval`, and `performance`. `coverage` is a policy
|
|
@@ -200,6 +203,34 @@ behavior:
|
|
|
200
203
|
Use these controls only after measuring a repeatable benefit. See [Caching and
|
|
201
204
|
remote caching](CACHING.md).
|
|
202
205
|
|
|
206
|
+
## Lane path filters
|
|
207
|
+
|
|
208
|
+
Validation lanes run their full suite by default. Repositories with clearly
|
|
209
|
+
separated areas — for example a Rust workspace next to a web app — can opt any
|
|
210
|
+
task lane into path filtering so a change that cannot affect the lane skips
|
|
211
|
+
its setup and execution steps:
|
|
212
|
+
|
|
213
|
+
```yaml
|
|
214
|
+
filter_integration: 'src/**/*.py,tests/**,pyproject.toml,uv.lock'
|
|
215
|
+
filter_eval: 'eval/**,crates/**,src/**'
|
|
216
|
+
filter_e2e: 'apps/**,src/**'
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
`filter_<task>` accepts the same task names as `required_capabilities`. Globs
|
|
220
|
+
are repo-relative: `**/` matches any directory depth, `*` stays inside one
|
|
221
|
+
path segment, `?` matches one character, and a trailing `/` is shorthand for
|
|
222
|
+
`dir/**`.
|
|
223
|
+
|
|
224
|
+
The gate is fail-open by design: a task without a configured filter, a diff
|
|
225
|
+
that cannot be resolved (shallow checkout edge, missing base ref), or an empty
|
|
226
|
+
change set all keep the lane running. Paths are evaluated against
|
|
227
|
+
`base...head` for pull requests and `before..after` for pushes; other events
|
|
228
|
+
always run. Because filters only decide whether a lane _executes_, required
|
|
229
|
+
checks stay green and the aggregate gate sees a normal success.
|
|
230
|
+
|
|
231
|
+
Security lanes and CodeQL are never filterable: their coverage is structural,
|
|
232
|
+
not change-scoped.
|
|
233
|
+
|
|
203
234
|
## Rust CodeQL tuning
|
|
204
235
|
|
|
205
236
|
Rust CodeQL defaults to one full scan with one worker. Larger multi-crate
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.29.0",
|
|
4
4
|
"description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
|
|
5
5
|
"homepage": "https://github.com/0xPlayerOne/code-foundry#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
|
|
3
|
+
import { execFileSync } from 'node:child_process'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Tasks that support `filter_<task>` path filters in code-foundry.yml. A
|
|
7
|
+
* filter lists repo-relative globs; when every changed path misses the filter
|
|
8
|
+
* the lane reports `affected=false` and its workflow steps skip. CI lanes and
|
|
9
|
+
* security tasks are not filterable because their coverage is structural.
|
|
10
|
+
*/
|
|
11
|
+
export const FILTERABLE_TASKS = [
|
|
12
|
+
'format',
|
|
13
|
+
'lint',
|
|
14
|
+
'type_check',
|
|
15
|
+
'build',
|
|
16
|
+
'unit',
|
|
17
|
+
'integration',
|
|
18
|
+
'e2e',
|
|
19
|
+
'smoke',
|
|
20
|
+
'eval',
|
|
21
|
+
'performance',
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Parse `filter_<task>` config keys into per-task glob lists.
|
|
26
|
+
* @param {Record<string, string>} config
|
|
27
|
+
* @returns {Map<string, string[]>}
|
|
28
|
+
*/
|
|
29
|
+
export function readTaskFilters(config) {
|
|
30
|
+
const filters = new Map()
|
|
31
|
+
for (const task of FILTERABLE_TASKS) {
|
|
32
|
+
const value = config[`filter_${task}`]
|
|
33
|
+
if (value === undefined || value === '') continue
|
|
34
|
+
const globs = value
|
|
35
|
+
.split(',')
|
|
36
|
+
.map((glob) => glob.trim())
|
|
37
|
+
.filter(Boolean)
|
|
38
|
+
if (globs.length > 0) filters.set(task, globs)
|
|
39
|
+
}
|
|
40
|
+
return filters
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Compile a repo-relative glob to a RegExp. Supported syntax: double-star
|
|
45
|
+
* segments match any directory depth, `*` stays inside a path segment, `?`
|
|
46
|
+
* matches one character, and a trailing `/` is a directory shorthand.
|
|
47
|
+
* @param {string} glob
|
|
48
|
+
* @returns {RegExp}
|
|
49
|
+
*/
|
|
50
|
+
export function globToRegExp(glob) {
|
|
51
|
+
let pattern = glob.replace(/^\.\//, '')
|
|
52
|
+
if (pattern.endsWith('/')) pattern += '**'
|
|
53
|
+
let regex = '^'
|
|
54
|
+
let index = 0
|
|
55
|
+
while (index < pattern.length) {
|
|
56
|
+
if (pattern.startsWith('**/', index)) {
|
|
57
|
+
regex += '(?:[^/]+/)*'
|
|
58
|
+
index += 3
|
|
59
|
+
} else if (pattern.startsWith('/**', index) && index + 3 === pattern.length) {
|
|
60
|
+
regex += '/.*'
|
|
61
|
+
index += 3
|
|
62
|
+
} else if (pattern.startsWith('**', index)) {
|
|
63
|
+
regex += '.*'
|
|
64
|
+
index += 2
|
|
65
|
+
} else if (pattern[index] === '*') {
|
|
66
|
+
regex += '[^/]*'
|
|
67
|
+
index += 1
|
|
68
|
+
} else if (pattern[index] === '?') {
|
|
69
|
+
regex += '[^/]'
|
|
70
|
+
index += 1
|
|
71
|
+
} else {
|
|
72
|
+
regex += pattern[index].replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
73
|
+
index += 1
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return new RegExp(`${regex}$`)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Resolve the pull request or push change set. The generated Detect steps
|
|
81
|
+
* pass EVENT_NAME plus BASE_REF/BASE_SHA/HEAD_SHA (pull_request) or
|
|
82
|
+
* BEFORE_SHA/HEAD_SHA (push). Returns null when the change set cannot be
|
|
83
|
+
* resolved; callers treat null as fail-open so a checkout edge never skips a
|
|
84
|
+
* required lane.
|
|
85
|
+
* @param {string} root
|
|
86
|
+
* @param {Record<string, string | undefined>} env
|
|
87
|
+
* @returns {string[] | null}
|
|
88
|
+
*/
|
|
89
|
+
export function resolveChangedPaths(root, env = process.env) {
|
|
90
|
+
const event = env.EVENT_NAME
|
|
91
|
+
let range = null
|
|
92
|
+
try {
|
|
93
|
+
if (event === 'pull_request' || event === 'pull_request_target') {
|
|
94
|
+
const baseRef = env.BASE_REF
|
|
95
|
+
const baseSha = env.BASE_SHA
|
|
96
|
+
const head = env.HEAD_SHA || 'HEAD'
|
|
97
|
+
if (!baseSha) return null
|
|
98
|
+
if (baseRef) {
|
|
99
|
+
execFileSync('git', ['fetch', '--no-tags', '--depth=100', 'origin', baseRef], {
|
|
100
|
+
cwd: root,
|
|
101
|
+
stdio: 'pipe',
|
|
102
|
+
})
|
|
103
|
+
range = `FETCH_HEAD...${head}`
|
|
104
|
+
} else {
|
|
105
|
+
range = `${baseSha}...${head}`
|
|
106
|
+
}
|
|
107
|
+
} else if (event === 'push') {
|
|
108
|
+
const before = env.BEFORE_SHA
|
|
109
|
+
const head = env.HEAD_SHA || 'HEAD'
|
|
110
|
+
if (!before || /^0+$/.test(before)) return null
|
|
111
|
+
range = `${before}..${head}`
|
|
112
|
+
} else {
|
|
113
|
+
return null
|
|
114
|
+
}
|
|
115
|
+
const output = execFileSync('git', ['diff', '--name-only', range], {
|
|
116
|
+
cwd: root,
|
|
117
|
+
encoding: 'utf8',
|
|
118
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
119
|
+
})
|
|
120
|
+
return output
|
|
121
|
+
.split('\n')
|
|
122
|
+
.map((line) => line.trim())
|
|
123
|
+
.filter((line) => line.length > 0)
|
|
124
|
+
} catch {
|
|
125
|
+
return null
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Report whether a task's configured path filter matches the change set.
|
|
131
|
+
* Fail-open by contract: no filter, no resolvable diff, or an empty diff all
|
|
132
|
+
* keep the lane running.
|
|
133
|
+
* @param {string} task
|
|
134
|
+
* @param {Map<string, string[]>} filters
|
|
135
|
+
* @param {string[] | null} paths
|
|
136
|
+
* @returns {boolean}
|
|
137
|
+
*/
|
|
138
|
+
export function taskAffected(task, filters, paths) {
|
|
139
|
+
const globs = filters.get(task)
|
|
140
|
+
if (!globs || globs.length === 0 || paths === null || paths.length === 0) return true
|
|
141
|
+
const matchers = globs.map(globToRegExp)
|
|
142
|
+
return paths.some((path) => matchers.some((matcher) => matcher.test(path)))
|
|
143
|
+
}
|
package/src/runtime-core.mjs
CHANGED
|
@@ -15,6 +15,7 @@ import { detectPackageManager, resolveProfile } from './lib/profile.mjs'
|
|
|
15
15
|
import { configured, readConfig } from './lib/config.mjs'
|
|
16
16
|
import { classifyTestFiles } from './lib/test-discovery.mjs'
|
|
17
17
|
import { docsOnlyPullRequest } from './lib/docs-only.mjs'
|
|
18
|
+
import { readTaskFilters, resolveChangedPaths, taskAffected } from './lib/task-filters.mjs'
|
|
18
19
|
import { classifyValidationMode, evaluateValidationGate } from './lib/validation-policy.mjs'
|
|
19
20
|
import { readReleaseConfig, validateGeneratedReleaseDiff } from './lib/release-policy.mjs'
|
|
20
21
|
import { runNodePackagePerformance } from './lib/node-package-performance.mjs'
|
|
@@ -688,6 +689,15 @@ function ci(task) {
|
|
|
688
689
|
if (task === 'should_run' || task === 'task_profile') {
|
|
689
690
|
const selected = process.argv[4]
|
|
690
691
|
writeOutput('applicable', relevant(selected) ? 'true' : 'false')
|
|
692
|
+
// Path-filtered lanes are opt-in via `filter_<task>` config keys. The
|
|
693
|
+
// gate fails open: no filter, an unresolvable diff, or an empty change
|
|
694
|
+
// set all keep the lane running.
|
|
695
|
+
writeOutput(
|
|
696
|
+
'affected',
|
|
697
|
+
taskAffected(selected ?? '', readTaskFilters(config), resolveChangedPaths(root))
|
|
698
|
+
? 'true'
|
|
699
|
+
: 'false'
|
|
700
|
+
)
|
|
691
701
|
writeOutput(
|
|
692
702
|
'javascript',
|
|
693
703
|
hasLanguage('typescript') || hasLanguage('javascript') ? 'true' : 'false'
|
|
@@ -784,9 +794,14 @@ function ci(task) {
|
|
|
784
794
|
}
|
|
785
795
|
|
|
786
796
|
if (hasLanguage('rust') && hasRootRustProject()) {
|
|
797
|
+
// `rust_nextest` opts into process-per-test parallelism. cargo-nextest
|
|
798
|
+
// accepts the same --lib/--bin/--test target flags as `cargo test`.
|
|
799
|
+
const nextest =
|
|
800
|
+
configured(config.rust_nextest, 'false') === 'true' && commandExists('cargo-nextest')
|
|
801
|
+
const testArgs = nextest ? ['nextest', 'run'] : ['test']
|
|
787
802
|
if (task === 'unit') {
|
|
788
803
|
// Batch exact prior targets through one Cargo graph.
|
|
789
|
-
const args = [
|
|
804
|
+
const args = [...testArgs]
|
|
790
805
|
if (existsSync(resolve(root, 'src/lib.rs'))) args.push('--lib')
|
|
791
806
|
if (existsSync(resolve(root, 'src/main.rs'))) args.push('--bin', packageName())
|
|
792
807
|
run('cargo', args)
|
|
@@ -796,7 +811,7 @@ function ci(task) {
|
|
|
796
811
|
const match = file.match(/^tests\/(.+)\.rs$/)
|
|
797
812
|
return match && !match[1].includes('/') ? ['--test', match[1]] : []
|
|
798
813
|
})
|
|
799
|
-
if (targets.length > 0) run('cargo', [
|
|
814
|
+
if (targets.length > 0) run('cargo', [...testArgs, ...targets])
|
|
800
815
|
}
|
|
801
816
|
}
|
|
802
817
|
}
|
package/src/runtime.mjs
CHANGED
|
@@ -42,6 +42,7 @@ export function taskProfile(root, task, entry = core) {
|
|
|
42
42
|
throw new Error(`Task discovery returned no applicability: ${task}`)
|
|
43
43
|
return {
|
|
44
44
|
...describeTask(root, task, profile),
|
|
45
|
+
affected: profile.affected ?? 'true',
|
|
45
46
|
javascript: profile.javascript ?? 'false',
|
|
46
47
|
python: profile.python ?? 'false',
|
|
47
48
|
rust: profile.rust ?? 'false',
|
|
@@ -110,6 +111,24 @@ export function runRuntime(args, root = process.cwd(), entry = core) {
|
|
|
110
111
|
(name) => name !== 'coverage' && name !== selected
|
|
111
112
|
))
|
|
112
113
|
taskProfile(root, requiredName, entry)
|
|
114
|
+
// A path-filtered lane that misses the diff still leaves a receipt so the
|
|
115
|
+
// run records why its steps skipped.
|
|
116
|
+
if (profile.applicable && profile.affected === 'false') {
|
|
117
|
+
const now = new Date().toISOString()
|
|
118
|
+
saveResult(root, selected, {
|
|
119
|
+
schemaVersion: 1,
|
|
120
|
+
kind: 'code-foundry-task-result',
|
|
121
|
+
task: selected,
|
|
122
|
+
sourceSha: sourceSha(root),
|
|
123
|
+
startedAt: now,
|
|
124
|
+
completedAt: now,
|
|
125
|
+
status: 'skipped',
|
|
126
|
+
reason: 'no changed path matched the task filter',
|
|
127
|
+
required: false,
|
|
128
|
+
commands: [],
|
|
129
|
+
artifacts: [],
|
|
130
|
+
})
|
|
131
|
+
}
|
|
113
132
|
if (!profile.applicable) {
|
|
114
133
|
const now = new Date().toISOString()
|
|
115
134
|
saveResult(root, selected, {
|
|
@@ -128,6 +147,7 @@ export function runRuntime(args, root = process.cwd(), entry = core) {
|
|
|
128
147
|
}
|
|
129
148
|
for (const [key, value] of Object.entries({
|
|
130
149
|
applicable: String(profile.applicable),
|
|
150
|
+
affected: profile.affected ?? 'true',
|
|
131
151
|
javascript: profile.javascript ?? 'false',
|
|
132
152
|
python: profile.python ?? 'false',
|
|
133
153
|
rust: profile.rust ?? 'false',
|