code-foundry 1.44.11 → 1.45.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.
@@ -0,0 +1,1159 @@
1
+ name: Code Foundry Validation (Billing)
2
+
3
+ # Billing-lane orchestrator for repositories whose Actions minutes are billed:
4
+ # identical coverage to the split orchestrators, but lanes that measure under a
5
+ # minute in practice share one runner so GitHub's whole-minute rounding stops
6
+ # dominating the invoice. Wall-clock neutrality rule enforced by review: a lane
7
+ # may only join the merged job when its work plus the shared checkout/setup
8
+ # overhead stays under the longest separate lane (type-check, unit, or build),
9
+ # so the merged job never becomes the critical path. Repositories that adopt
10
+ # this orchestrator must keep every runner input on standard hosted runners.
11
+ #
12
+ # Differences from the split orchestrators, by design:
13
+ # - Format, build, performance, smoke, and eval run as sequential steps of one
14
+ # job ("Fast lanes"). Each lane keeps its own detect, setup, execution, and
15
+ # task-receipt steps, so receipts and skip semantics are unchanged.
16
+ # - Profile and dependency audit run in one job; the audit matrix is replaced
17
+ # by language blocks driven directly by the profile step's outputs.
18
+ # - One file serves both CodeQL-enabled and CodeQL-unavailable consumers via
19
+ # the `codeql` input, instead of two orchestrator variants.
20
+
21
+ on:
22
+ workflow_call:
23
+ inputs:
24
+ mode:
25
+ description: Validation tier (fast, audit, or release).
26
+ required: true
27
+ type: string
28
+ codeql:
29
+ description: Run the CodeQL lane (the consumer's canonical codeql config).
30
+ required: false
31
+ type: boolean
32
+ default: false
33
+ runtime-repository:
34
+ description: Repository containing the Code Foundry runtime.
35
+ required: false
36
+ type: string
37
+ default: 0xPlayerOne/code-foundry
38
+ runtime-ref:
39
+ description: Code Foundry runtime tag or ref.
40
+ required: false
41
+ type: string
42
+ default: v1.0.5
43
+ ci-runner:
44
+ description: Runner used by CI jobs and the merged fast-lanes job.
45
+ required: false
46
+ type: string
47
+ default: ubuntu-latest
48
+ test-runner:
49
+ description: Runner used by non-unit test jobs.
50
+ required: false
51
+ type: string
52
+ default: ubuntu-latest
53
+ unit-runner:
54
+ description: Runner used by unit tests.
55
+ required: false
56
+ type: string
57
+ default: ubuntu-slim
58
+ security-runner:
59
+ description: Runner used by the merged audit job.
60
+ required: false
61
+ type: string
62
+ default: ubuntu-slim
63
+ codeql-runner:
64
+ description: Runner used by CodeQL jobs.
65
+ required: false
66
+ type: string
67
+ default: ubuntu-latest
68
+ rust-shards:
69
+ description: JSON array of Rust scope sharding values. Use ["all"] for single-pass behavior.
70
+ required: false
71
+ type: string
72
+ default: '["all"]'
73
+ rust-threads:
74
+ description: Threads used for Rust extraction and analysis. Values above 1 opt into local parallelism.
75
+ required: false
76
+ type: string
77
+ default: '1'
78
+ rust-max-parallel:
79
+ description: Maximum Rust shard jobs allowed to run concurrently.
80
+ required: false
81
+ type: number
82
+ default: 1
83
+ artifact-prefix:
84
+ description: Prefix for task receipts; use a unique value when calling this workflow more than once.
85
+ required: false
86
+ type: string
87
+ default: task-result
88
+ e2e-shard-list:
89
+ description: Comma-separated E2E shard indices passed to the test lane's matrix, e.g. "1,2".
90
+ required: false
91
+ type: string
92
+ default: '1'
93
+ e2e-total-shards:
94
+ description: Total E2E shard count passed to the repository script as E2E_TOTAL_SHARDS.
95
+ required: false
96
+ type: string
97
+ default: '1'
98
+ secrets:
99
+ TURBO_TOKEN:
100
+ required: false
101
+ NEXTAUTH_SECRET:
102
+ required: false
103
+
104
+ # The orchestrator keeps the union of permissions needed by the chain it calls
105
+ # (CodeQL uploads require security-events: write). Nested reusable workflows
106
+ # can only maintain or reduce permissions, never elevate them.
107
+ permissions:
108
+ actions: read
109
+ contents: read
110
+ packages: read
111
+ security-events: write
112
+
113
+ env:
114
+ TURBO_API: ${{ vars.TURBO_API }}
115
+ TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
116
+ TURBO_TEAM: ${{ vars.TURBO_TEAM }}
117
+ REPO_FOUNDRY_PROFILE: ${{ vars.REPO_FOUNDRY_PROFILE }}
118
+ REPO_FOUNDRY_LANGUAGES: ${{ vars.REPO_FOUNDRY_LANGUAGES }}
119
+ REPO_FOUNDRY_FEATURES: ${{ vars.REPO_FOUNDRY_FEATURES }}
120
+ REPO_FOUNDRY_PACKAGE_MANAGER: ${{ vars.REPO_FOUNDRY_PACKAGE_MANAGER }}
121
+ REPO_FOUNDRY_RUNNER: ${{ vars.REPO_FOUNDRY_RUNNER }}
122
+ REPO_FOUNDRY_CACHE_PACKAGES: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
123
+ REPO_FOUNDRY_CACHE_BUILD: ${{ vars.REPO_FOUNDRY_CACHE_BUILD || 'auto' }}
124
+ REPO_FOUNDRY_BASE_SHA: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event.before || '' }}
125
+
126
+ concurrency:
127
+ group: code-foundry-validation-billing-${{ github.event_name }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.event.pull_request.head.ref || github.ref_name }}
128
+ # Superseded pull-request runs are cancelled so the newest head owns the
129
+ # group; push and scheduled runs queue instead, because cancelling a main
130
+ # push can drop default-branch analysis or release-adjacent work.
131
+ cancel-in-progress: ${{ github.event_name == 'pull_request' }}
132
+
133
+ jobs:
134
+ # Merged low-cost lanes. Each block below is a step-for-step mirror of the
135
+ # corresponding lane job in ci.yml, test.yml, or eval.yml; only the step ids
136
+ # are prefixed and subsequent lanes add !cancelled() so one lane's failure
137
+ # never hides another lane's result.
138
+ fast-lanes:
139
+ name: Fast lanes
140
+ if: vars.CI_BILLING_PAUSED != 'true'
141
+ runs-on: ${{ inputs.ci-runner }}
142
+ timeout-minutes: 45
143
+ steps:
144
+ - name: Checkout
145
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
146
+ with:
147
+ persist-credentials: false
148
+ fetch-depth: 2
149
+ - name: Runtime
150
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
151
+ with:
152
+ persist-credentials: false
153
+ repository: ${{ inputs.runtime-repository }}
154
+ ref: ${{ inputs.runtime-ref }}
155
+ path: .github/.code-foundry
156
+ sparse-checkout: |
157
+ .github/actions
158
+ src/lib
159
+ src/runtime-core.mjs
160
+ src/runtime.mjs
161
+ - name: Install runtime
162
+ run: |
163
+ mkdir -p .github/actions
164
+ mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
165
+ cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
166
+ # --- Format lane (mirror of ci.yml format) ---
167
+ - name: Detect format
168
+ id: format_applicability
169
+ env:
170
+ EVENT_NAME: ${{ github.event_name }}
171
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
172
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
173
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
174
+ BEFORE_SHA: ${{ github.event.before }}
175
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run format >> "$GITHUB_OUTPUT"
176
+ - name: Setup format
177
+ if: steps.format_applicability.outputs.applicable == 'true' && steps.format_applicability.outputs.affected != 'false'
178
+ uses: ./.github/actions/setup
179
+ with:
180
+ # Repository format scripts normally call a project-local formatter
181
+ # (for example, Oxfmt). Install dependencies before running them;
182
+ # otherwise a clean runner cannot resolve the declared tool.
183
+ install: 'true'
184
+ cache-format: 'true'
185
+ cache-lint: 'false'
186
+ cache-build: 'false'
187
+ task: format
188
+ - name: Format
189
+ id: format_execute
190
+ if: steps.format_applicability.outputs.applicable == 'true' && steps.format_applicability.outputs.affected != 'false'
191
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci format
192
+ - name: Retain format task receipt
193
+ if: >-
194
+ always() &&
195
+ (steps.format_execute.outcome == 'success' || steps.format_execute.outcome == 'failure' ||
196
+ steps.format_applicability.outputs.applicable == 'false' || steps.format_applicability.outputs.affected == 'false') &&
197
+ hashFiles('.code-foundry/results/format.json') != ''
198
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
199
+ with:
200
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-format
201
+ path: .code-foundry/results/format.json
202
+ include-hidden-files: true
203
+ if-no-files-found: error
204
+ retention-days: 14
205
+ # --- Build lane (mirror of ci.yml build) ---
206
+ - name: Detect build
207
+ id: build_applicability
208
+ if: ${{ !cancelled() }}
209
+ env:
210
+ EVENT_NAME: ${{ github.event_name }}
211
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
212
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
213
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
214
+ BEFORE_SHA: ${{ github.event.before }}
215
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run build >> "$GITHUB_OUTPUT"
216
+ - name: Setup build
217
+ if: ${{ !cancelled() && steps.build_applicability.outputs.applicable == 'true' && steps.build_applicability.outputs.affected != 'false' }}
218
+ uses: ./.github/actions/setup
219
+ with:
220
+ install: 'true'
221
+ cache-build: 'true'
222
+ task: build
223
+ env:
224
+ # Framework builds may validate server-side configuration at build
225
+ # time. Consumers can provide the real value; the fallback is
226
+ # intentionally CI-only and must never be used at runtime.
227
+ NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET || 'code-foundry-ci-placeholder-0123456789' }}
228
+ - name: Build
229
+ id: build_execute
230
+ if: ${{ !cancelled() && steps.build_applicability.outputs.applicable == 'true' && steps.build_applicability.outputs.affected != 'false' }}
231
+ env:
232
+ NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET || 'code-foundry-ci-placeholder-0123456789' }}
233
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci build
234
+ - name: Retain build task receipt
235
+ if: >-
236
+ always() &&
237
+ (steps.build_execute.outcome == 'success' || steps.build_execute.outcome == 'failure' ||
238
+ steps.build_applicability.outputs.applicable == 'false' || steps.build_applicability.outputs.affected == 'false') &&
239
+ hashFiles('.code-foundry/results/build.json') != ''
240
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
241
+ with:
242
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-build
243
+ path: .code-foundry/results/build.json
244
+ include-hidden-files: true
245
+ if-no-files-found: error
246
+ retention-days: 14
247
+ # --- Performance lane (mirror of test.yml performance; audit tier only) ---
248
+ - name: Detect performance
249
+ id: performance_applicability
250
+ if: ${{ !cancelled() && inputs.mode == 'audit' }}
251
+ env:
252
+ EVENT_NAME: ${{ github.event_name }}
253
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
254
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
255
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
256
+ BEFORE_SHA: ${{ github.event.before }}
257
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile performance >> "$GITHUB_OUTPUT"
258
+ - name: Setup performance
259
+ if: ${{ !cancelled() && inputs.mode == 'audit' && steps.performance_applicability.outputs.applicable == 'true' && steps.performance_applicability.outputs.affected != 'false' }}
260
+ uses: ./.github/actions/setup
261
+ with:
262
+ install: true
263
+ install-javascript: ${{ steps.performance_applicability.outputs.javascript == 'true' }}
264
+ install-python: ${{ steps.performance_applicability.outputs.python == 'true' }}
265
+ install-rust: ${{ steps.performance_applicability.outputs.rust == 'true' }}
266
+ cache-build: false
267
+ cache-environment: false
268
+ cache-save: false
269
+ cache-packages: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
270
+ task: performance
271
+ task-javascript: ${{ steps.performance_applicability.outputs.javascript }}
272
+ task-python: ${{ steps.performance_applicability.outputs.python }}
273
+ task-rust: ${{ steps.performance_applicability.outputs.rust }}
274
+ - name: Performance
275
+ id: performance_execute
276
+ if: ${{ !cancelled() && inputs.mode == 'audit' && steps.performance_applicability.outputs.applicable == 'true' && steps.performance_applicability.outputs.affected != 'false' }}
277
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci performance
278
+ - name: Retain performance task receipt
279
+ if: >-
280
+ always() &&
281
+ inputs.mode == 'audit' &&
282
+ (steps.performance_execute.outcome == 'success' || steps.performance_execute.outcome == 'failure' ||
283
+ steps.performance_applicability.outputs.applicable == 'false' || steps.performance_applicability.outputs.affected == 'false') &&
284
+ hashFiles('.code-foundry/results/performance.json') != ''
285
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
286
+ with:
287
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-performance
288
+ path: .code-foundry/results/performance.json
289
+ include-hidden-files: true
290
+ if-no-files-found: error
291
+ retention-days: 14
292
+ - name: Upload performance results
293
+ if: >-
294
+ always() &&
295
+ inputs.mode == 'audit' &&
296
+ steps.performance_applicability.outputs.applicable == 'true' &&
297
+ hashFiles('artifacts/performance/**', 'performance-results.json', 'performance-results/**') != ''
298
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
299
+ with:
300
+ name: performance-${{ github.run_id }}
301
+ path: |
302
+ artifacts/performance/**
303
+ performance-results.json
304
+ performance-results/**
305
+ compression-level: 1
306
+ if-no-files-found: ignore
307
+ retention-days: 14
308
+ # --- Smoke lane (mirror of test.yml smoke; audit tier only) ---
309
+ - name: Detect smoke
310
+ id: smoke_applicability
311
+ if: ${{ !cancelled() && inputs.mode == 'audit' }}
312
+ env:
313
+ EVENT_NAME: ${{ github.event_name }}
314
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
315
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
316
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
317
+ BEFORE_SHA: ${{ github.event.before }}
318
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile smoke >> "$GITHUB_OUTPUT"
319
+ - name: Setup smoke
320
+ if: ${{ !cancelled() && inputs.mode == 'audit' && steps.smoke_applicability.outputs.applicable == 'true' && steps.smoke_applicability.outputs.affected != 'false' }}
321
+ uses: ./.github/actions/setup
322
+ with:
323
+ install: true
324
+ install-javascript: ${{ steps.smoke_applicability.outputs.javascript == 'true' }}
325
+ install-python: ${{ steps.smoke_applicability.outputs.python == 'true' }}
326
+ install-rust: ${{ steps.smoke_applicability.outputs.rust == 'true' }}
327
+ cache-build: false
328
+ cache-environment: false
329
+ cache-save: ${{ github.event_name == 'push' }}
330
+ cache-packages: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
331
+ task: smoke
332
+ task-javascript: ${{ steps.smoke_applicability.outputs.javascript }}
333
+ task-python: ${{ steps.smoke_applicability.outputs.python }}
334
+ task-rust: ${{ steps.smoke_applicability.outputs.rust }}
335
+ - name: Smoke
336
+ id: smoke_execute
337
+ if: ${{ !cancelled() && inputs.mode == 'audit' && steps.smoke_applicability.outputs.applicable == 'true' && steps.smoke_applicability.outputs.affected != 'false' }}
338
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci smoke
339
+ - name: Retain smoke task receipt
340
+ if: >-
341
+ always() &&
342
+ inputs.mode == 'audit' &&
343
+ (steps.smoke_execute.outcome == 'success' || steps.smoke_execute.outcome == 'failure' ||
344
+ steps.smoke_applicability.outputs.applicable == 'false' || steps.smoke_applicability.outputs.affected == 'false') &&
345
+ hashFiles('.code-foundry/results/smoke.json') != ''
346
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
347
+ with:
348
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-smoke
349
+ path: .code-foundry/results/smoke.json
350
+ include-hidden-files: true
351
+ if-no-files-found: error
352
+ retention-days: 14
353
+ # --- Eval lane (mirror of eval.yml; audit tier only) ---
354
+ - name: Detect eval
355
+ id: eval_applicability
356
+ if: ${{ !cancelled() && inputs.mode == 'audit' }}
357
+ env:
358
+ EVENT_NAME: ${{ github.event_name }}
359
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
360
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
361
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
362
+ BEFORE_SHA: ${{ github.event.before }}
363
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run eval >> "$GITHUB_OUTPUT"
364
+ - name: Setup eval
365
+ if: ${{ !cancelled() && inputs.mode == 'audit' && steps.eval_applicability.outputs.applicable == 'true' && steps.eval_applicability.outputs.affected != 'false' }}
366
+ uses: ./.github/actions/setup
367
+ with:
368
+ # Eval harnesses run through the repository's own package scripts and
369
+ # need their dependencies installed before the task executes.
370
+ install: 'true'
371
+ cache-build: 'true'
372
+ task: eval
373
+ - name: Eval
374
+ id: eval_execute
375
+ if: ${{ !cancelled() && inputs.mode == 'audit' && steps.eval_applicability.outputs.applicable == 'true' && steps.eval_applicability.outputs.affected != 'false' }}
376
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci eval
377
+ - name: Retain eval task receipt
378
+ if: >-
379
+ always() &&
380
+ inputs.mode == 'audit' &&
381
+ (steps.eval_execute.outcome == 'success' || steps.eval_execute.outcome == 'failure' ||
382
+ steps.eval_applicability.outputs.applicable == 'false' || steps.eval_applicability.outputs.affected == 'false') &&
383
+ hashFiles('.code-foundry/results/eval.json') != ''
384
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
385
+ with:
386
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-eval
387
+ path: .code-foundry/results/eval.json
388
+ include-hidden-files: true
389
+ if-no-files-found: error
390
+ retention-days: 14
391
+ - name: Retain eval report
392
+ if: >-
393
+ always() &&
394
+ inputs.mode == 'audit' &&
395
+ steps.eval_execute.outcome == 'failure' &&
396
+ hashFiles('eval-results/result.json') != ''
397
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
398
+ with:
399
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-eval-report
400
+ path: |
401
+ eval-results/result.json
402
+ eval-results/summary.json
403
+ if-no-files-found: error
404
+ retention-days: 14
405
+
406
+ lint:
407
+ name: Lint
408
+ if: vars.CI_BILLING_PAUSED != 'true'
409
+ runs-on: ${{ inputs.ci-runner }}
410
+ timeout-minutes: 30
411
+ steps:
412
+ - name: Checkout
413
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
414
+ with:
415
+ persist-credentials: false
416
+ - name: Runtime
417
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
418
+ with:
419
+ persist-credentials: false
420
+ repository: ${{ inputs.runtime-repository }}
421
+ ref: ${{ inputs.runtime-ref }}
422
+ path: .github/.code-foundry
423
+ sparse-checkout: |
424
+ .github/actions
425
+ src/lib
426
+ src/runtime-core.mjs
427
+ src/runtime.mjs
428
+ - name: Install runtime
429
+ run: |
430
+ mkdir -p .github/actions
431
+ mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
432
+ cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
433
+ - name: Detect
434
+ id: applicability
435
+ env:
436
+ EVENT_NAME: ${{ github.event_name }}
437
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
438
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
439
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
440
+ BEFORE_SHA: ${{ github.event.before }}
441
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run lint >> "$GITHUB_OUTPUT"
442
+ - name: Setup
443
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
444
+ uses: ./.github/actions/setup
445
+ with:
446
+ install: 'true'
447
+ cache-lint: 'true'
448
+ task: lint
449
+ - name: Lint
450
+ id: execute
451
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
452
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci lint
453
+ - name: Retain task receipt
454
+ if: >-
455
+ always() &&
456
+ (steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
457
+ steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
458
+ hashFiles('.code-foundry/results/lint.json') != ''
459
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
460
+ with:
461
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-lint
462
+ path: .code-foundry/results/lint.json
463
+ include-hidden-files: true
464
+ if-no-files-found: error
465
+ retention-days: 14
466
+
467
+ type-check:
468
+ name: Type-Check
469
+ if: vars.CI_BILLING_PAUSED != 'true'
470
+ runs-on: ${{ inputs.ci-runner }}
471
+ timeout-minutes: 30
472
+ steps:
473
+ - name: Checkout
474
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
475
+ with:
476
+ persist-credentials: false
477
+ - name: Runtime
478
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
479
+ with:
480
+ persist-credentials: false
481
+ repository: ${{ inputs.runtime-repository }}
482
+ ref: ${{ inputs.runtime-ref }}
483
+ path: .github/.code-foundry
484
+ sparse-checkout: |
485
+ .github/actions
486
+ src/lib
487
+ src/runtime-core.mjs
488
+ src/runtime.mjs
489
+ - name: Install runtime
490
+ run: |
491
+ mkdir -p .github/actions
492
+ mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
493
+ cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
494
+ - name: Detect
495
+ id: applicability
496
+ env:
497
+ EVENT_NAME: ${{ github.event_name }}
498
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
499
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
500
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
501
+ BEFORE_SHA: ${{ github.event.before }}
502
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci should_run type_check >> "$GITHUB_OUTPUT"
503
+ - name: Setup
504
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
505
+ uses: ./.github/actions/setup
506
+ with:
507
+ install: 'true'
508
+ cache-build: 'true'
509
+ task: type_check
510
+ - name: Type-Check
511
+ id: execute
512
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
513
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci type_check
514
+ - name: Retain task receipt
515
+ if: >-
516
+ always() &&
517
+ (steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
518
+ steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
519
+ hashFiles('.code-foundry/results/type_check.json') != ''
520
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
521
+ with:
522
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-type_check
523
+ path: .code-foundry/results/type_check.json
524
+ include-hidden-files: true
525
+ if-no-files-found: error
526
+ retention-days: 14
527
+
528
+ unit:
529
+ name: Unit
530
+ if: vars.CI_BILLING_PAUSED != 'true'
531
+ runs-on: ${{ inputs.unit-runner }}
532
+ timeout-minutes: 30
533
+ steps:
534
+ - name: Checkout
535
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
536
+ with:
537
+ persist-credentials: false
538
+ fetch-depth: 2
539
+ - name: Runtime
540
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
541
+ with:
542
+ persist-credentials: false
543
+ repository: ${{ inputs.runtime-repository }}
544
+ ref: ${{ inputs.runtime-ref }}
545
+ path: .github/.code-foundry
546
+ sparse-checkout: |
547
+ .github/actions
548
+ src/lib
549
+ src/runtime-core.mjs
550
+ src/runtime.mjs
551
+ - name: Install runtime
552
+ run: |
553
+ mkdir -p .github/actions
554
+ mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
555
+ cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
556
+ - name: Detect
557
+ id: applicability
558
+ env:
559
+ EVENT_NAME: ${{ github.event_name }}
560
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
561
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
562
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
563
+ BEFORE_SHA: ${{ github.event.before }}
564
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile unit >> "$GITHUB_OUTPUT"
565
+ - name: Setup
566
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
567
+ uses: ./.github/actions/setup
568
+ with:
569
+ install: true
570
+ install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
571
+ install-python: ${{ steps.applicability.outputs.python == 'true' }}
572
+ install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
573
+ cache-build: false
574
+ cache-environment: false
575
+ cache-packages: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
576
+ task: unit
577
+ task-javascript: ${{ steps.applicability.outputs.javascript }}
578
+ task-python: ${{ steps.applicability.outputs.python }}
579
+ task-rust: ${{ steps.applicability.outputs.rust }}
580
+ - name: Unit
581
+ id: execute
582
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
583
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci unit
584
+ - name: Retain task receipt
585
+ if: >-
586
+ always() &&
587
+ (steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
588
+ steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
589
+ hashFiles('.code-foundry/results/unit.json') != ''
590
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
591
+ with:
592
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-unit
593
+ path: .code-foundry/results/unit.json
594
+ include-hidden-files: true
595
+ if-no-files-found: error
596
+ retention-days: 14
597
+ - name: Upload coverage
598
+ if: >-
599
+ always() &&
600
+ steps.applicability.outputs.applicable == 'true' &&
601
+ hashFiles('coverage/**', 'htmlcov/**', '.coverage*', 'target/llvm-cov/**') != ''
602
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
603
+ with:
604
+ name: coverage-unit-${{ github.run_id }}
605
+ path: |
606
+ coverage/**
607
+ htmlcov/**
608
+ .coverage*
609
+ target/llvm-cov/**
610
+ compression-level: 1
611
+ if-no-files-found: ignore
612
+ retention-days: 14
613
+
614
+ integration:
615
+ name: Integration
616
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
617
+ runs-on: ${{ inputs.test-runner }}
618
+ timeout-minutes: 30
619
+ steps:
620
+ - name: Checkout
621
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
622
+ with:
623
+ persist-credentials: false
624
+ fetch-depth: 2
625
+ - name: Runtime
626
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
627
+ with:
628
+ persist-credentials: false
629
+ repository: ${{ inputs.runtime-repository }}
630
+ ref: ${{ inputs.runtime-ref }}
631
+ path: .github/.code-foundry
632
+ sparse-checkout: |
633
+ .github/actions
634
+ src/lib
635
+ src/runtime-core.mjs
636
+ src/runtime.mjs
637
+ - name: Install runtime
638
+ run: |
639
+ mkdir -p .github/actions
640
+ mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
641
+ cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
642
+ - name: Detect
643
+ id: applicability
644
+ env:
645
+ EVENT_NAME: ${{ github.event_name }}
646
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
647
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
648
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
649
+ BEFORE_SHA: ${{ github.event.before }}
650
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile integration >> "$GITHUB_OUTPUT"
651
+ - name: Setup
652
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
653
+ uses: ./.github/actions/setup
654
+ with:
655
+ install: true
656
+ install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
657
+ install-python: ${{ steps.applicability.outputs.python == 'true' }}
658
+ install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
659
+ cache-build: ${{ steps.applicability.outputs.rust == 'true' }}
660
+ cache-environment: false
661
+ cache-save: ${{ github.event_name == 'push' }}
662
+ task: integration
663
+ task-javascript: ${{ steps.applicability.outputs.javascript }}
664
+ task-python: ${{ steps.applicability.outputs.python }}
665
+ task-rust: ${{ steps.applicability.outputs.rust }}
666
+ - name: Integration
667
+ id: execute
668
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
669
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci integration
670
+ - name: Retain task receipt
671
+ if: >-
672
+ always() &&
673
+ (steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
674
+ steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
675
+ hashFiles('.code-foundry/results/integration.json') != ''
676
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
677
+ with:
678
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-integration
679
+ path: .code-foundry/results/integration.json
680
+ include-hidden-files: true
681
+ if-no-files-found: error
682
+ retention-days: 14
683
+
684
+ e2e:
685
+ name: E2E
686
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
687
+ runs-on: ${{ inputs.test-runner }}
688
+ timeout-minutes: 45
689
+ # Shards duplicate the whole job, but each shard owns a runner-local test
690
+ # database (repositories without DATABASE_URL fall back to their own local
691
+ # compose services), so shards stay isolated. A single-entry matrix keeps
692
+ # the unsharded default byte-compatible with the pre-matrix job.
693
+ strategy:
694
+ fail-fast: false
695
+ matrix:
696
+ shard: ${{ fromJson(format('[{0}]', inputs.e2e-shard-list)) }}
697
+ steps:
698
+ - name: Checkout
699
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
700
+ with:
701
+ persist-credentials: false
702
+ fetch-depth: 2
703
+ - name: Runtime
704
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
705
+ with:
706
+ persist-credentials: false
707
+ repository: ${{ inputs.runtime-repository }}
708
+ ref: ${{ inputs.runtime-ref }}
709
+ path: .github/.code-foundry
710
+ sparse-checkout: |
711
+ .github/actions
712
+ src/lib
713
+ src/runtime-core.mjs
714
+ src/runtime.mjs
715
+ - name: Install runtime
716
+ run: |
717
+ mkdir -p .github/actions
718
+ mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
719
+ cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
720
+ - name: Detect
721
+ id: applicability
722
+ env:
723
+ EVENT_NAME: ${{ github.event_name }}
724
+ BASE_REF: ${{ github.event.pull_request.base.ref }}
725
+ BASE_SHA: ${{ github.event.pull_request.base.sha }}
726
+ HEAD_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
727
+ BEFORE_SHA: ${{ github.event.before }}
728
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci task_profile e2e >> "$GITHUB_OUTPUT"
729
+ - name: Cache browser binaries
730
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false' && steps.applicability.outputs.browser == 'true'
731
+ uses: ./.github/actions/cache
732
+ with:
733
+ save: ${{ github.event_name == 'push' }}
734
+ path: |
735
+ ~/.cache/ms-playwright
736
+ ~/.cache/Cypress
737
+ ~/.cache/puppeteer
738
+ key: ${{ runner.os }}-e2e-browsers-${{ hashFiles('**/package.json', '**/bun.lock', '**/bun.lockb', '**/pnpm-lock.yaml', '**/yarn.lock', '**/package-lock.json', '**/playwright.config.*', '**/cypress.config.*') }}
739
+ restore-keys: |
740
+ ${{ runner.os }}-e2e-browsers-
741
+ - name: Setup
742
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
743
+ uses: ./.github/actions/setup
744
+ with:
745
+ install: true
746
+ install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
747
+ install-python: ${{ steps.applicability.outputs.python == 'true' }}
748
+ install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
749
+ cache-build: false
750
+ cache-environment: false
751
+ cache-save: ${{ github.event_name == 'push' }}
752
+ task: e2e
753
+ task-javascript: ${{ steps.applicability.outputs.javascript }}
754
+ task-python: ${{ steps.applicability.outputs.python }}
755
+ task-rust: ${{ steps.applicability.outputs.rust }}
756
+ - name: E2E
757
+ id: execute
758
+ if: steps.applicability.outputs.applicable == 'true' && steps.applicability.outputs.affected != 'false'
759
+ env:
760
+ E2E_SHARD_INDEX: ${{ matrix.shard }}
761
+ E2E_TOTAL_SHARDS: ${{ inputs.e2e-total-shards }}
762
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" ci e2e
763
+ - name: Retain task receipt
764
+ if: >-
765
+ always() &&
766
+ (steps.execute.outcome == 'success' || steps.execute.outcome == 'failure' ||
767
+ steps.applicability.outputs.applicable == 'false' || steps.applicability.outputs.affected == 'false') &&
768
+ hashFiles('.code-foundry/results/e2e.json') != ''
769
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
770
+ with:
771
+ name: ${{ inputs.artifact-prefix }}-${{ github.run_id }}-${{ github.run_attempt }}-e2e${{ inputs.e2e-total-shards != '1' && format('-s{0}', matrix.shard) || '' }}
772
+ path: .code-foundry/results/e2e.json
773
+ include-hidden-files: true
774
+ if-no-files-found: error
775
+ retention-days: 14
776
+
777
+ # Profile and dependency audit merged into one job. The split orchestrators
778
+ # run a profile job that feeds an audit matrix; here the language blocks run
779
+ # sequentially, driven directly by the profile step's outputs, so the second
780
+ # runner spin-up disappears. Python requirements run in one loop inside the
781
+ # audit step because a matrix cannot follow preceding steps in the same job.
782
+ audit:
783
+ name: Audit
784
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.mode == 'audit'
785
+ runs-on: ${{ inputs.security-runner }}
786
+ timeout-minutes: 30
787
+ steps:
788
+ - name: Checkout
789
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
790
+ with:
791
+ persist-credentials: false
792
+ fetch-depth: 2
793
+ filter: blob:none
794
+ sparse-checkout: |
795
+ .github
796
+ .mise.toml
797
+ mise.lock
798
+ .npmrc
799
+ .pnpmfile.cjs
800
+ .yarnrc*
801
+ **/package.json
802
+ **/bun.lock
803
+ **/bun.lockb
804
+ **/pnpm-lock.yaml
805
+ **/yarn.lock
806
+ **/package-lock.json
807
+ **/Cargo.toml
808
+ **/Cargo.lock
809
+ **/.cargo/**
810
+ **/pyproject.toml
811
+ **/requirements*.txt
812
+ **/setup.py
813
+ **/setup.cfg
814
+ **/Pipfile
815
+ **/Pipfile.lock
816
+ **/poetry.lock
817
+ **/uv.lock
818
+ sparse-checkout-cone-mode: false
819
+ - name: Runtime
820
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
821
+ with:
822
+ persist-credentials: false
823
+ repository: ${{ inputs.runtime-repository }}
824
+ ref: ${{ inputs.runtime-ref }}
825
+ path: .github/.code-foundry
826
+ sparse-checkout: |
827
+ .github/actions
828
+ src/lib
829
+ src/runtime-core.mjs
830
+ src/runtime.mjs
831
+ - name: Install runtime
832
+ run: |
833
+ mkdir -p .github/actions
834
+ mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
835
+ cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
836
+ - name: Detect
837
+ id: profile
838
+ env:
839
+ REPO_FOUNDRY_PRIVATE: ${{ github.event.repository.private }}
840
+ REPO_FOUNDRY_VISIBILITY: ${{ github.event.repository.visibility }}
841
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security profile >> "$GITHUB_OUTPUT"
842
+ - name: Dependency Review
843
+ if: ${{ github.event_name == 'pull_request' && steps.profile.outputs.dependency_review == 'true' }}
844
+ uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5
845
+ with:
846
+ fail-on-severity: high
847
+ license-check: true
848
+ - name: Detect audit toolchain
849
+ id: audit-toolchain
850
+ if: steps.profile.outputs.javascript == 'true' || steps.profile.outputs.rust == 'true' || steps.profile.outputs.python == 'true'
851
+ shell: bash
852
+ env:
853
+ REPO_FOUNDRY_LANGUAGE: ${{ steps.profile.outputs.javascript == 'true' && 'javascript' || (steps.profile.outputs.rust == 'true' && 'rust' || 'python') }}
854
+ run: |
855
+ toolchain=auto
856
+ configured_toolchain=''
857
+ configured_package_manager=''
858
+ if [ -f .github/code-foundry.yml ]; then
859
+ configured_toolchain="$(awk -F': ' '/^toolchain:/ {print $2; exit}' .github/code-foundry.yml)"
860
+ configured_package_manager="$(awk -F': ' '/^package_manager:/ {print $2; exit}' .github/code-foundry.yml)"
861
+ fi
862
+ [ -n "$configured_toolchain" ] && toolchain="$configured_toolchain"
863
+ if [ "$toolchain" = auto ] && [ -f .mise.toml ]; then toolchain=mise; fi
864
+
865
+ package_manager=none
866
+ case "$configured_package_manager" in
867
+ bun|pnpm|yarn|npm|none) package_manager="$configured_package_manager" ;;
868
+ *)
869
+ if [ -f bun.lock ] || [ -f bun.lockb ]; then package_manager=bun
870
+ elif [ -f pnpm-lock.yaml ]; then package_manager=pnpm
871
+ elif [ -f yarn.lock ]; then package_manager=yarn
872
+ elif [ -f package-lock.json ]; then package_manager=npm
873
+ elif [ -f package.json ]; then package_manager=bun
874
+ fi
875
+ ;;
876
+ esac
877
+
878
+ mise_tools=''
879
+ configured_tool() {
880
+ [ -f .mise.toml ] && grep -Eq "^$1[[:space:]]*=" .mise.toml
881
+ }
882
+ add_mise_tool() {
883
+ configured_tool "$1" || return 0
884
+ if [ -n "$mise_tools" ]; then mise_tools="$mise_tools $1"; else mise_tools="$1"; fi
885
+ }
886
+ if [ "$toolchain" = mise ] && [ -f .mise.toml ]; then
887
+ case "$REPO_FOUNDRY_LANGUAGE" in
888
+ javascript)
889
+ add_mise_tool node
890
+ [ "$package_manager" = bun ] && add_mise_tool bun
891
+ ;;
892
+ python)
893
+ add_mise_tool python
894
+ add_mise_tool uv
895
+ add_mise_tool ruff
896
+ ;;
897
+ rust) add_mise_tool rust ;;
898
+ esac
899
+ fi
900
+
901
+ {
902
+ printf 'toolchain_mode=%s\n' "$toolchain"
903
+ printf 'package_manager=%s\n' "$package_manager"
904
+ printf 'mise_tools=%s\n' "$mise_tools"
905
+ } >> "$GITHUB_OUTPUT"
906
+ - name: Setup mise toolchain
907
+ if: steps.audit-toolchain.outputs.mise_tools != ''
908
+ uses: jdx/mise-action@c2a87611a18de5b3828c5652fe268e992400cb5c # v4
909
+ with:
910
+ version: 2026.9.2
911
+ cache: false
912
+ install_args: ${{ steps.audit-toolchain.outputs.mise_tools }}
913
+ # --- JavaScript audit block ---
914
+ - name: Detect JavaScript
915
+ id: applicability-javascript
916
+ if: steps.profile.outputs.javascript == 'true'
917
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security should_run javascript >> "$GITHUB_OUTPUT"
918
+ - name: Setup Node
919
+ if: >-
920
+ steps.profile.outputs.javascript == 'true' &&
921
+ steps.applicability-javascript.outputs.applicable == 'true' &&
922
+ steps.audit-toolchain.outputs.toolchain_mode != 'mise' &&
923
+ steps.audit-toolchain.outputs.package_manager != 'bun' &&
924
+ steps.audit-toolchain.outputs.package_manager != 'none'
925
+ uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
926
+ with:
927
+ node-version: 24
928
+ - name: Setup Bun
929
+ if: >-
930
+ steps.profile.outputs.javascript == 'true' &&
931
+ steps.applicability-javascript.outputs.applicable == 'true' &&
932
+ steps.audit-toolchain.outputs.toolchain_mode != 'mise' &&
933
+ steps.audit-toolchain.outputs.package_manager == 'bun'
934
+ uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2
935
+ with:
936
+ bun-version: 1.4.0
937
+ - name: Enable Corepack
938
+ if: >-
939
+ steps.profile.outputs.javascript == 'true' &&
940
+ steps.applicability-javascript.outputs.applicable == 'true' &&
941
+ (steps.audit-toolchain.outputs.package_manager == 'pnpm' ||
942
+ steps.audit-toolchain.outputs.package_manager == 'yarn')
943
+ shell: bash
944
+ run: corepack enable
945
+ - name: Audit JavaScript dependencies
946
+ if: >-
947
+ steps.profile.outputs.javascript == 'true' &&
948
+ steps.applicability-javascript.outputs.applicable == 'true'
949
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security audit javascript
950
+ # --- Rust audit block ---
951
+ - name: Checkout Rust
952
+ if: steps.profile.outputs.rust == 'true'
953
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
954
+ with:
955
+ persist-credentials: false
956
+ filter: blob:none
957
+ path: .audit-worktree
958
+ sparse-checkout: |
959
+ .github
960
+ .mise.toml
961
+ mise.lock
962
+ **/Cargo.toml
963
+ **/Cargo.lock
964
+ **/.cargo/**
965
+ sparse-checkout-cone-mode: false
966
+ - name: Detect Rust
967
+ id: applicability-rust
968
+ if: steps.profile.outputs.rust == 'true'
969
+ working-directory: .audit-worktree
970
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security should_run rust >> "$GITHUB_OUTPUT"
971
+ - name: Check Rust
972
+ id: system-rust
973
+ if: >-
974
+ steps.profile.outputs.rust == 'true' &&
975
+ steps.applicability-rust.outputs.applicable == 'true'
976
+ shell: bash
977
+ run: |
978
+ if command -v cargo >/dev/null 2>&1 && command -v rustc >/dev/null 2>&1; then
979
+ cargo --version
980
+ rustc --version
981
+ echo 'available=true' >> "$GITHUB_OUTPUT"
982
+ else
983
+ echo 'available=false' >> "$GITHUB_OUTPUT"
984
+ fi
985
+ - name: Setup Rust
986
+ if: >-
987
+ steps.profile.outputs.rust == 'true' &&
988
+ steps.applicability-rust.outputs.applicable == 'true' &&
989
+ steps.audit-toolchain.outputs.toolchain_mode != 'mise' &&
990
+ steps.system-rust.outputs.available != 'true'
991
+ uses: dtolnay/rust-toolchain@6bed0761d98439e5a578e2877258200ad565ba87 # stable
992
+ - name: Install cargo-audit
993
+ if: >-
994
+ steps.profile.outputs.rust == 'true' &&
995
+ steps.applicability-rust.outputs.applicable == 'true'
996
+ uses: taiki-e/install-action@cb33e69fad06166ca28a42b2575e4dadabf62ee8 # v2
997
+ with:
998
+ tool: cargo-audit
999
+ - name: Audit Rust dependencies
1000
+ if: >-
1001
+ steps.profile.outputs.rust == 'true' &&
1002
+ steps.applicability-rust.outputs.applicable == 'true'
1003
+ working-directory: .audit-worktree
1004
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security audit rust
1005
+ # --- Python audit block ---
1006
+ - name: Checkout Python
1007
+ if: steps.profile.outputs.python == 'true'
1008
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
1009
+ with:
1010
+ persist-credentials: false
1011
+ filter: blob:none
1012
+ path: .audit-worktree
1013
+ sparse-checkout: |
1014
+ .github
1015
+ .mise.toml
1016
+ mise.lock
1017
+ **/pyproject.toml
1018
+ **/requirements*.txt
1019
+ **/setup.py
1020
+ **/setup.cfg
1021
+ **/Pipfile
1022
+ **/Pipfile.lock
1023
+ **/poetry.lock
1024
+ **/uv.lock
1025
+ sparse-checkout-cone-mode: false
1026
+ - name: Detect Python
1027
+ id: applicability-python
1028
+ if: steps.profile.outputs.python == 'true'
1029
+ working-directory: .audit-worktree
1030
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security should_run python >> "$GITHUB_OUTPUT"
1031
+ - name: Setup Python
1032
+ if: >-
1033
+ steps.profile.outputs.python == 'true' &&
1034
+ steps.applicability-python.outputs.applicable == 'true' &&
1035
+ steps.audit-toolchain.outputs.toolchain_mode != 'mise'
1036
+ uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
1037
+ with:
1038
+ python-version: '3.13'
1039
+ - name: Check uv
1040
+ id: uv
1041
+ if: steps.profile.outputs.python == 'true' && steps.applicability-python.outputs.applicable == 'true'
1042
+ shell: bash
1043
+ run: |
1044
+ if command -v uv >/dev/null 2>&1; then
1045
+ echo 'available=true' >> "$GITHUB_OUTPUT"
1046
+ else
1047
+ echo 'available=false' >> "$GITHUB_OUTPUT"
1048
+ fi
1049
+ - name: Setup uv
1050
+ if: >-
1051
+ steps.profile.outputs.python == 'true' &&
1052
+ steps.applicability-python.outputs.applicable == 'true' &&
1053
+ steps.uv.outputs.available != 'true'
1054
+ uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
1055
+ with:
1056
+ version: 0.11.32
1057
+ enable-cache: false
1058
+ - name: Audit Python dependencies
1059
+ if: steps.profile.outputs.python == 'true' && steps.applicability-python.outputs.applicable == 'true'
1060
+ working-directory: .audit-worktree
1061
+ shell: bash
1062
+ env:
1063
+ REQUIREMENTS_JSON: ${{ steps.profile.outputs.python_requirements }}
1064
+ run: |
1065
+ # The split orchestrator fans one matrix job out per Python
1066
+ # requirement; a single merged job loops over them instead.
1067
+ requirements=''
1068
+ if [ -n "$REQUIREMENTS_JSON" ] && [ "$REQUIREMENTS_JSON" != '[]' ]; then
1069
+ requirements="$(node -e '
1070
+ const parsed = JSON.parse(process.argv[1] || "[]");
1071
+ console.log(parsed.filter((item) => item && item !== "none").join("\n"));
1072
+ ' "$REQUIREMENTS_JSON")"
1073
+ fi
1074
+ if [ -z "$requirements" ]; then
1075
+ node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security audit python
1076
+ else
1077
+ while IFS= read -r requirement; do
1078
+ [ -n "$requirement" ] || continue
1079
+ echo "Auditing Python requirements set: $requirement"
1080
+ REPO_FOUNDRY_PYTHON_REQUIREMENT="$requirement" \
1081
+ node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" security audit python
1082
+ done <<< "$requirements"
1083
+ fi
1084
+
1085
+ codeql:
1086
+ name: CodeQL
1087
+ # Release-please pull requests also analyze with CodeQL so repository
1088
+ # rulesets requiring code scanning results never deadlock the release.
1089
+ if: vars.CI_BILLING_PAUSED != 'true' && inputs.codeql == true && (inputs.mode == 'audit' || inputs.mode == 'release')
1090
+ uses: ./.github/workflows/codeql.yml
1091
+ with:
1092
+ runtime-repository: ${{ inputs.runtime-repository }}
1093
+ runtime-ref: ${{ inputs.runtime-ref }}
1094
+ runner: ${{ inputs.codeql-runner }}
1095
+ rust-shards: ${{ inputs.rust-shards }}
1096
+ rust-threads: ${{ inputs.rust-threads }}
1097
+ rust-max-parallel: ${{ inputs.rust-max-parallel }}
1098
+
1099
+ # Aggregate check: "Validation / Gate" (caller job name + this job name).
1100
+ # Always evaluates; only jobs required for the mode must have succeeded.
1101
+ # Category results fold the merged job's lanes back into the same FOUNDRY_*
1102
+ # vocabulary the split orchestrators feed the runtime gate, so
1103
+ # evaluateValidationGate's mode truth table is reused unchanged.
1104
+ gate:
1105
+ name: Gate
1106
+ needs: [fast-lanes, lint, type-check, unit, integration, e2e, audit, codeql]
1107
+ if: vars.CI_BILLING_PAUSED != 'true' && always()
1108
+ runs-on: ubuntu-slim
1109
+ timeout-minutes: 10
1110
+ env:
1111
+ FOUNDRY_MODE: ${{ inputs.mode }}
1112
+ # CI category: lint and type-check always run; the merged fast-lanes job
1113
+ # carries the format and build lanes.
1114
+ FOUNDRY_CI: ${{ (needs.lint.result != 'success' && needs.lint.result) || (needs.type-check.result != 'success' && needs.type-check.result) || (needs.fast-lanes.result != 'success' && needs.fast-lanes.result) || 'success' }}
1115
+ # Test category: unit always runs and must succeed; integration and e2e
1116
+ # are audit-tier jobs whose expected skip on fast/release is not a
1117
+ # failure; the merged fast-lanes job carries performance, smoke, and
1118
+ # eval-mode lanes, so its result joins the category too.
1119
+ FOUNDRY_TEST: ${{ needs.unit.result == 'success' && needs.fast-lanes.result == 'success' && (needs.integration.result == 'success' || needs.integration.result == 'skipped') && (needs.e2e.result == 'success' || needs.e2e.result == 'skipped') && 'success' || ((needs.integration.result != 'success' && needs.integration.result != 'skipped' && needs.integration.result) || (needs.e2e.result != 'success' && needs.e2e.result != 'skipped' && needs.e2e.result) || (needs.unit.result != 'success' && needs.unit.result) || (needs.fast-lanes.result != 'success' && needs.fast-lanes.result) || 'failure') }}
1120
+ FOUNDRY_SECURITY: ${{ needs.audit.result }}
1121
+ # This orchestrator runs CodeQL only when the consumer's canonical
1122
+ # configuration enables it; otherwise the unavailability decision is
1123
+ # treated as satisfied without registering a skipped PR check.
1124
+ FOUNDRY_CODEQL: ${{ inputs.codeql == true && needs.codeql.result || 'success' }}
1125
+ # Eval runs inside the merged fast-lanes job on the audit tier; a
1126
+ # fast-lanes failure on that tier marks the eval category failed even if
1127
+ # another merged lane caused it, which fails closed.
1128
+ FOUNDRY_EVAL: ${{ needs.fast-lanes.result }}
1129
+ steps:
1130
+ - name: Checkout runtime
1131
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
1132
+ with:
1133
+ persist-credentials: false
1134
+ repository: ${{ inputs.runtime-repository }}
1135
+ ref: ${{ inputs.runtime-ref }}
1136
+ path: .github/.code-foundry
1137
+ sparse-checkout: |
1138
+ src/lib
1139
+ src/runtime-core.mjs
1140
+ src/runtime.mjs
1141
+ - name: Install runtime
1142
+ run: mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
1143
+ - name: Checkout consumer repository
1144
+ if: ${{ inputs.mode == 'release' }}
1145
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
1146
+ with:
1147
+ persist-credentials: false
1148
+ fetch-depth: 0
1149
+ filter: blob:none
1150
+ - name: Validate generated release diff
1151
+ if: ${{ inputs.mode == 'release' }}
1152
+ env:
1153
+ FOUNDRY_BASE_SHA: ${{ github.event.pull_request.base.sha }}
1154
+ FOUNDRY_HEAD_REF: ${{ github.event.pull_request.head.ref }}
1155
+ FOUNDRY_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
1156
+ FOUNDRY_REPOSITORY: ${{ github.repository }}
1157
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" validation release_diff
1158
+ - name: Evaluate aggregate gate
1159
+ run: node "$RUNNER_TEMP/code-foundry/src/runtime.mjs" validation gate