code-foundry 1.0.6 → 1.1.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/codeql.yml +72 -184
- package/.github/workflows/security.yml +96 -129
- package/CHANGELOG.md +7 -0
- package/docs/WORKFLOWS.md +14 -5
- package/package.json +1 -1
|
@@ -39,7 +39,9 @@ permissions:
|
|
|
39
39
|
packages: read
|
|
40
40
|
security-events: write
|
|
41
41
|
|
|
42
|
-
#
|
|
42
|
+
# Analyzers run only for detected languages: the analysis matrix is built from
|
|
43
|
+
# detection, so repositories never see skipped checks for languages they do
|
|
44
|
+
# not use. An empty matrix while analysis is enabled fails the build closed.
|
|
43
45
|
env:
|
|
44
46
|
REPO_FOUNDRY_PROFILE: ${{ vars.REPO_FOUNDRY_PROFILE }}
|
|
45
47
|
REPO_FOUNDRY_LANGUAGES: ${{ vars.REPO_FOUNDRY_LANGUAGES }}
|
|
@@ -58,6 +60,8 @@ jobs:
|
|
|
58
60
|
outputs:
|
|
59
61
|
languages: ${{ steps.languages.outputs.languages }}
|
|
60
62
|
enabled: ${{ steps.languages.outputs.enabled }}
|
|
63
|
+
matrix: ${{ steps.matrix.outputs.matrix }}
|
|
64
|
+
rust_matrix: ${{ steps.matrix.outputs.rust_matrix }}
|
|
61
65
|
code_security: ${{ steps.security.outputs.status }}
|
|
62
66
|
actions_available: ${{ steps.languages.outputs.actions_available }}
|
|
63
67
|
actions_changed: ${{ steps.languages.outputs.actions_changed }}
|
|
@@ -126,148 +130,65 @@ jobs:
|
|
|
126
130
|
REPO_FOUNDRY_PRIVATE: ${{ github.event.repository.private }}
|
|
127
131
|
REPO_FOUNDRY_VISIBILITY: ${{ github.event.repository.visibility }}
|
|
128
132
|
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs codeql
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
136
|
-
needs.detect.outputs.actions_available == 'true'
|
|
137
|
-
runs-on: ${{ inputs.runner }}
|
|
138
|
-
timeout-minutes: 30
|
|
139
|
-
steps:
|
|
140
|
-
- name: Checkout
|
|
141
|
-
if: >-
|
|
142
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
143
|
-
needs.detect.outputs.actions_available == 'true' &&
|
|
144
|
-
needs.detect.outputs.actions_changed == 'true'
|
|
145
|
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
146
|
-
with:
|
|
147
|
-
persist-credentials: false
|
|
148
|
-
- name: Runtime
|
|
149
|
-
if: >-
|
|
150
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
151
|
-
needs.detect.outputs.actions_available == 'true' &&
|
|
152
|
-
needs.detect.outputs.actions_changed == 'true'
|
|
153
|
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
154
|
-
with:
|
|
155
|
-
persist-credentials: false
|
|
156
|
-
repository: ${{ inputs.runtime-repository }}
|
|
157
|
-
ref: ${{ inputs.runtime-ref }}
|
|
158
|
-
path: .github/.code-foundry
|
|
159
|
-
sparse-checkout: |
|
|
160
|
-
.github/actions
|
|
161
|
-
src/lib
|
|
162
|
-
src/runtime.mjs
|
|
163
|
-
- name: Install runtime
|
|
164
|
-
if: >-
|
|
165
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
166
|
-
needs.detect.outputs.actions_available == 'true' &&
|
|
167
|
-
needs.detect.outputs.actions_changed == 'true'
|
|
168
|
-
run: |
|
|
169
|
-
mkdir -p .github/actions
|
|
170
|
-
mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
|
|
171
|
-
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
172
|
-
- name: Analyze
|
|
173
|
-
if: >-
|
|
174
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
175
|
-
needs.detect.outputs.actions_available == 'true' &&
|
|
176
|
-
needs.detect.outputs.actions_changed == 'true'
|
|
177
|
-
uses: ./.github/actions/codeql
|
|
178
|
-
with:
|
|
179
|
-
language: actions
|
|
180
|
-
build-mode: ${{ needs.detect.outputs.actions_build_mode }}
|
|
181
|
-
category: /language:actions
|
|
182
|
-
- name: Not applicable
|
|
183
|
-
if: >-
|
|
184
|
-
needs.detect.outputs.enabled != 'true' ||
|
|
185
|
-
needs.detect.outputs.actions_available != 'true' ||
|
|
186
|
-
needs.detect.outputs.actions_changed != 'true'
|
|
187
|
-
run: echo "CodeQL Actions analysis is not applicable to this change."
|
|
188
|
-
|
|
189
|
-
analyze-typescript:
|
|
190
|
-
name: Analyze (TypeScript)
|
|
191
|
-
needs: detect
|
|
192
|
-
if: >-
|
|
193
|
-
vars.CI_BILLING_PAUSED != 'true' &&
|
|
194
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
195
|
-
needs.detect.outputs.javascript_available == 'true'
|
|
196
|
-
runs-on: ${{ inputs.runner }}
|
|
197
|
-
timeout-minutes: 30
|
|
198
|
-
steps:
|
|
199
|
-
- name: Checkout
|
|
200
|
-
if: >-
|
|
201
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
202
|
-
needs.detect.outputs.javascript_available == 'true' &&
|
|
203
|
-
needs.detect.outputs.javascript_changed == 'true'
|
|
204
|
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
205
|
-
with:
|
|
206
|
-
persist-credentials: false
|
|
207
|
-
- name: Runtime
|
|
208
|
-
if: >-
|
|
209
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
210
|
-
needs.detect.outputs.javascript_available == 'true' &&
|
|
211
|
-
needs.detect.outputs.javascript_changed == 'true'
|
|
212
|
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
213
|
-
with:
|
|
214
|
-
persist-credentials: false
|
|
215
|
-
repository: ${{ inputs.runtime-repository }}
|
|
216
|
-
ref: ${{ inputs.runtime-ref }}
|
|
217
|
-
path: .github/.code-foundry
|
|
218
|
-
sparse-checkout: |
|
|
219
|
-
.github/actions
|
|
220
|
-
src/lib
|
|
221
|
-
src/runtime.mjs
|
|
222
|
-
- name: Install runtime
|
|
223
|
-
if: >-
|
|
224
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
225
|
-
needs.detect.outputs.javascript_available == 'true' &&
|
|
226
|
-
needs.detect.outputs.javascript_changed == 'true'
|
|
133
|
+
- id: matrix
|
|
134
|
+
name: Build analysis matrix
|
|
135
|
+
env:
|
|
136
|
+
MATRIX_ENABLED: ${{ steps.languages.outputs.enabled }}
|
|
137
|
+
MATRIX_LANGUAGES: ${{ steps.languages.outputs.languages }}
|
|
138
|
+
MATRIX_SHARDS: ${{ inputs.rust-shards }}
|
|
227
139
|
run: |
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
140
|
+
node -e '
|
|
141
|
+
const fs = require("node:fs");
|
|
142
|
+
const out = process.env.GITHUB_OUTPUT;
|
|
143
|
+
function append(name, value) { fs.appendFileSync(out, name + "=" + value + "\n"); }
|
|
144
|
+
const enabled = process.env.MATRIX_ENABLED === "true";
|
|
145
|
+
if (!enabled) {
|
|
146
|
+
append("matrix", "[]");
|
|
147
|
+
append("rust_matrix", "[]");
|
|
148
|
+
} else {
|
|
149
|
+
const languages = JSON.parse(process.env.MATRIX_LANGUAGES || "[]");
|
|
150
|
+
const shards = JSON.parse(process.env.MATRIX_SHARDS || "[\"all\"]");
|
|
151
|
+
const display = { actions: "Actions", "javascript-typescript": "TypeScript", python: "Python" };
|
|
152
|
+
const matrix = languages
|
|
153
|
+
.filter((entry) => entry.language !== "rust")
|
|
154
|
+
.map((entry) => ({
|
|
155
|
+
display: display[entry.language] || entry.language,
|
|
156
|
+
language: entry.language,
|
|
157
|
+
category: "/language/" + entry.language,
|
|
158
|
+
build_mode: entry["build-mode"] || "none",
|
|
159
|
+
changed: entry.changed === true,
|
|
160
|
+
}));
|
|
161
|
+
const rust = languages.find((entry) => entry.language === "rust");
|
|
162
|
+
const rustMatrix = rust
|
|
163
|
+
? shards.map((shard) => ({ display: "Rust (" + shard + ")", shard: String(shard), changed: rust.changed === true }))
|
|
164
|
+
: [];
|
|
165
|
+
if (!matrix.length && !rustMatrix.length) {
|
|
166
|
+
console.error("CodeQL analysis matrix is empty while analysis is enabled.");
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
append("matrix", JSON.stringify(matrix));
|
|
170
|
+
append("rust_matrix", JSON.stringify(rustMatrix));
|
|
171
|
+
}
|
|
172
|
+
'
|
|
247
173
|
|
|
248
|
-
analyze
|
|
249
|
-
name: Analyze (
|
|
174
|
+
analyze:
|
|
175
|
+
name: Analyze (${{ matrix.entry.display }})
|
|
250
176
|
needs: detect
|
|
251
|
-
if:
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
177
|
+
if: vars.CI_BILLING_PAUSED != 'true' && needs.detect.outputs.enabled == 'true'
|
|
178
|
+
strategy:
|
|
179
|
+
fail-fast: false
|
|
180
|
+
matrix:
|
|
181
|
+
entry: ${{ fromJson(needs.detect.outputs.matrix || '[]') }}
|
|
255
182
|
runs-on: ${{ inputs.runner }}
|
|
256
183
|
timeout-minutes: 30
|
|
257
184
|
steps:
|
|
258
185
|
- name: Checkout
|
|
259
|
-
if:
|
|
260
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
261
|
-
needs.detect.outputs.python_available == 'true' &&
|
|
262
|
-
needs.detect.outputs.python_changed == 'true'
|
|
186
|
+
if: ${{ matrix.entry.changed == true }}
|
|
263
187
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
264
188
|
with:
|
|
265
189
|
persist-credentials: false
|
|
266
190
|
- name: Runtime
|
|
267
|
-
if:
|
|
268
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
269
|
-
needs.detect.outputs.python_available == 'true' &&
|
|
270
|
-
needs.detect.outputs.python_changed == 'true'
|
|
191
|
+
if: ${{ matrix.entry.changed == true }}
|
|
271
192
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
272
193
|
with:
|
|
273
194
|
persist-credentials: false
|
|
@@ -279,59 +200,41 @@ jobs:
|
|
|
279
200
|
src/lib
|
|
280
201
|
src/runtime.mjs
|
|
281
202
|
- name: Install runtime
|
|
282
|
-
if:
|
|
283
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
284
|
-
needs.detect.outputs.python_available == 'true' &&
|
|
285
|
-
needs.detect.outputs.python_changed == 'true'
|
|
203
|
+
if: ${{ matrix.entry.changed == true }}
|
|
286
204
|
run: |
|
|
287
205
|
mkdir -p .github/actions
|
|
288
206
|
mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
|
|
289
207
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
290
208
|
- name: Analyze
|
|
291
|
-
if:
|
|
292
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
293
|
-
needs.detect.outputs.python_available == 'true' &&
|
|
294
|
-
needs.detect.outputs.python_changed == 'true'
|
|
209
|
+
if: ${{ matrix.entry.changed == true }}
|
|
295
210
|
uses: ./.github/actions/codeql
|
|
296
211
|
with:
|
|
297
|
-
language:
|
|
298
|
-
build-mode: ${{
|
|
299
|
-
category:
|
|
212
|
+
language: ${{ matrix.entry.language }}
|
|
213
|
+
build-mode: ${{ matrix.entry.build_mode }}
|
|
214
|
+
category: ${{ matrix.entry.category }}
|
|
300
215
|
- name: Not applicable
|
|
301
|
-
if:
|
|
302
|
-
|
|
303
|
-
needs.detect.outputs.python_available != 'true' ||
|
|
304
|
-
needs.detect.outputs.python_changed != 'true'
|
|
305
|
-
run: echo "CodeQL Python analysis is not applicable to this change."
|
|
216
|
+
if: ${{ matrix.entry.changed != true }}
|
|
217
|
+
run: echo "CodeQL ${{ matrix.entry.display }} analysis is not applicable to this change."
|
|
306
218
|
|
|
307
219
|
analyze-rust:
|
|
308
|
-
name: Analyze (
|
|
220
|
+
name: Analyze (${{ matrix.entry.display }})
|
|
309
221
|
needs: detect
|
|
310
|
-
if:
|
|
311
|
-
vars.CI_BILLING_PAUSED != 'true' &&
|
|
312
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
313
|
-
needs.detect.outputs.rust_available == 'true'
|
|
222
|
+
if: vars.CI_BILLING_PAUSED != 'true' && needs.detect.outputs.enabled == 'true' && needs.detect.outputs.rust_available == 'true'
|
|
314
223
|
strategy:
|
|
315
224
|
fail-fast: false
|
|
316
225
|
max-parallel: ${{ inputs.rust-max-parallel }}
|
|
317
226
|
matrix:
|
|
318
|
-
|
|
227
|
+
entry: ${{ fromJson(needs.detect.outputs.rust_matrix || '[]') }}
|
|
319
228
|
runs-on: ${{ inputs.runner }}
|
|
320
229
|
timeout-minutes: 30
|
|
321
230
|
steps:
|
|
322
231
|
- name: Checkout
|
|
323
|
-
if:
|
|
324
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
325
|
-
needs.detect.outputs.rust_available == 'true' &&
|
|
326
|
-
needs.detect.outputs.rust_changed == 'true'
|
|
232
|
+
if: ${{ matrix.entry.changed == true }}
|
|
327
233
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
328
234
|
with:
|
|
329
235
|
persist-credentials: false
|
|
330
236
|
- name: Runtime
|
|
331
|
-
if:
|
|
332
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
333
|
-
needs.detect.outputs.rust_available == 'true' &&
|
|
334
|
-
needs.detect.outputs.rust_changed == 'true'
|
|
237
|
+
if: ${{ matrix.entry.changed == true }}
|
|
335
238
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
336
239
|
with:
|
|
337
240
|
persist-credentials: false
|
|
@@ -343,22 +246,16 @@ jobs:
|
|
|
343
246
|
src/lib
|
|
344
247
|
src/runtime.mjs
|
|
345
248
|
- name: Install runtime
|
|
346
|
-
if:
|
|
347
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
348
|
-
needs.detect.outputs.rust_available == 'true' &&
|
|
349
|
-
needs.detect.outputs.rust_changed == 'true'
|
|
249
|
+
if: ${{ matrix.entry.changed == true }}
|
|
350
250
|
run: |
|
|
351
251
|
mkdir -p .github/actions
|
|
352
252
|
mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
|
|
353
253
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
354
254
|
- name: Configure Rust scope
|
|
355
|
-
if:
|
|
356
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
357
|
-
needs.detect.outputs.rust_available == 'true' &&
|
|
358
|
-
needs.detect.outputs.rust_changed == 'true'
|
|
255
|
+
if: ${{ matrix.entry.changed == true }}
|
|
359
256
|
id: scope
|
|
360
257
|
env:
|
|
361
|
-
RUST_SCOPE: ${{ matrix.shard }}
|
|
258
|
+
RUST_SCOPE: ${{ matrix.entry.shard }}
|
|
362
259
|
run: |
|
|
363
260
|
set -euo pipefail
|
|
364
261
|
scope="$RUST_SCOPE"
|
|
@@ -403,10 +300,7 @@ jobs:
|
|
|
403
300
|
echo "config_file=$config_file" >> "$GITHUB_OUTPUT"
|
|
404
301
|
echo "scope_id=$scope_id" >> "$GITHUB_OUTPUT"
|
|
405
302
|
- name: Initialize
|
|
406
|
-
if:
|
|
407
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
408
|
-
needs.detect.outputs.rust_available == 'true' &&
|
|
409
|
-
needs.detect.outputs.rust_changed == 'true'
|
|
303
|
+
if: ${{ matrix.entry.changed == true }}
|
|
410
304
|
uses: github/codeql-action/init@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
|
411
305
|
with:
|
|
412
306
|
languages: rust
|
|
@@ -414,18 +308,12 @@ jobs:
|
|
|
414
308
|
config-file: ${{ steps.scope.outputs.config_file }}
|
|
415
309
|
threads: ${{ inputs.rust-threads }}
|
|
416
310
|
- name: Analyze
|
|
417
|
-
if:
|
|
418
|
-
needs.detect.outputs.enabled == 'true' &&
|
|
419
|
-
needs.detect.outputs.rust_available == 'true' &&
|
|
420
|
-
needs.detect.outputs.rust_changed == 'true'
|
|
311
|
+
if: ${{ matrix.entry.changed == true }}
|
|
421
312
|
uses: github/codeql-action/analyze@5595ccaf912efad79be6eef63a5619ff05969be3 # v4
|
|
422
313
|
with:
|
|
423
314
|
category: /language:rust/${{ steps.scope.outputs.scope_id }}
|
|
424
315
|
upload-database: false
|
|
425
316
|
wait-for-processing: false
|
|
426
317
|
- name: Not applicable
|
|
427
|
-
if:
|
|
428
|
-
|
|
429
|
-
needs.detect.outputs.rust_available != 'true' ||
|
|
430
|
-
needs.detect.outputs.rust_changed != 'true'
|
|
431
|
-
run: echo "CodeQL Rust analysis is not applicable to this change."
|
|
318
|
+
if: ${{ matrix.entry.changed != true }}
|
|
319
|
+
run: echo "CodeQL ${{ matrix.entry.display }} analysis is not applicable to this change."
|
|
@@ -45,6 +45,7 @@ jobs:
|
|
|
45
45
|
python: ${{ steps.profile.outputs.python }}
|
|
46
46
|
python_requirements: ${{ steps.profile.outputs.python_requirements }}
|
|
47
47
|
dependency_review: ${{ steps.profile.outputs.dependency_review }}
|
|
48
|
+
audit_matrix: ${{ steps.matrix.outputs.audit_matrix }}
|
|
48
49
|
steps:
|
|
49
50
|
- name: Checkout
|
|
50
51
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
@@ -99,15 +100,49 @@ jobs:
|
|
|
99
100
|
REPO_FOUNDRY_PRIVATE: ${{ github.event.repository.private }}
|
|
100
101
|
REPO_FOUNDRY_VISIBILITY: ${{ github.event.repository.visibility }}
|
|
101
102
|
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security profile >> "$GITHUB_OUTPUT"
|
|
103
|
+
- id: matrix
|
|
104
|
+
name: Build audit matrix
|
|
105
|
+
env:
|
|
106
|
+
MATRIX_JAVASCRIPT: ${{ steps.profile.outputs.javascript }}
|
|
107
|
+
MATRIX_RUST: ${{ steps.profile.outputs.rust }}
|
|
108
|
+
MATRIX_PYTHON: ${{ steps.profile.outputs.python }}
|
|
109
|
+
MATRIX_REQUIREMENTS: ${{ steps.profile.outputs.python_requirements }}
|
|
110
|
+
run: |
|
|
111
|
+
node -e '
|
|
112
|
+
const fs = require("node:fs");
|
|
113
|
+
const env = process.env;
|
|
114
|
+
const entries = [];
|
|
115
|
+
if (env.MATRIX_JAVASCRIPT === "true") entries.push({ display: "JavaScript", language: "javascript" });
|
|
116
|
+
if (env.MATRIX_RUST === "true") entries.push({ display: "Rust", language: "rust" });
|
|
117
|
+
if (env.MATRIX_PYTHON === "true") {
|
|
118
|
+
let requirements = [];
|
|
119
|
+
try { requirements = JSON.parse(env.MATRIX_REQUIREMENTS || "[]"); } catch (error) { requirements = []; }
|
|
120
|
+
for (const requirement of requirements.filter((item) => item && item !== "none")) {
|
|
121
|
+
entries.push({ display: "Python / " + requirement, language: "python", requirement: requirement });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
fs.appendFileSync(env.GITHUB_OUTPUT, "audit_matrix=" + JSON.stringify(entries) + "\n");
|
|
125
|
+
'
|
|
102
126
|
|
|
103
|
-
|
|
104
|
-
|
|
127
|
+
# Audits run only for detected languages: the audit matrix is built from the
|
|
128
|
+
# profile, so repositories never see skipped checks for ecosystems they do
|
|
129
|
+
# not use. An empty matrix skips this job with no per-language rows.
|
|
130
|
+
dependency-audit:
|
|
131
|
+
name: Dependency Audit (${{ matrix.entry.display }})
|
|
105
132
|
needs: profile
|
|
106
|
-
if:
|
|
133
|
+
if: vars.CI_BILLING_PAUSED != 'true' && needs.profile.result == 'success'
|
|
134
|
+
strategy:
|
|
135
|
+
fail-fast: false
|
|
136
|
+
max-parallel: 8
|
|
137
|
+
matrix:
|
|
138
|
+
entry: ${{ fromJson(needs.profile.outputs.audit_matrix || '[]') }}
|
|
107
139
|
runs-on: ${{ inputs.runner }}
|
|
108
140
|
timeout-minutes: 20
|
|
141
|
+
env:
|
|
142
|
+
REPO_FOUNDRY_PYTHON_REQUIREMENT: ${{ matrix.entry.requirement }}
|
|
109
143
|
steps:
|
|
110
|
-
- name: Checkout
|
|
144
|
+
- name: Checkout JavaScript
|
|
145
|
+
if: matrix.entry.language == 'javascript'
|
|
111
146
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
112
147
|
with:
|
|
113
148
|
persist-credentials: false
|
|
@@ -126,43 +161,22 @@ jobs:
|
|
|
126
161
|
**/yarn.lock
|
|
127
162
|
**/package-lock.json
|
|
128
163
|
sparse-checkout-cone-mode: false
|
|
129
|
-
- name:
|
|
164
|
+
- name: Checkout Rust
|
|
165
|
+
if: matrix.entry.language == 'rust'
|
|
130
166
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
131
167
|
with:
|
|
132
168
|
persist-credentials: false
|
|
133
|
-
|
|
134
|
-
ref: ${{ inputs.runtime-ref }}
|
|
135
|
-
path: .github/.code-foundry
|
|
169
|
+
filter: blob:none
|
|
136
170
|
sparse-checkout: |
|
|
137
|
-
.github
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
id: applicability
|
|
147
|
-
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security should_run javascript >> "$GITHUB_OUTPUT"
|
|
148
|
-
- name: Setup
|
|
149
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
150
|
-
uses: ./.github/actions/setup
|
|
151
|
-
with:
|
|
152
|
-
mise-scope: javascript
|
|
153
|
-
cache-save: ${{ github.event_name == 'push' }}
|
|
154
|
-
- name: Audit dependencies
|
|
155
|
-
if: steps.applicability.outputs.applicable == 'true'
|
|
156
|
-
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security audit javascript
|
|
157
|
-
|
|
158
|
-
dependency-audit-rust:
|
|
159
|
-
name: Dependency Audit (Rust)
|
|
160
|
-
needs: profile
|
|
161
|
-
if: ${{ vars.CI_BILLING_PAUSED != 'true' && needs.profile.result == 'success' && needs.profile.outputs.rust == 'true' }}
|
|
162
|
-
runs-on: ${{ inputs.runner }}
|
|
163
|
-
timeout-minutes: 20
|
|
164
|
-
steps:
|
|
165
|
-
- name: Checkout
|
|
171
|
+
.github
|
|
172
|
+
.mise.toml
|
|
173
|
+
mise.lock
|
|
174
|
+
**/Cargo.toml
|
|
175
|
+
**/Cargo.lock
|
|
176
|
+
**/.cargo/**
|
|
177
|
+
sparse-checkout-cone-mode: false
|
|
178
|
+
- name: Checkout Python
|
|
179
|
+
if: matrix.entry.language == 'python'
|
|
166
180
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
167
181
|
with:
|
|
168
182
|
persist-credentials: false
|
|
@@ -171,9 +185,14 @@ jobs:
|
|
|
171
185
|
.github
|
|
172
186
|
.mise.toml
|
|
173
187
|
mise.lock
|
|
174
|
-
**/
|
|
175
|
-
**/
|
|
176
|
-
|
|
188
|
+
**/pyproject.toml
|
|
189
|
+
**/requirements*.txt
|
|
190
|
+
**/setup.py
|
|
191
|
+
**/setup.cfg
|
|
192
|
+
**/Pipfile
|
|
193
|
+
**/Pipfile.lock
|
|
194
|
+
**/poetry.lock
|
|
195
|
+
**/uv.lock
|
|
177
196
|
sparse-checkout-cone-mode: false
|
|
178
197
|
- name: Runtime
|
|
179
198
|
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
@@ -191,12 +210,32 @@ jobs:
|
|
|
191
210
|
mkdir -p .github/actions
|
|
192
211
|
mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
|
|
193
212
|
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
194
|
-
- name: Detect
|
|
195
|
-
id: applicability
|
|
213
|
+
- name: Detect JavaScript
|
|
214
|
+
id: applicability-javascript
|
|
215
|
+
if: matrix.entry.language == 'javascript'
|
|
216
|
+
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security should_run javascript >> "$GITHUB_OUTPUT"
|
|
217
|
+
- name: Detect Rust
|
|
218
|
+
id: applicability-rust
|
|
219
|
+
if: matrix.entry.language == 'rust'
|
|
196
220
|
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security should_run rust >> "$GITHUB_OUTPUT"
|
|
221
|
+
- name: Setup JavaScript
|
|
222
|
+
if: >-
|
|
223
|
+
matrix.entry.language == 'javascript' &&
|
|
224
|
+
steps.applicability-javascript.outputs.applicable == 'true'
|
|
225
|
+
uses: ./.github/actions/setup
|
|
226
|
+
with:
|
|
227
|
+
mise-scope: javascript
|
|
228
|
+
cache-save: ${{ github.event_name == 'push' }}
|
|
229
|
+
- name: Audit JavaScript dependencies
|
|
230
|
+
if: >-
|
|
231
|
+
matrix.entry.language == 'javascript' &&
|
|
232
|
+
steps.applicability-javascript.outputs.applicable == 'true'
|
|
233
|
+
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security audit javascript
|
|
197
234
|
- name: Check Rust
|
|
198
235
|
id: system-rust
|
|
199
|
-
if:
|
|
236
|
+
if: >-
|
|
237
|
+
matrix.entry.language == 'rust' &&
|
|
238
|
+
steps.applicability-rust.outputs.applicable == 'true'
|
|
200
239
|
shell: bash
|
|
201
240
|
run: |
|
|
202
241
|
if command -v cargo >/dev/null 2>&1 && command -v rustc >/dev/null 2>&1; then
|
|
@@ -206,109 +245,37 @@ jobs:
|
|
|
206
245
|
else
|
|
207
246
|
echo 'available=false' >> "$GITHUB_OUTPUT"
|
|
208
247
|
fi
|
|
209
|
-
- name: Setup
|
|
248
|
+
- name: Setup Rust
|
|
210
249
|
if: >-
|
|
211
|
-
|
|
250
|
+
matrix.entry.language == 'rust' &&
|
|
251
|
+
steps.applicability-rust.outputs.applicable == 'true' &&
|
|
212
252
|
steps.system-rust.outputs.available != 'true'
|
|
213
253
|
uses: ./.github/actions/setup
|
|
214
254
|
with:
|
|
215
255
|
mise-scope: rust
|
|
216
256
|
cache-save: ${{ github.event_name == 'push' }}
|
|
217
257
|
- name: Install cargo-audit
|
|
218
|
-
if:
|
|
258
|
+
if: >-
|
|
259
|
+
matrix.entry.language == 'rust' &&
|
|
260
|
+
steps.applicability-rust.outputs.applicable == 'true'
|
|
219
261
|
uses: taiki-e/install-action@cb33e69fad06166ca28a42b2575e4dadabf62ee8 # v2
|
|
220
262
|
with:
|
|
221
263
|
tool: cargo-audit
|
|
222
|
-
- name: Audit dependencies
|
|
223
|
-
if:
|
|
264
|
+
- name: Audit Rust dependencies
|
|
265
|
+
if: >-
|
|
266
|
+
matrix.entry.language == 'rust' &&
|
|
267
|
+
steps.applicability-rust.outputs.applicable == 'true'
|
|
224
268
|
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security audit rust
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
name: Dependency Audit (Python) / ${{ matrix.requirement }}
|
|
228
|
-
needs: profile
|
|
229
|
-
if: >-
|
|
230
|
-
${{ vars.CI_BILLING_PAUSED != 'true' &&
|
|
231
|
-
needs.profile.result == 'success' &&
|
|
232
|
-
needs.profile.outputs.python == 'true' &&
|
|
233
|
-
needs.profile.outputs.python_requirements != '["none"]' }}
|
|
234
|
-
strategy:
|
|
235
|
-
fail-fast: false
|
|
236
|
-
max-parallel: 8
|
|
237
|
-
matrix:
|
|
238
|
-
requirement: ${{ fromJSON(needs.profile.outputs.python_requirements) }}
|
|
239
|
-
runs-on: ${{ inputs.runner }}
|
|
240
|
-
timeout-minutes: 20
|
|
241
|
-
env:
|
|
242
|
-
REPO_FOUNDRY_PYTHON_REQUIREMENT: ${{ matrix.requirement }}
|
|
243
|
-
steps:
|
|
244
|
-
- name: Checkout
|
|
245
|
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
246
|
-
with:
|
|
247
|
-
persist-credentials: false
|
|
248
|
-
filter: blob:none
|
|
249
|
-
sparse-checkout: |
|
|
250
|
-
.github
|
|
251
|
-
.mise.toml
|
|
252
|
-
mise.lock
|
|
253
|
-
**/pyproject.toml
|
|
254
|
-
**/requirements*.txt
|
|
255
|
-
**/setup.py
|
|
256
|
-
**/setup.cfg
|
|
257
|
-
**/Pipfile
|
|
258
|
-
**/Pipfile.lock
|
|
259
|
-
**/poetry.lock
|
|
260
|
-
**/uv.lock
|
|
261
|
-
sparse-checkout-cone-mode: false
|
|
262
|
-
- name: Runtime
|
|
263
|
-
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
264
|
-
with:
|
|
265
|
-
persist-credentials: false
|
|
266
|
-
repository: ${{ inputs.runtime-repository }}
|
|
267
|
-
ref: ${{ inputs.runtime-ref }}
|
|
268
|
-
path: .github/.code-foundry
|
|
269
|
-
sparse-checkout: |
|
|
270
|
-
.github/actions
|
|
271
|
-
src/lib
|
|
272
|
-
src/runtime.mjs
|
|
273
|
-
- name: Install runtime
|
|
274
|
-
run: |
|
|
275
|
-
mkdir -p .github/actions
|
|
276
|
-
mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
|
|
277
|
-
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
278
|
-
- name: Setup
|
|
269
|
+
- name: Setup Python
|
|
270
|
+
if: matrix.entry.language == 'python'
|
|
279
271
|
uses: ./.github/actions/setup
|
|
280
272
|
with:
|
|
281
273
|
mise-scope: python
|
|
282
274
|
cache-save: ${{ github.event_name == 'push' }}
|
|
283
|
-
- name: Audit dependencies
|
|
275
|
+
- name: Audit Python dependencies
|
|
276
|
+
if: matrix.entry.language == 'python'
|
|
284
277
|
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs security audit python
|
|
285
278
|
|
|
286
|
-
dependency-audit-python-gate:
|
|
287
|
-
name: Dependency Audit (Python)
|
|
288
|
-
needs: [profile, dependency-audit-python]
|
|
289
|
-
if: >-
|
|
290
|
-
${{ vars.CI_BILLING_PAUSED != 'true' &&
|
|
291
|
-
always() &&
|
|
292
|
-
needs.profile.result == 'success' &&
|
|
293
|
-
needs.profile.outputs.python == 'true' &&
|
|
294
|
-
needs.profile.outputs.python_requirements != '["none"]' }}
|
|
295
|
-
runs-on: ${{ inputs.runner }}
|
|
296
|
-
timeout-minutes: 5
|
|
297
|
-
steps:
|
|
298
|
-
- name: Gate
|
|
299
|
-
env:
|
|
300
|
-
PROFILE_RESULT: ${{ needs.profile.result }}
|
|
301
|
-
AUDIT_RESULT: ${{ needs.dependency-audit-python.result }}
|
|
302
|
-
run: |
|
|
303
|
-
if [ "$PROFILE_RESULT" != success ]; then
|
|
304
|
-
echo "Python audit profile failed: $PROFILE_RESULT" >&2
|
|
305
|
-
exit 1
|
|
306
|
-
fi
|
|
307
|
-
case "$AUDIT_RESULT" in
|
|
308
|
-
success|skipped) exit 0 ;;
|
|
309
|
-
*) echo "Python dependency audit failed: $AUDIT_RESULT" >&2; exit 1 ;;
|
|
310
|
-
esac
|
|
311
|
-
|
|
312
279
|
dependency-review:
|
|
313
280
|
name: Dependency Review
|
|
314
281
|
needs: profile
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.1.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.0.6...v1.1.0) (2026-09-06)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* scope per-language checks to detected languages via matrix ([#459](https://github.com/0xPlayerOne/code-foundry/issues/459)) ([71f8985](https://github.com/0xPlayerOne/code-foundry/commit/71f8985b9732d39b7b68df40a4c8cbe5a90175fe))
|
|
9
|
+
|
|
3
10
|
## [1.0.6](https://github.com/0xPlayerOne/code-foundry/compare/v1.0.5...v1.0.6) (2026-09-06)
|
|
4
11
|
|
|
5
12
|
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -82,8 +82,13 @@ honor the shared billing pause.
|
|
|
82
82
|
| Release | Release Please, GitHub release, and optional npm publication |
|
|
83
83
|
|
|
84
84
|
Use concise job names such as `CI / Format`, `Test / Unit`, and
|
|
85
|
-
`CodeQL / Analyze (Python)`.
|
|
86
|
-
|
|
85
|
+
`CodeQL / Analyze (Python)`. Per-language CodeQL analyzers and security
|
|
86
|
+
audits run through a detection-built matrix, so a repository only ever shows
|
|
87
|
+
checks for languages it actually uses; inapplicable languages produce no
|
|
88
|
+
checks instead of skipped rows. Required checks should match the jobs
|
|
89
|
+
actually enabled for the repository profile — in practice, require only the
|
|
90
|
+
aggregate `Validation / Gate`, which fails closed unless every generated
|
|
91
|
+
check succeeds.
|
|
87
92
|
|
|
88
93
|
## Merge methods
|
|
89
94
|
|
|
@@ -178,9 +183,13 @@ validation gate. Land changes through the standard `direct` or
|
|
|
178
183
|
- Solidity: preserve the repository's native Hardhat, Foundry, or specialized
|
|
179
184
|
test/security workflows.
|
|
180
185
|
|
|
181
|
-
Jobs detect applicability before installing tools.
|
|
182
|
-
|
|
183
|
-
|
|
186
|
+
Jobs detect applicability before installing tools. Per-language CodeQL and
|
|
187
|
+
security-audit jobs are generated from detection, so empty language surfaces
|
|
188
|
+
produce no checks at all instead of skipped rows; the aggregate
|
|
189
|
+
`Validation / Gate` keeps branch protection unambiguous for mixed-language
|
|
190
|
+
repositories by failing closed unless every generated check succeeds. An
|
|
191
|
+
empty analysis matrix while analysis is enabled fails the build instead of
|
|
192
|
+
silently skipping every analyzer.
|
|
184
193
|
|
|
185
194
|
## Security behavior
|
|
186
195
|
|
package/package.json
CHANGED