code-foundry 0.25.0 → 0.27.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.
Files changed (47) hide show
  1. package/.githooks/pre-commit +3 -4
  2. package/.github/CONTRIBUTING.md +10 -13
  3. package/.github/actions/setup/action.yml +50 -3
  4. package/.github/code-foundry.yml +6 -1
  5. package/.github/licenses/AGPL-3.0-or-later.txt +661 -0
  6. package/.github/licenses/GPL-3.0-or-later.txt +674 -0
  7. package/.github/licenses/MIT.txt +4 -16
  8. package/.github/workflows/ci.yml +20 -23
  9. package/.github/workflows/ci_self-ci.yml +1 -1
  10. package/.github/workflows/codeql.yml +23 -29
  11. package/.github/workflows/codeql_self-ci.yml +1 -1
  12. package/.github/workflows/draft-pr.yml +2 -2
  13. package/.github/workflows/release-pr.yml +4 -4
  14. package/.github/workflows/release.yml +17 -29
  15. package/.github/workflows/security.yml +24 -19
  16. package/.github/workflows/security_self-ci.yml +1 -1
  17. package/.github/workflows/test.yml +20 -20
  18. package/.github/workflows/test_self-ci.yml +1 -1
  19. package/AGENTS.md +13 -10
  20. package/CHANGELOG.md +28 -0
  21. package/README.md +19 -8
  22. package/docs/CONFIGURATION.md +11 -2
  23. package/docs/INITIALIZATION.md +9 -5
  24. package/docs/RELEASES.md +5 -0
  25. package/docs/WORKFLOWS.md +12 -5
  26. package/package.json +7 -3
  27. package/src/cli.mjs +29 -25
  28. package/src/commands/doctor.mjs +70 -0
  29. package/src/commands/sync.mjs +224 -0
  30. package/src/lib/config.mjs +38 -0
  31. package/src/lib/profile.mjs +114 -0
  32. package/src/runtime.mjs +316 -0
  33. package/.github/scripts/bootstrap.sh +0 -21
  34. package/.github/scripts/changed-files.sh +0 -96
  35. package/.github/scripts/ci.sh +0 -641
  36. package/.github/scripts/codeql-languages.sh +0 -91
  37. package/.github/scripts/doctor.sh +0 -98
  38. package/.github/scripts/format-fast-path.sh +0 -80
  39. package/.github/scripts/init-repo.sh +0 -264
  40. package/.github/scripts/pre-commit.sh +0 -67
  41. package/.github/scripts/profile.sh +0 -186
  42. package/.github/scripts/security.sh +0 -214
  43. package/.github/scripts/sitecustomize.py +0 -17
  44. package/.github/scripts/sync-codeowners.sh +0 -76
  45. package/.github/scripts/sync-protection.sh +0 -138
  46. package/.github/scripts/sync-template.sh +0 -744
  47. package/.github/scripts/turbo-cache-probe.sh +0 -102
@@ -0,0 +1,316 @@
1
+ #!/usr/bin/env node
2
+ // @ts-check
3
+
4
+ import { appendFileSync, existsSync, readFileSync } from 'node:fs'
5
+ import { resolve } from 'node:path'
6
+ import { spawnSync } from 'node:child_process'
7
+ import { detectPackageManager, resolveProfile } from './lib/profile.mjs'
8
+ import { configured, readConfig } from './lib/config.mjs'
9
+
10
+ const root = process.cwd()
11
+ const config = readConfig(resolve(root, '.github/code-foundry.yml'))
12
+ const repoProfile = resolveProfile(root)
13
+ /** @type {string[]} */
14
+ const languages = configured(config.languages, repoProfile.languages).split(',').filter(Boolean)
15
+ const packageManager = configured(config.package_manager, detectPackageManager(root))
16
+ const output = process.env.GITHUB_OUTPUT
17
+
18
+ /** @param {string} language */
19
+ function hasLanguage(language) {
20
+ return languages.includes(language) || languages.includes('all')
21
+ }
22
+
23
+ /** @param {string} name */
24
+ function hasScript(name) {
25
+ return readPackage()?.scripts?.[name] !== undefined
26
+ }
27
+
28
+ function readPackage() {
29
+ try { return JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8')) } catch { return null }
30
+ }
31
+
32
+ /** @param {string} key @param {unknown} value */
33
+ function writeOutput(key, value) {
34
+ const line = `${key}=${typeof value === 'string' ? value : JSON.stringify(value)}\n`
35
+ if (output) requireWrite(output, line)
36
+ else console.log(line.trimEnd())
37
+ }
38
+
39
+ /** @param {string} file @param {string} content */
40
+ function requireWrite(file, content) {
41
+ appendFileSync(file, content)
42
+ }
43
+
44
+ /** @param {string} command */
45
+ function commandExists(command) {
46
+ return spawnSync(command, ['--version'], { stdio: 'ignore' }).status === 0
47
+ }
48
+
49
+ /** @param {string} command @param {string[]} [args] @param {Record<string, unknown>} [options] */
50
+ function run(command, args = [], options = {}) {
51
+ const result = spawnSync(command, args, { cwd: root, stdio: 'inherit', env: process.env, ...options })
52
+ if (result.error) throw result.error
53
+ if (result.status !== 0) process.exit(result.status ?? 1)
54
+ }
55
+
56
+ /** @param {string} command @param {string[]} [args] */
57
+ function capture(command, args = []) {
58
+ const result = spawnSync(command, args, { cwd: root, encoding: 'utf8', env: process.env })
59
+ return result.status === 0 ? result.stdout.trim() : ''
60
+ }
61
+
62
+ /** @param {string[]} args @returns {[string|null, string[]]} */
63
+ function packageCommand(args) {
64
+ switch (packageManager) {
65
+ case 'bun': return ['bun', args]
66
+ case 'pnpm': return ['pnpm', args]
67
+ case 'yarn': return ['yarn', args]
68
+ case 'npm': return ['npm', args]
69
+ default: return [null, args]
70
+ }
71
+ }
72
+
73
+ /** @param {string[]} names */
74
+ function runScript(names) {
75
+ const name = names.find((candidate) => hasScript(candidate))
76
+ if (!name) return false
77
+ const [manager, args] = packageCommand(['run', name])
78
+ if (!manager) return false
79
+ run(manager, args)
80
+ return true
81
+ }
82
+
83
+ /** @param {string} tool @param {string[]} [args] */
84
+ function runTool(tool, args = []) {
85
+ const [manager] = packageCommand([])
86
+ if (manager === 'bun') return run('bunx', ['--no-install', tool, ...args])
87
+ if (manager === 'pnpm') return run('pnpm', ['exec', tool, ...args])
88
+ if (manager === 'yarn') return run('yarn', ['exec', tool, ...args])
89
+ if (manager === 'npm') return run('npx', ['--no-install', tool, ...args])
90
+ return run(tool, args)
91
+ }
92
+
93
+ function install() {
94
+ if (existsSync(resolve(root, 'package.json'))) {
95
+ const lock = ['bun.lock', 'bun.lockb', 'pnpm-lock.yaml', 'yarn.lock', 'package-lock.json'].find((file) => existsSync(resolve(root, file)))
96
+ if (lock) {
97
+ /** @type {Record<string, [string, string[]]>} */
98
+ const commands = {
99
+ bun: ['bun', ['install', '--frozen-lockfile']],
100
+ pnpm: ['pnpm', ['install', '--frozen-lockfile', '--prefer-offline']],
101
+ yarn: ['yarn', ['install', '--immutable']],
102
+ npm: ['npm', ['ci', '--prefer-offline', '--no-audit', '--fund=false']],
103
+ }
104
+ const command = commands[packageManager]
105
+ if (command) run(command[0], command[1])
106
+ }
107
+ }
108
+ if (hasLanguage('python') && (existsSync(resolve(root, 'pyproject.toml')) || existsSync(resolve(root, 'requirements.txt')))) {
109
+ if (commandExists('uv') && existsSync(resolve(root, 'uv.lock'))) run('uv', ['sync', '--frozen'])
110
+ else if (!existsSync(resolve(root, '.venv'))) run('python', ['-m', 'venv', '.venv'])
111
+ }
112
+ if (hasLanguage('rust') && existsSync(resolve(root, 'Cargo.toml'))) run('cargo', ['fetch'])
113
+ }
114
+
115
+ /** @param {string} task */
116
+ function relevant(task) {
117
+ const js = hasLanguage('typescript') || hasLanguage('javascript')
118
+ const python = hasLanguage('python')
119
+ const rust = hasLanguage('rust')
120
+ if (task === 'format' || task === 'lint' || task === 'type_check' || task === 'build') return js || python || rust
121
+ if (['unit', 'integration', 'e2e', 'smoke'].includes(task)) return js || python || rust || hasLanguage('solidity')
122
+ return true
123
+ }
124
+
125
+ /** @param {string} ecosystem */
126
+ function hasDependencyManifest(ecosystem) {
127
+ if (ecosystem === 'javascript') {
128
+ const packageJson = readPackage()
129
+ return ['bun.lock', 'bun.lockb', 'pnpm-lock.yaml', 'yarn.lock', 'package-lock.json'].some((file) => existsSync(resolve(root, file))) ||
130
+ Boolean(packageJson && ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'].some((group) => Object.keys(packageJson[group] ?? {}).length))
131
+ }
132
+ if (ecosystem === 'rust') return existsSync(resolve(root, 'Cargo.toml'))
133
+ if (ecosystem === 'python') return existsSync(resolve(root, 'pyproject.toml')) || existsSync(resolve(root, 'uv.lock')) || capture('git', ['ls-files', '*requirements*.txt']) !== ''
134
+ return false
135
+ }
136
+
137
+ /** @param {string} task */
138
+ function ci(task) {
139
+ if (task === 'install') return install()
140
+ if (task === 'should_run' || task === 'task_profile') {
141
+ const selected = process.argv[3]
142
+ writeOutput('applicable', relevant(selected) ? 'true' : 'false')
143
+ writeOutput('javascript', (hasLanguage('typescript') || hasLanguage('javascript')) ? 'true' : 'false')
144
+ writeOutput('python', hasLanguage('python') ? 'true' : 'false')
145
+ writeOutput('rust', hasLanguage('rust') ? 'true' : 'false')
146
+ return
147
+ }
148
+ if (task === 'format') {
149
+ const scripted = runScript(['format:check', 'format', 'fmt'])
150
+ if (!scripted && (hasLanguage('typescript') || hasLanguage('javascript'))) runTool('prettier', ['--check', '.'])
151
+ if (hasLanguage('python')) runTool('ruff', ['format', '--check', '.'])
152
+ if (hasLanguage('rust')) run('cargo', ['fmt', '--check'])
153
+ return
154
+ }
155
+ if (task === 'lint') {
156
+ const scripted = runScript(['lint'])
157
+ if (!scripted && (hasLanguage('typescript') || hasLanguage('javascript'))) runTool('eslint', ['.'])
158
+ if (hasLanguage('python')) runTool('ruff', ['check', '.'])
159
+ if (hasLanguage('rust')) run('cargo', ['clippy', '--all-targets', '--', '-D', 'warnings'])
160
+ return
161
+ }
162
+ if (task === 'type_check') {
163
+ const scripted = runScript(['type-check', 'typecheck', 'type:check'])
164
+ if (!scripted && existsSync(resolve(root, 'tsconfig.json'))) runTool('tsc', ['--noEmit'])
165
+ if (hasLanguage('rust')) run('cargo', ['check', '--all-targets'])
166
+ return
167
+ }
168
+ if (task === 'build') {
169
+ const scripted = runScript(['build'])
170
+ if (!scripted && hasLanguage('rust')) run('cargo', ['build', '--all-targets'])
171
+ return
172
+ }
173
+ /** @type {Record<string, string[]>} */
174
+ const scriptsByTask = {
175
+ unit: ['test:unit', 'test:coverage', 'test'],
176
+ integration: ['test:integration'],
177
+ e2e: ['test:e2e', 'e2e'],
178
+ smoke: ['test:smoke', 'smoke'],
179
+ }
180
+ const scripts = scriptsByTask[task]
181
+ if (scripts) runScript(scripts)
182
+ if (hasLanguage('rust')) run('cargo', ['test'])
183
+ if (hasLanguage('python')) {
184
+ const python = existsSync(resolve(root, '.venv/bin/python')) ? resolve(root, '.venv/bin/python') : 'python'
185
+ run(python, ['-m', 'pytest', ...(task === 'integration' ? ['tests/integration'] : [])])
186
+ }
187
+ }
188
+
189
+ /** @param {string} task @param {string} ecosystem */
190
+ function security(task, ecosystem) {
191
+ if (task === 'profile') {
192
+ writeOutput('javascript', hasDependencyManifest('javascript') ? 'true' : 'false')
193
+ writeOutput('rust', hasDependencyManifest('rust') ? 'true' : 'false')
194
+ writeOutput('python', hasDependencyManifest('python') ? 'true' : 'false')
195
+ const requirements = capture('git', ['ls-files', '*requirements*.txt']).split('\n').filter(Boolean)
196
+ writeOutput('python_requirements', hasDependencyManifest('python') ? (requirements.length ? requirements : ['project']) : ['none'])
197
+ writeOutput('dependency_review', featureEnabled('dependency_review') ? 'true' : 'false')
198
+ return
199
+ }
200
+ if (task === 'should_run') {
201
+ writeOutput('applicable', hasDependencyManifest(ecosystem) ? 'true' : 'false')
202
+ return
203
+ }
204
+ if (ecosystem === 'javascript' && existsSync(resolve(root, 'package.json'))) {
205
+ const ignores = existsSync(resolve(root, '.github/security-audit-allowlist.txt'))
206
+ ? readFileSync(resolve(root, '.github/security-audit-allowlist.txt'), 'utf8').split(/\r?\n/).filter((line) => line && !line.startsWith('#'))
207
+ : []
208
+ /** @type {Record<string, [string, string[]]>} */
209
+ const commands = {
210
+ bun: ['bun', ['audit', ...ignores.flatMap((advisory) => ['--ignore', advisory])]],
211
+ pnpm: ['pnpm', ['audit', '--audit-level', 'high']],
212
+ yarn: ['yarn', ['npm', 'audit', '--all', '--recursive']],
213
+ npm: ['npm', ['audit', '--audit-level=high']],
214
+ }
215
+ const command = commands[packageManager]
216
+ if (command) run(command[0], command[1])
217
+ } else if (ecosystem === 'rust' && existsSync(resolve(root, 'Cargo.toml'))) {
218
+ if (!commandExists('cargo-audit')) run('cargo', ['install', 'cargo-audit', '--locked', '--quiet'])
219
+ run('cargo', ['audit'])
220
+ } else if (ecosystem === 'python' && hasDependencyManifest('python')) {
221
+ const requirement = process.env.REPO_FOUNDRY_PYTHON_REQUIREMENT
222
+ const auditArgs = requirement && !['project', 'none'].includes(requirement) ? ['-r', requirement] : []
223
+ if (commandExists('uv')) run('uv', ['tool', 'run', '--from', 'pip-audit==2.10.1', 'pip-audit', ...auditArgs])
224
+ else {
225
+ run('python', ['-m', 'pip', 'install', '--quiet', 'pip-audit==2.10.1'])
226
+ run('python', ['-m', 'pip_audit', ...auditArgs])
227
+ }
228
+ }
229
+ }
230
+
231
+ /** @param {string} key */
232
+ function featureEnabled(key) {
233
+ const policy = config[key] ?? 'auto'
234
+ if (policy === 'false') return false
235
+ if (policy === 'true') return true
236
+ return isPublicRepository()
237
+ }
238
+
239
+ function isPublicRepository() {
240
+ const visibility = process.env.REPO_FOUNDRY_VISIBILITY
241
+ return visibility ? visibility === 'public' : process.env.REPO_FOUNDRY_PRIVATE !== 'true'
242
+ }
243
+
244
+ function codeql() {
245
+ const enabled = featureEnabled('codeql') &&
246
+ (isPublicRepository() || process.env.REPO_FOUNDRY_CODE_SECURITY === 'enabled')
247
+ writeOutput('enabled', enabled ? 'true' : 'false')
248
+ if (!enabled) {
249
+ writeOutput('languages', [])
250
+ for (const language of ['actions', 'javascript', 'python', 'rust']) {
251
+ writeOutput(`${language}_available`, 'false')
252
+ writeOutput(`${language}_changed`, 'false')
253
+ writeOutput(`${language}_build_mode`, 'none')
254
+ }
255
+ return
256
+ }
257
+ const available = []
258
+ if (existsSync(resolve(root, '.github/workflows'))) available.push('actions')
259
+ if (hasLanguage('typescript') || hasLanguage('javascript')) available.push('javascript-typescript')
260
+ if (hasLanguage('python')) available.push('python')
261
+ if (hasLanguage('rust')) available.push('rust')
262
+ const changed = capture('git', ['diff', '--name-only', process.env.CODEQL_BASE_SHA || 'HEAD^', process.env.GITHUB_SHA || 'HEAD']).split('\n').filter(Boolean)
263
+ const languagesJson = available.map((language) => ({ language, name: language === 'javascript-typescript' ? 'TypeScript' : language[0].toUpperCase() + language.slice(1), 'build-mode': 'none', changed: changed.length === 0 || changed.some((file) => fileMatches(language, file)) }))
264
+ writeOutput('languages', languagesJson)
265
+ for (const language of ['actions', 'javascript-typescript', 'python', 'rust']) {
266
+ const entry = languagesJson.find((item) => item.language === language)
267
+ const prefix = language === 'javascript-typescript' ? 'javascript' : language
268
+ writeOutput(`${prefix}_available`, entry ? 'true' : 'false')
269
+ writeOutput(`${prefix}_changed`, entry?.changed ? 'true' : 'false')
270
+ writeOutput(`${prefix}_build_mode`, entry?.['build-mode'] ?? 'none')
271
+ }
272
+ }
273
+
274
+ /** @param {string} language @param {string} file */
275
+ function fileMatches(language, file) {
276
+ if (language === 'actions') return file.startsWith('.github/workflows/') || file.endsWith('action.yml')
277
+ if (language === 'javascript-typescript') return /\.(js|jsx|mjs|cjs|ts|tsx|mts|cts)$/.test(file) || /(^|\/)(package\.json|tsconfig[^/]*\.json|(?:bun|pnpm|yarn|package-lock)\.lock)$/.test(file)
278
+ if (language === 'python') return /\.py$|(^|\/)(pyproject\.toml|requirements[^/]*\.txt|setup\.py|Pipfile\.lock|poetry\.lock)$/.test(file)
279
+ return /\.rs$|(^|\/)Cargo\.(toml|lock)$/.test(file)
280
+ }
281
+
282
+ /** @param {string} command */
283
+ function printProfile(command) {
284
+ if (command === 'get') {
285
+ const key = process.argv[3]
286
+ console.log(config[key] ?? (key === 'languages' ? languages.join(',') : key === 'package_manager' ? packageManager : ''))
287
+ return
288
+ }
289
+ writeOutput('languages', languages.join(','))
290
+ writeOutput('package_manager', packageManager)
291
+ writeOutput('release_type', config.release_type ?? 'auto')
292
+ writeOutput('npm_publish', config.npm_publish ?? 'false')
293
+ }
294
+
295
+ function preCommit() {
296
+ const changed = capture('git', ['diff', '--cached', '--name-only'])
297
+ if (!changed) return
298
+ const check = spawnSync('git', ['diff', '--cached', '--check'], { cwd: root, stdio: 'inherit' })
299
+ if (check.status !== 0) process.exit(check.status ?? 1)
300
+ if (/\.(js|jsx|ts|tsx|json|md|mdx|yml|yaml)$/.test(changed)) { ci('format'); ci('lint') }
301
+ if (/\.rs$|(^|\/)Cargo\.toml$/.test(changed)) { run('cargo', ['fmt', '--check']); run('cargo', ['clippy', '--all-targets', '--', '-D', 'warnings']) }
302
+ if (/\.py$|(^|\/)(pyproject\.toml|requirements[^/]*\.txt)$/.test(changed)) { runTool('ruff', ['format', '--check', '.']); runTool('ruff', ['check', '.']) }
303
+ }
304
+
305
+ const [area, task, ecosystem] = process.argv.slice(2)
306
+ try {
307
+ if (area === 'ci') ci(task)
308
+ else if (area === 'security') security(task, ecosystem)
309
+ else if (area === 'codeql') codeql()
310
+ else if (area === 'profile') printProfile(task)
311
+ else if (area === 'pre-commit') preCommit()
312
+ else throw new Error(`Unknown runtime command: ${area || '(missing)'}`)
313
+ } catch (error) {
314
+ console.error(error instanceof Error ? error.message : String(error))
315
+ process.exitCode = 1
316
+ }
@@ -1,21 +0,0 @@
1
- #!/usr/bin/env bash
2
- set -euo pipefail
3
-
4
- git config core.hooksPath .githooks
5
-
6
- if command -v mise >/dev/null 2>&1; then
7
- mise trust --yes .mise.toml >/dev/null 2>&1 || true
8
- if [ -f .mise.toml ] && [ ! -f mise.lock ]; then
9
- if MISE_TRUSTED_CONFIG_PATHS="$PWD" mise lock >/dev/null 2>&1; then
10
- printf '%s\n' 'Initialized mise.lock for deterministic CI tool installs.'
11
- else
12
- printf '%s\n' 'Warning: mise.lock could not be generated; continuing with pinned tool resolution.' >&2
13
- fi
14
- fi
15
- mise install
16
- else
17
- printf '%s\n' "mise is not installed; install it from https://mise.jdx.dev/ and rerun this script." >&2
18
- exit 1
19
- fi
20
-
21
- bash .github/scripts/doctor.sh
@@ -1,96 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- # Shared pull-request change detection. A failed or incomplete diff must be
4
- # treated as relevant so checks never become silently optional.
5
- repo_foundry_changed_files() {
6
- if [ "${REPO_FOUNDRY_CHANGED_FILES_READY:-false}" = true ]; then
7
- return 0
8
- fi
9
-
10
- local base_sha="${REPO_FOUNDRY_BASE_SHA:-}"
11
- local head_sha="${GITHUB_SHA:-HEAD}"
12
- local changed_files=""
13
-
14
- if [ -n "$base_sha" ] && [ "$base_sha" != "0000000000000000000000000000000000000000" ]; then
15
- if ! git cat-file -e "$base_sha^{commit}" 2>/dev/null; then
16
- git fetch --no-tags --filter=blob:none --depth=1 origin "$base_sha" >/dev/null 2>&1 || return 1
17
- fi
18
- changed_files="$(git diff --name-only "$base_sha" "$head_sha" 2>/dev/null || true)"
19
- else
20
- changed_files="$(git diff --name-only HEAD^ HEAD 2>/dev/null || true)"
21
- fi
22
-
23
- [ -n "$changed_files" ] || return 1
24
- REPO_FOUNDRY_CHANGED_FILES="$changed_files"
25
- REPO_FOUNDRY_CHANGED_FILES_READY=true
26
- }
27
-
28
- repo_foundry_governance_only() {
29
- case "${GITHUB_EVENT_NAME:-}" in
30
- pull_request|push) ;;
31
- *) return 1 ;;
32
- esac
33
-
34
- local changed_files=""
35
-
36
- repo_foundry_changed_files || return 1
37
- changed_files="$REPO_FOUNDRY_CHANGED_FILES"
38
-
39
- # An unavailable or empty diff is not evidence that a PR is documentation
40
- # only. Continue with the full check in that case.
41
- while IFS= read -r file; do
42
- case "$file" in
43
- README|README.*|LICENSE|NOTICE|.github/CODEOWNERS|.github/CODE_OF_CONDUCT.md|\
44
- .github/CONTRIBUTING.md|.github/PULL_REQUEST_TEMPLATE.md|.github/SECURITY.md|\
45
- .github/ISSUE_TEMPLATE/*)
46
- ;;
47
- *) return 1 ;;
48
- esac
49
- done <<< "$changed_files"
50
-
51
- return 0
52
- }
53
-
54
- repo_foundry_pr_docs_only() {
55
- repo_foundry_governance_only
56
- }
57
-
58
- # Return success when an ordinary push or pull request changed no dependency or
59
- # audit inputs for the requested ecosystem. Scheduled and manual runs, plus
60
- # unknown or unavailable diffs, fail open to a full security check.
61
- repo_foundry_pr_dependencies_unchanged() {
62
- local ecosystem="${1:-all}"
63
- case "${GITHUB_EVENT_NAME:-}" in
64
- pull_request|push) ;;
65
- *) return 1 ;;
66
- esac
67
-
68
- local changed_files=""
69
- repo_foundry_changed_files || return 1
70
- changed_files="$REPO_FOUNDRY_CHANGED_FILES"
71
-
72
- while IFS= read -r file; do
73
- case "$file" in
74
- .github/workflows/security.yml|.github/scripts/security.sh|.github/scripts/changed-files.sh|\
75
- .github/actions/setup/action.yml|.github/code-foundry.yml|.mise.toml|mise.lock|\
76
- .github/security-audit-allowlist.txt)
77
- return 1
78
- ;;
79
- package.json|*/package.json|bun.lock|bun.lockb|*/bun.lock|*/bun.lockb|\
80
- pnpm-lock.yaml|*/pnpm-lock.yaml|yarn.lock|*/yarn.lock|package-lock.json|*/package-lock.json|\
81
- .npmrc|*/.npmrc|.yarnrc*|*/.yarnrc*|.pnpmfile.cjs|*/.pnpmfile.cjs)
82
- case "$ecosystem" in javascript|all) return 1 ;; esac
83
- ;;
84
- Cargo.toml|*/Cargo.toml|Cargo.lock|*/Cargo.lock|.cargo/*|*/.cargo/*)
85
- case "$ecosystem" in rust|all) return 1 ;; esac
86
- ;;
87
- pyproject.toml|*/pyproject.toml|requirements*.txt|*/requirements*.txt|\
88
- setup.py|*/setup.py|setup.cfg|*/setup.cfg|Pipfile|*/Pipfile|Pipfile.lock|*/Pipfile.lock|\
89
- poetry.lock|*/poetry.lock|uv.lock|*/uv.lock)
90
- case "$ecosystem" in python|all) return 1 ;; esac
91
- ;;
92
- esac
93
- done <<< "$changed_files"
94
-
95
- return 0
96
- }