code-foundry 1.44.10 → 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.
- package/.github/workflows/release.yml +31 -7
- package/.github/workflows/validation-billing.yml +1159 -0
- package/CHANGELOG.md +15 -15
- package/docs/CONFIGURATION.md +26 -25
- package/package.json +1 -1
- package/src/commands/sync.mjs +20 -0
|
@@ -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
|