code-foundry 1.5.4 → 1.6.1
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/CONTRIBUTING.md +2 -2
- package/.github/actions/setup/action.yml +2 -1
- package/.github/code-foundry.yml +3 -0
- package/.github/workflows/test.yml +70 -0
- package/.github/workflows/validation.yml +6 -0
- package/.github/workflows/validation_audit_self-ci.yml +43 -0
- package/.github/workflows/validation_self-ci.yml +5 -8
- package/AGENTS.md +2 -1
- package/CHANGELOG.md +14 -0
- package/docs/CONFIGURATION.md +22 -1
- package/docs/WORKFLOWS.md +1 -1
- package/package.json +1 -1
- package/src/commands/sync.mjs +3 -0
- package/src/lib/profile.mjs +1 -0
- package/src/runtime.mjs +37 -0
package/.github/CONTRIBUTING.md
CHANGED
|
@@ -19,7 +19,7 @@ Agents must follow these rules before changing code:
|
|
|
19
19
|
3. Preserve user-owned changes. Never discard or overwrite unrelated work.
|
|
20
20
|
4. Branch from `staging` and target pull requests at `staging`; do not work directly on `main`.
|
|
21
21
|
5. Keep the change focused. Do not expand scope without documenting why.
|
|
22
|
-
6. Run the applicable format, lint, type-check, build, unit, integration, E2E, smoke, and security checks.
|
|
22
|
+
6. Run the applicable format, lint, type-check, build, unit, performance, integration, E2E, smoke, and security checks.
|
|
23
23
|
7. Report exact validation results, skipped checks, known limitations, and remaining risks.
|
|
24
24
|
8. Never commit secrets, credentials, local environment files, generated artifacts, or machine-specific paths.
|
|
25
25
|
|
|
@@ -163,7 +163,7 @@ Keep pull requests focused and reviewable. Include screenshots or recordings for
|
|
|
163
163
|
| Push to `staging` | Promotion PR workflow; canonical validation waits for the PR event |
|
|
164
164
|
| Push to `main` | Release workflow; canonical validation already ran on the merged PR |
|
|
165
165
|
|
|
166
|
-
|
|
166
|
+
Pull-request validation keys concurrency by event and pull-request head, so a newer update cancels its superseded run. Scheduled and manual audits use a separate caller pinned to the protected default branch; this prevents caller-selected runtime code from executing with default-branch cache access. Both callers use the mode-aware orchestrator, which fans out only the required jobs and concludes with the stable aggregate gate.
|
|
167
167
|
|
|
168
168
|
Required checks are enforced by branch protection rulesets/branch protection. Do not duplicate their checklists in the pull request description; document validation commands and results instead.
|
|
169
169
|
|
|
@@ -129,6 +129,7 @@ runs:
|
|
|
129
129
|
integration: ['test:integration'],
|
|
130
130
|
e2e: ['test:e2e', 'e2e'],
|
|
131
131
|
smoke: ['test:smoke', 'smoke'],
|
|
132
|
+
performance: ['performance:check', 'perf:check'],
|
|
132
133
|
}[task] || [];
|
|
133
134
|
const selected = candidates.find((name) => scripts[name]);
|
|
134
135
|
const usesTurbo = Boolean(selected && /\bturbo(?:\s|$)/.test(scripts[selected]));
|
|
@@ -441,7 +442,7 @@ runs:
|
|
|
441
442
|
- name: Install native test libraries
|
|
442
443
|
if: >-
|
|
443
444
|
inputs.install == 'true' &&
|
|
444
|
-
inputs.task == 'unit' &&
|
|
445
|
+
(inputs.task == 'unit' || inputs.task == 'performance') &&
|
|
445
446
|
hashFiles('**/package.json') != '' &&
|
|
446
447
|
steps.profile.outputs.javascript == 'true'
|
|
447
448
|
shell: bash
|
package/.github/code-foundry.yml
CHANGED
|
@@ -20,6 +20,7 @@ merge_strategy: rebase
|
|
|
20
20
|
release_merge_strategy: rebase
|
|
21
21
|
runner: ubuntu-latest
|
|
22
22
|
unit_runner: ubuntu-slim
|
|
23
|
+
performance_runner: ubuntu-latest
|
|
23
24
|
cache_packages: auto
|
|
24
25
|
cache_build: auto
|
|
25
26
|
coverage_minimum: 80
|
|
@@ -38,4 +39,6 @@ opencode_security: false
|
|
|
38
39
|
sync_mode: overlay
|
|
39
40
|
custom_workflows: preserve
|
|
40
41
|
staging_validation_mode: fast
|
|
42
|
+
performance: auto
|
|
43
|
+
performance_command:
|
|
41
44
|
opencode_security_model:
|
|
@@ -23,6 +23,11 @@ on:
|
|
|
23
23
|
required: false
|
|
24
24
|
type: string
|
|
25
25
|
default: ubuntu-slim
|
|
26
|
+
performance-runner:
|
|
27
|
+
description: Runner used by deterministic performance regression checks.
|
|
28
|
+
required: false
|
|
29
|
+
type: string
|
|
30
|
+
default: ubuntu-latest
|
|
26
31
|
unit-only:
|
|
27
32
|
description: Run only the unit-test subset; skip integration, E2E, and smoke jobs.
|
|
28
33
|
required: false
|
|
@@ -117,6 +122,71 @@ jobs:
|
|
|
117
122
|
if-no-files-found: ignore
|
|
118
123
|
retention-days: 14
|
|
119
124
|
|
|
125
|
+
performance:
|
|
126
|
+
name: Performance
|
|
127
|
+
if: vars.CI_BILLING_PAUSED != 'true'
|
|
128
|
+
runs-on: ${{ inputs.performance-runner }}
|
|
129
|
+
timeout-minutes: 30
|
|
130
|
+
steps:
|
|
131
|
+
- name: Checkout
|
|
132
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
133
|
+
with:
|
|
134
|
+
persist-credentials: false
|
|
135
|
+
fetch-depth: 2
|
|
136
|
+
- name: Runtime
|
|
137
|
+
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
138
|
+
with:
|
|
139
|
+
persist-credentials: false
|
|
140
|
+
repository: ${{ inputs.runtime-repository }}
|
|
141
|
+
ref: ${{ inputs.runtime-ref }}
|
|
142
|
+
path: .github/.code-foundry
|
|
143
|
+
sparse-checkout: |
|
|
144
|
+
.github/actions
|
|
145
|
+
src/lib
|
|
146
|
+
src/runtime.mjs
|
|
147
|
+
- name: Install runtime
|
|
148
|
+
run: |
|
|
149
|
+
mkdir -p .github/actions
|
|
150
|
+
mv .github/.code-foundry "$RUNNER_TEMP/code-foundry"
|
|
151
|
+
cp -R "$RUNNER_TEMP/code-foundry/.github/actions/." .github/actions/
|
|
152
|
+
- name: Detect
|
|
153
|
+
id: applicability
|
|
154
|
+
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs ci task_profile performance >> "$GITHUB_OUTPUT"
|
|
155
|
+
- name: Setup
|
|
156
|
+
if: steps.applicability.outputs.applicable == 'true'
|
|
157
|
+
uses: ./.github/actions/setup
|
|
158
|
+
with:
|
|
159
|
+
install: true
|
|
160
|
+
install-javascript: ${{ steps.applicability.outputs.javascript == 'true' }}
|
|
161
|
+
install-python: ${{ steps.applicability.outputs.python == 'true' }}
|
|
162
|
+
install-rust: ${{ steps.applicability.outputs.rust == 'true' }}
|
|
163
|
+
cache-build: false
|
|
164
|
+
cache-environment: false
|
|
165
|
+
cache-save: false
|
|
166
|
+
cache-packages: ${{ vars.REPO_FOUNDRY_CACHE_PACKAGES || 'auto' }}
|
|
167
|
+
task: performance
|
|
168
|
+
task-javascript: ${{ steps.applicability.outputs.javascript }}
|
|
169
|
+
task-python: ${{ steps.applicability.outputs.python }}
|
|
170
|
+
task-rust: ${{ steps.applicability.outputs.rust }}
|
|
171
|
+
- name: Performance
|
|
172
|
+
if: steps.applicability.outputs.applicable == 'true'
|
|
173
|
+
run: node $RUNNER_TEMP/code-foundry/src/runtime.mjs ci performance
|
|
174
|
+
- name: Upload performance results
|
|
175
|
+
if: >-
|
|
176
|
+
always() &&
|
|
177
|
+
steps.applicability.outputs.applicable == 'true' &&
|
|
178
|
+
hashFiles('artifacts/performance/**', 'performance-results.json', 'performance-results/**') != ''
|
|
179
|
+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
|
|
180
|
+
with:
|
|
181
|
+
name: performance-${{ github.run_id }}
|
|
182
|
+
path: |
|
|
183
|
+
artifacts/performance/**
|
|
184
|
+
performance-results.json
|
|
185
|
+
performance-results/**
|
|
186
|
+
compression-level: 1
|
|
187
|
+
if-no-files-found: ignore
|
|
188
|
+
retention-days: 14
|
|
189
|
+
|
|
120
190
|
integration:
|
|
121
191
|
name: Integration
|
|
122
192
|
if: vars.CI_BILLING_PAUSED != 'true' && inputs.unit-only != true
|
|
@@ -32,6 +32,11 @@ on:
|
|
|
32
32
|
required: false
|
|
33
33
|
type: string
|
|
34
34
|
default: ubuntu-slim
|
|
35
|
+
performance-runner:
|
|
36
|
+
description: Runner used by deterministic performance regression checks.
|
|
37
|
+
required: false
|
|
38
|
+
type: string
|
|
39
|
+
default: ubuntu-latest
|
|
35
40
|
security-runner:
|
|
36
41
|
description: Runner used by Security jobs.
|
|
37
42
|
required: false
|
|
@@ -94,6 +99,7 @@ jobs:
|
|
|
94
99
|
runtime-ref: ${{ inputs.runtime-ref }}
|
|
95
100
|
runner: ${{ inputs.test-runner }}
|
|
96
101
|
unit-runner: ${{ inputs.unit-runner }}
|
|
102
|
+
performance-runner: ${{ inputs.performance-runner }}
|
|
97
103
|
unit-only: ${{ inputs.mode == 'fast' }}
|
|
98
104
|
secrets:
|
|
99
105
|
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: Code Foundry Audit
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
schedule:
|
|
5
|
+
- cron: '31 6 * * 1'
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions: {}
|
|
9
|
+
|
|
10
|
+
concurrency:
|
|
11
|
+
group: code-foundry-audit-${{ github.event_name }}
|
|
12
|
+
cancel-in-progress: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
# Default-branch-capable events must not call the local reusable workflow:
|
|
16
|
+
# a pull request could otherwise change that workflow and feed an untrusted
|
|
17
|
+
# runtime ref into steps that can populate the protected branch cache. Use
|
|
18
|
+
# the protected default branch for both workflow code and runtime code.
|
|
19
|
+
validation:
|
|
20
|
+
name: Validation
|
|
21
|
+
if: vars.CI_BILLING_PAUSED != 'true'
|
|
22
|
+
permissions:
|
|
23
|
+
actions: read
|
|
24
|
+
contents: read
|
|
25
|
+
packages: read
|
|
26
|
+
security-events: write
|
|
27
|
+
uses: 0xPlayerOne/code-foundry/.github/workflows/validation.yml@main
|
|
28
|
+
with:
|
|
29
|
+
mode: audit
|
|
30
|
+
runtime-repository: 0xPlayerOne/code-foundry
|
|
31
|
+
runtime-ref: main
|
|
32
|
+
ci-runner: ubuntu-latest
|
|
33
|
+
test-runner: ubuntu-latest
|
|
34
|
+
unit-runner: ubuntu-slim
|
|
35
|
+
performance-runner: ubuntu-latest
|
|
36
|
+
security-runner: ubuntu-slim
|
|
37
|
+
codeql-runner: ubuntu-latest
|
|
38
|
+
rust-shards: '["all"]'
|
|
39
|
+
rust-threads: '1'
|
|
40
|
+
rust-max-parallel: 1
|
|
41
|
+
secrets:
|
|
42
|
+
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
|
43
|
+
NEXTAUTH_SECRET: ${{ secrets.NEXTAUTH_SECRET }}
|
|
@@ -8,16 +8,12 @@ on:
|
|
|
8
8
|
- synchronize
|
|
9
9
|
- reopened
|
|
10
10
|
- ready_for_review
|
|
11
|
-
schedule:
|
|
12
|
-
- cron: '31 6 * * 1'
|
|
13
|
-
workflow_dispatch:
|
|
14
11
|
|
|
15
12
|
# Default every caller job to no repository permissions. Individual jobs grant
|
|
16
13
|
# only the scopes their own validation path consumes.
|
|
17
14
|
permissions: {}
|
|
18
15
|
|
|
19
|
-
# Superseded PR updates cancel the previous run
|
|
20
|
-
# are keyed by event so periodic audits and manual runs stay independent.
|
|
16
|
+
# Superseded PR updates cancel the previous run.
|
|
21
17
|
concurrency:
|
|
22
18
|
group: code-foundry-validation-${{ github.event_name }}-${{ github.event.pull_request.head.repo.full_name || github.repository }}-${{ github.event.pull_request.head.ref || github.ref_name }}
|
|
23
19
|
cancel-in-progress: true
|
|
@@ -77,12 +73,13 @@ jobs:
|
|
|
77
73
|
mode: ${{ needs.mode.outputs.mode }}
|
|
78
74
|
runtime-repository: 0xPlayerOne/code-foundry
|
|
79
75
|
# Pull requests validate the proposed runtime commit. Scheduled and
|
|
80
|
-
# manually dispatched audits
|
|
81
|
-
# selected
|
|
82
|
-
runtime-ref: ${{ github.
|
|
76
|
+
# manually dispatched audits are isolated in validation_audit_self-ci.yml
|
|
77
|
+
# so this caller-selected ref never runs with default-branch cache access.
|
|
78
|
+
runtime-ref: ${{ github.sha }}
|
|
83
79
|
ci-runner: ubuntu-latest
|
|
84
80
|
test-runner: ubuntu-latest
|
|
85
81
|
unit-runner: ubuntu-slim
|
|
82
|
+
performance-runner: ubuntu-latest
|
|
86
83
|
security-runner: ubuntu-slim
|
|
87
84
|
codeql-runner: ubuntu-latest
|
|
88
85
|
rust-shards: '["all"]'
|
package/AGENTS.md
CHANGED
|
@@ -120,6 +120,7 @@ node src/runtime.mjs ci unit
|
|
|
120
120
|
node src/runtime.mjs ci integration
|
|
121
121
|
node src/runtime.mjs ci e2e
|
|
122
122
|
node src/runtime.mjs ci smoke
|
|
123
|
+
node src/runtime.mjs ci performance
|
|
123
124
|
Security and dependency audits run through the GitHub Security workflow.
|
|
124
125
|
```
|
|
125
126
|
|
|
@@ -138,7 +139,7 @@ If a check cannot run, state the exact reason. A skipped check is not a passing
|
|
|
138
139
|
## Tests and coverage
|
|
139
140
|
|
|
140
141
|
- Add or update tests for behavior changes and regressions.
|
|
141
|
-
- Keep unit, integration, E2E, and smoke coverage in the suite where each applies.
|
|
142
|
+
- Keep unit, performance, integration, E2E, and smoke coverage in the suite where each applies.
|
|
142
143
|
- Preserve project-specific coverage thresholds; do not lower them to make CI green.
|
|
143
144
|
- Keep test data deterministic and remove secrets from logs and fixtures.
|
|
144
145
|
- Use the narrowest test command while iterating, then run the affected package or workspace suite.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.6.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.6.0...v1.6.1) (2026-09-08)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **ci:** isolate default-branch security audits ([5ea0914](https://github.com/0xPlayerOne/code-foundry/commit/5ea09146af9995f16d1ab4e9a73f14a13582da36))
|
|
9
|
+
|
|
10
|
+
## [1.6.0](https://github.com/0xPlayerOne/code-foundry/compare/v1.5.4...v1.6.0) (2026-09-08)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* **ci:** add shared performance validation ([#492](https://github.com/0xPlayerOne/code-foundry/issues/492)) ([ef12990](https://github.com/0xPlayerOne/code-foundry/commit/ef1299045b6d67e447def93e2096862cde64bbc7))
|
|
16
|
+
|
|
3
17
|
## [1.5.4](https://github.com/0xPlayerOne/code-foundry/compare/v1.5.3...v1.5.4) (2026-09-08)
|
|
4
18
|
|
|
5
19
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -36,6 +36,8 @@ repository manifests and source
|
|
|
36
36
|
| `package_manager` | `bun`, `pnpm`, `yarn`, `npm`, `none` | JavaScript setup |
|
|
37
37
|
| `toolchain` | `auto`, `native`, `mise` | Environment setup policy; defaults to `auto` |
|
|
38
38
|
| `staging_validation_mode` | `fast`, `audit` | Validation tier for pull requests targeting `staging`; defaults to `fast` |
|
|
39
|
+
| `performance` | `auto`, `true`, `false` | Run a deterministic performance task when a supported entrypoint exists; defaults to `auto` |
|
|
40
|
+
| `performance_command` | JSON string array | Command argv for non-package performance harnesses; package scripts take precedence |
|
|
39
41
|
| `features` | `all` or a list | Standard workflow callers |
|
|
40
42
|
| `codeql` | `auto`, `true`, `false` | CodeQL policy; public repositories default to enabled, non-public repositories default to disabled |
|
|
41
43
|
| `codeql_rust_shards` | JSON array of paths | Rust scan scopes; `["all"]` keeps the safe single full scan |
|
|
@@ -51,11 +53,30 @@ repository manifests and source
|
|
|
51
53
|
| `git_workflow` | `direct` (default), `staging-release` | Branch/release model; `direct` opens feature branches into `main`, `staging-release` promotes `staging` into `main` |
|
|
52
54
|
| `merge_strategy` | `rebase` | Promotion merge method for `staging` → `main`; only enforced by the `staging-release` topology |
|
|
53
55
|
| `release_merge_strategy` | `rebase`, `squash` (direct topology only) | Merge method for Release Please version PRs into `main`; release automation fails closed on anything else |
|
|
54
|
-
| `runner` fields | GitHub runner names | Per-workflow runner policy
|
|
56
|
+
| `runner` fields | GitHub runner names | Per-workflow runner policy, including `performance_runner` |
|
|
55
57
|
|
|
56
58
|
Supported features are `ci`, `codeql`, `security`, `test`, `draft-pr`,
|
|
57
59
|
`release-pr`, `release`, and `dependabot`.
|
|
58
60
|
|
|
61
|
+
## Performance validation
|
|
62
|
+
|
|
63
|
+
The shared Test workflow exposes a deterministic `Performance` job. In JavaScript
|
|
64
|
+
repositories it discovers `performance:check` first and `perf:check` second. Other
|
|
65
|
+
repositories can declare an argv array without shell interpolation:
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
performance: true
|
|
69
|
+
performance_command: '["python3","scripts/performance_audit.py","--check"]'
|
|
70
|
+
performance_runner: ubuntu-latest
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`performance: false` disables discovery. Performance budgets, fixtures, mock
|
|
74
|
+
providers, and live endpoint credentials remain repository-owned. The shared job
|
|
75
|
+
owns checkout, pinned setup, billing controls, concurrency, and artifact upload;
|
|
76
|
+
it uploads `artifacts/performance/**`, `performance-results.json`, or
|
|
77
|
+
`performance-results/**` when present. Network-dependent and post-deployment
|
|
78
|
+
checks should remain separate from this deterministic validation task.
|
|
79
|
+
|
|
59
80
|
## OpenCode Security opt-in and opt-out
|
|
60
81
|
|
|
61
82
|
`opencode_security` controls the optional OpenCode scan, and the generated
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -79,7 +79,7 @@ repositories can opt in or out without a code change.
|
|
|
79
79
|
| Workflow | Responsibility |
|
|
80
80
|
| ---------- | ------------------------------------------------------------- |
|
|
81
81
|
| CI | Format, lint, type-check, and build |
|
|
82
|
-
| Test | Unit, integration, E2E, and smoke tests
|
|
82
|
+
| Test | Unit, performance, integration, E2E, and smoke tests |
|
|
83
83
|
| Security | Profile, audits, and public-only Dependency Review |
|
|
84
84
|
| CodeQL | GitHub-native code scanning, kept separate from CI |
|
|
85
85
|
| Draft PR | Create/update development pull requests |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.6.1",
|
|
4
4
|
"description": "A fast, language-aware repository factory for agent-ready workflows, testing, security, and release automation.",
|
|
5
5
|
"homepage": "https://github.com/0xPlayerOne/code-foundry#readme",
|
|
6
6
|
"bugs": {
|
package/src/commands/sync.mjs
CHANGED
|
@@ -549,6 +549,7 @@ function renderWorkflow(content, config, repository, ref, rustCodeql) {
|
|
|
549
549
|
'security-runner': config.security_runner ?? config.runner,
|
|
550
550
|
'codeql-runner': config.codeql_runner ?? config.runner,
|
|
551
551
|
'unit-runner': config.unit_runner,
|
|
552
|
+
'performance-runner': config.performance_runner ?? config.test_runner ?? config.runner,
|
|
552
553
|
}
|
|
553
554
|
for (const [input, value] of Object.entries(runnerInputs)) {
|
|
554
555
|
if (!value) continue
|
|
@@ -1088,6 +1089,8 @@ function createDefaultConfig(root, source) {
|
|
|
1088
1089
|
...runners,
|
|
1089
1090
|
toolchain: 'auto',
|
|
1090
1091
|
staging_validation_mode: 'fast',
|
|
1092
|
+
performance: 'auto',
|
|
1093
|
+
performance_command: '',
|
|
1091
1094
|
prune_standard: 'false',
|
|
1092
1095
|
cache_packages: 'auto',
|
|
1093
1096
|
cache_build: 'auto',
|
package/src/lib/profile.mjs
CHANGED
|
@@ -129,6 +129,7 @@ export function recommendRunners(root) {
|
|
|
129
129
|
ci_runner: heavy ? 'ubuntu-latest' : 'ubuntu-slim',
|
|
130
130
|
test_runner: heavy ? 'ubuntu-latest' : 'ubuntu-slim',
|
|
131
131
|
unit_runner: heavy ? 'ubuntu-latest' : 'ubuntu-slim',
|
|
132
|
+
performance_runner: 'ubuntu-latest',
|
|
132
133
|
security_runner: 'ubuntu-slim',
|
|
133
134
|
codeql_runner: 'ubuntu-latest',
|
|
134
135
|
pr_runner: 'ubuntu-slim',
|
package/src/runtime.mjs
CHANGED
|
@@ -52,6 +52,29 @@ function readPackage() {
|
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
function performanceEnabled() {
|
|
56
|
+
return configured(config.performance, 'auto') !== 'false'
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function performanceCommand() {
|
|
60
|
+
const raw = configured(config.performance_command, '').trim()
|
|
61
|
+
if (!raw) return null
|
|
62
|
+
let command
|
|
63
|
+
try {
|
|
64
|
+
command = JSON.parse(raw)
|
|
65
|
+
} catch {
|
|
66
|
+
throw new Error('performance_command must be a JSON array of command arguments.')
|
|
67
|
+
}
|
|
68
|
+
if (
|
|
69
|
+
!Array.isArray(command) ||
|
|
70
|
+
command.length === 0 ||
|
|
71
|
+
command.some((argument) => typeof argument !== 'string' || argument.length === 0)
|
|
72
|
+
) {
|
|
73
|
+
throw new Error('performance_command must be a non-empty JSON array of non-empty strings.')
|
|
74
|
+
}
|
|
75
|
+
return command
|
|
76
|
+
}
|
|
77
|
+
|
|
55
78
|
/** @param {string} task */
|
|
56
79
|
function validation(task) {
|
|
57
80
|
if (task === 'mode') {
|
|
@@ -271,7 +294,14 @@ function relevant(task) {
|
|
|
271
294
|
integration: ['test:integration'],
|
|
272
295
|
e2e: ['test:e2e', 'e2e'],
|
|
273
296
|
smoke: ['test:smoke', 'smoke'],
|
|
297
|
+
performance: ['performance:check', 'perf:check'],
|
|
274
298
|
}[task]
|
|
299
|
+
if (task === 'performance') {
|
|
300
|
+
if (!performanceEnabled()) return false
|
|
301
|
+
return Boolean(
|
|
302
|
+
(scripted && scripted.some((candidate) => hasScript(candidate))) || performanceCommand()
|
|
303
|
+
)
|
|
304
|
+
}
|
|
275
305
|
if (scripted && scripted.some((candidate) => hasScript(candidate)))
|
|
276
306
|
return packageManager !== 'none'
|
|
277
307
|
if (task === 'format' || task === 'lint' || task === 'type_check' || task === 'build') {
|
|
@@ -434,6 +464,13 @@ function ci(task) {
|
|
|
434
464
|
run('cargo', ['build', '--all-targets'])
|
|
435
465
|
return
|
|
436
466
|
}
|
|
467
|
+
if (task === 'performance') {
|
|
468
|
+
if (!performanceEnabled()) return
|
|
469
|
+
if (runScript(['performance:check', 'perf:check'])) return
|
|
470
|
+
const command = performanceCommand()
|
|
471
|
+
if (command) run(command[0], command.slice(1))
|
|
472
|
+
return
|
|
473
|
+
}
|
|
437
474
|
/** @type {Record<string, string[]>} */
|
|
438
475
|
const scriptsByTask = {
|
|
439
476
|
unit: ['test:unit', 'test:coverage', 'test'],
|