code-foundry 1.43.1 → 1.43.2
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/CHANGELOG.md +7 -0
- package/docs/CONFIGURATION.md +24 -23
- package/package.json +1 -1
- package/src/commands/sync.mjs +38 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.43.2](https://github.com/0xPlayerOne/code-foundry/compare/v1.43.1...v1.43.2) (2026-10-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* require candidate asset qualification before stable promotion ([#705](https://github.com/0xPlayerOne/code-foundry/issues/705)) ([f42e4f5](https://github.com/0xPlayerOne/code-foundry/commit/f42e4f5fb063ea22fa25791a13c75c90d41bf17a))
|
|
9
|
+
|
|
3
10
|
## [1.43.1](https://github.com/0xPlayerOne/code-foundry/compare/v1.43.0...v1.43.1) (2026-10-03)
|
|
4
11
|
|
|
5
12
|
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -115,29 +115,30 @@ See [Merge queue validation](merge-queues.md) before enabling it.
|
|
|
115
115
|
|
|
116
116
|
## Validation and quality
|
|
117
117
|
|
|
118
|
-
| Key
|
|
119
|
-
|
|
|
120
|
-
| `performance`
|
|
121
|
-
| `performance_command`
|
|
122
|
-
| `performance_profile`
|
|
123
|
-
| `performance_budget_file`
|
|
124
|
-
| `eval`
|
|
125
|
-
| `eval_command`
|
|
126
|
-
| `eval_report_file`
|
|
127
|
-
| `eval_budget_file`
|
|
128
|
-
| `eval_runner`
|
|
129
|
-
| `required_capabilities`
|
|
130
|
-
| `coverage_enforcement`
|
|
131
|
-
| `coverage_minimum`
|
|
132
|
-
| `coverage_metrics`
|
|
133
|
-
| `coverage_report`
|
|
134
|
-
| `filter_<task>`
|
|
135
|
-
| `rust_sccache`
|
|
136
|
-
| `rust_nextest`
|
|
137
|
-
| `e2e_shards`
|
|
138
|
-
| `release_batching_schedule`
|
|
139
|
-
| `release_batching_prerelease`
|
|
140
|
-
| `release_batching_soak_hours`
|
|
118
|
+
| Key | Values | Purpose |
|
|
119
|
+
| ----------------------------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
120
|
+
| `performance` | `auto`, `true`, `false` | Discover, require, or disable performance checks. |
|
|
121
|
+
| `performance_command` | JSON argv array or array of argv arrays | Ordered commands for a non-package performance harness. |
|
|
122
|
+
| `performance_profile` | empty or `node-package` | Shared package import, memory, archive, and dependency audit. |
|
|
123
|
+
| `performance_budget_file` | repository-relative path | Budget file for `node-package`; defaults to `performance-package-budgets.json`. |
|
|
124
|
+
| `eval` | `auto`, `true`, `false` | Discover, require, or disable the deterministic eval tier. |
|
|
125
|
+
| `eval_command` | JSON argv array | Explicit harness command when there is no `eval` package script. |
|
|
126
|
+
| `eval_report_file` | repository-relative path | Report validated against the eval contract; defaults to `eval-results/result.json`. |
|
|
127
|
+
| `eval_budget_file` | repository-relative path | Optional budget file; defaults to `eval-budgets.json`. |
|
|
128
|
+
| `eval_runner` | runner label | Runner for the `Validation / Eval` lane; defaults to the repository runner. Browser evals need a Chrome-capable runner such as `ubuntu-latest`. |
|
|
129
|
+
| `required_capabilities` | comma-separated task names | Fail closed when a required task or coverage evidence is unavailable. |
|
|
130
|
+
| `coverage_enforcement` | `auto`, `required`, `off` | Shared coverage-report policy. |
|
|
131
|
+
| `coverage_minimum` | `0`–`100` | Minimum percentage; defaults to `80`. |
|
|
132
|
+
| `coverage_metrics` | `lines`, `functions`, `branches`, `statements` | Metrics checked by the coverage gate. |
|
|
133
|
+
| `coverage_report` | comma-separated repository paths | Istanbul JSON summary or LCOV evidence files. |
|
|
134
|
+
| `filter_<task>` | comma-separated repository path globs | Skip a lane when no changed path matches; see [Lane path filters](#lane-path-filters). |
|
|
135
|
+
| `rust_sccache` | `true`, `false` | Install sccache and wrap rustc so compile artifacts survive manifest/lockfile churn. |
|
|
136
|
+
| `rust_nextest` | `true`, `false` | Install cargo-nextest and prefer `cargo nextest run` over `cargo test` in Rust test lanes. |
|
|
137
|
+
| `e2e_shards` | `1`–`8` | Fan the `Validation / Test / E2E` job into one runner per shard. The repository's `test:e2e`/`e2e` script receives `E2E_SHARD_INDEX` and `E2E_TOTAL_SHARDS` and partitions itself (Playwright takes `--shard=$E2E_SHARD_INDEX/$E2E_TOTAL_SHARDS`); each shard owns a runner-local test database, so shards stay isolated. |
|
|
138
|
+
| `release_batching_schedule` | five-field numeric cron | Batch Release Please into scheduled windows. Ordinary pushes skip the producer; release-PR squashes and manual dispatches still run. Batched releases are created privately as drafts and published with prerelease visibility atomically. Manual dispatches publish stable hotfixes. Absent, releases publish per merge. Requires a single root Release Please package. |
|
|
139
|
+
| `release_batching_prerelease` | `true`, `false` | Defaults to `true` with a schedule. Sync enables `draft` and `force-tag-creation` in Release Please; the producer publishes the draft with the selected visibility. `false` keeps scheduled releases stable-visible. |
|
|
140
|
+
| `release_batching_soak_hours` | `1`–`336` | Generate a daily promoter that promotes the newest prerelease when the oldest candidate since the last stable has soaked this many hours, stitching batch notes. Requires a batching schedule and prerelease publication. Set `STABLE_PROMOTION_HELD=true` in repository Actions variables to hold scheduled and manual promotion; `force` overrides the hold or soak, and `version` selects a plain semantic version. |
|
|
141
|
+
| `release_batching_qualification_workflow` | workflow filename (for example `release-assets.yml`) | Require the latest release-event run of this workflow for the candidate tag’s exact source commit to succeed before stable promotion. Requires a batching soak. Running, missing, failed, or cancelled runs hold promotion, including named and forced promotions; `force` only bypasses hold and soak. The promoter receives read-only Actions access. |
|
|
141
142
|
|
|
142
143
|
Supported task capabilities are `format`, `lint`, `type_check`, `build`, `unit`,
|
|
143
144
|
`integration`, `e2e`, `smoke`, `eval`, and `performance`. `coverage` is a policy
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-foundry",
|
|
3
|
-
"version": "1.43.
|
|
3
|
+
"version": "1.43.2",
|
|
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
|
@@ -754,6 +754,7 @@ on:
|
|
|
754
754
|
|
|
755
755
|
permissions:
|
|
756
756
|
contents: write
|
|
757
|
+
actions: read
|
|
757
758
|
|
|
758
759
|
concurrency:
|
|
759
760
|
group: promote-stable
|
|
@@ -769,6 +770,7 @@ jobs:
|
|
|
769
770
|
env:
|
|
770
771
|
GH_TOKEN: \${{ github.token }}
|
|
771
772
|
SOAK_HOURS: '__SOAK_HOURS__'
|
|
773
|
+
QUALIFICATION_WORKFLOW: '__QUALIFICATION_WORKFLOW__'
|
|
772
774
|
VERSION: \${{ inputs.version }}
|
|
773
775
|
FORCE: \${{ inputs.force }}
|
|
774
776
|
STABLE_PROMOTION_HELD: \${{ vars.STABLE_PROMOTION_HELD }}
|
|
@@ -777,6 +779,19 @@ jobs:
|
|
|
777
779
|
repo="$GITHUB_REPOSITORY"
|
|
778
780
|
summary="$GITHUB_STEP_SUMMARY"
|
|
779
781
|
|
|
782
|
+
# Force bypasses hold and soak, but never asset qualification.
|
|
783
|
+
require_qualification() {
|
|
784
|
+
[ -z "$QUALIFICATION_WORKFLOW" ] && return 0
|
|
785
|
+
local candidate_sha conclusion
|
|
786
|
+
candidate_sha="$(gh api "repos/$repo/commits/$1" --jq '.sha')" || return 1
|
|
787
|
+
[ -n "$candidate_sha" ] && [ "$candidate_sha" != "null" ] || return 1
|
|
788
|
+
conclusion="$(gh run list --repo "$repo" --workflow "$QUALIFICATION_WORKFLOW" --event release --commit "$candidate_sha" --limit 1 --json conclusion --jq '.[0].conclusion // "missing"')" || return 1
|
|
789
|
+
if [ "$conclusion" != "success" ]; then
|
|
790
|
+
echo "Asset qualification for $1 is $conclusion; holding stable promotion." | tee -a "$summary"
|
|
791
|
+
return 1
|
|
792
|
+
fi
|
|
793
|
+
}
|
|
794
|
+
|
|
780
795
|
# The repository variable applies equally to scheduled and manual runs.
|
|
781
796
|
if [ "$STABLE_PROMOTION_HELD" = "true" ] && [ "$FORCE" != "true" ]; then
|
|
782
797
|
echo "Stable promotion is held." | tee -a "$summary"
|
|
@@ -788,6 +803,10 @@ jobs:
|
|
|
788
803
|
echo "::error::version must be a plain semantic version" >&2
|
|
789
804
|
exit 1
|
|
790
805
|
fi
|
|
806
|
+
if ! require_qualification "v$VERSION"; then
|
|
807
|
+
echo "Qualification unavailable or unsuccessful; holding v$VERSION." | tee -a "$summary"
|
|
808
|
+
exit 0
|
|
809
|
+
fi
|
|
791
810
|
gh release edit "v$VERSION" --repo "$repo" --prerelease=false --latest
|
|
792
811
|
echo "Promoted v$VERSION to stable by name." | tee -a "$summary"
|
|
793
812
|
exit 0
|
|
@@ -833,6 +852,11 @@ jobs:
|
|
|
833
852
|
exit 0
|
|
834
853
|
fi
|
|
835
854
|
|
|
855
|
+
if ! require_qualification "$tip"; then
|
|
856
|
+
echo "Qualification unavailable or unsuccessful; holding $tip." | tee -a "$summary"
|
|
857
|
+
exit 0
|
|
858
|
+
fi
|
|
859
|
+
|
|
836
860
|
# Stitch the batch's notes oldest→newest so the stable release
|
|
837
861
|
# documents everything stable users are getting, not just the tip.
|
|
838
862
|
jq -r '.[] | "## " + .tag + "\\n\\n" + (.body // "")' <<<"$batch" > batch-notes.md
|
|
@@ -878,6 +902,16 @@ function validateReleaseBatchingConfig(config) {
|
|
|
878
902
|
`Unsupported release_batching_prerelease: ${config.release_batching_prerelease}; use true or false.`
|
|
879
903
|
)
|
|
880
904
|
}
|
|
905
|
+
if (config.release_batching_qualification_workflow) {
|
|
906
|
+
if (
|
|
907
|
+
!/^[A-Za-z0-9_.-]+\.ya?ml$/.test(config.release_batching_qualification_workflow) ||
|
|
908
|
+
!config.release_batching_soak_hours
|
|
909
|
+
) {
|
|
910
|
+
throw new Error(
|
|
911
|
+
'Unsupported release_batching_qualification_workflow: use a workflow filename with a batching soak.'
|
|
912
|
+
)
|
|
913
|
+
}
|
|
914
|
+
}
|
|
881
915
|
if (config.release_batching_soak_hours) {
|
|
882
916
|
const hours = Number(config.release_batching_soak_hours)
|
|
883
917
|
if (!Number.isInteger(hours) || hours < 1 || hours > 336) {
|
|
@@ -902,7 +936,10 @@ function validateReleaseBatchingConfig(config) {
|
|
|
902
936
|
export function renderPromoteStable(config) {
|
|
903
937
|
const soakHours = Number(config.release_batching_soak_hours ?? '')
|
|
904
938
|
if (!Number.isInteger(soakHours) || soakHours < 1 || soakHours > 336) return null
|
|
905
|
-
return PROMOTE_STABLE_TEMPLATE.replaceAll('__SOAK_HOURS__', String(soakHours))
|
|
939
|
+
return PROMOTE_STABLE_TEMPLATE.replaceAll('__SOAK_HOURS__', String(soakHours)).replaceAll(
|
|
940
|
+
'__QUALIFICATION_WORKFLOW__',
|
|
941
|
+
config.release_batching_qualification_workflow ?? ''
|
|
942
|
+
)
|
|
906
943
|
}
|
|
907
944
|
|
|
908
945
|
/**
|