code-foundry 0.37.0 → 0.37.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/.github/CONTRIBUTING.md +14 -14
- package/CHANGELOG.md +14 -0
- package/docs/RELEASES.md +5 -4
- package/docs/WORKFLOWS.md +5 -3
- package/package.json +1 -1
- package/src/commands/sync.mjs +10 -4
- package/src/lib/release-policy.mjs +10 -6
package/.github/CONTRIBUTING.md
CHANGED
|
@@ -153,15 +153,15 @@ Keep pull requests focused and reviewable. Include screenshots or recordings for
|
|
|
153
153
|
|
|
154
154
|
## Workflow and check behavior
|
|
155
155
|
|
|
156
|
-
| Event
|
|
157
|
-
|
|
|
158
|
-
| Pull request targeting `staging`
|
|
159
|
-
| Ordinary pull request targeting `main`
|
|
160
|
-
| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate`
|
|
161
|
-
| Scheduled or manual validation
|
|
162
|
-
| Push to a working branch
|
|
163
|
-
| Push to `staging`
|
|
164
|
-
| Push to `main`
|
|
156
|
+
| Event | Expected automation |
|
|
157
|
+
| -------------------------------------------------- | ------------------------------------------------------------------------------------- |
|
|
158
|
+
| Pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |
|
|
159
|
+
| Ordinary pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |
|
|
160
|
+
| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |
|
|
161
|
+
| Scheduled or manual validation | Full audit tier |
|
|
162
|
+
| Push to a working branch | Draft PR workflow |
|
|
163
|
+
| Push to `staging` | Promotion PR workflow; canonical validation waits for the PR event |
|
|
164
|
+
| Push to `main` | Release workflow; canonical validation already ran on the merged PR |
|
|
165
165
|
|
|
166
166
|
The single validation caller keys concurrency by event and pull-request head. A newer update to the same pull request cancels its superseded validation run; scheduled and manual audits remain independent. The mode-aware orchestrator fans out only the jobs required by that event and always concludes with the stable aggregate gate.
|
|
167
167
|
|
|
@@ -175,11 +175,11 @@ Security checks can be skipped when repository visibility or the GitHub plan doe
|
|
|
175
175
|
|
|
176
176
|
## Review and merge protocol
|
|
177
177
|
|
|
178
|
-
| Change
|
|
179
|
-
|
|
|
180
|
-
| Working branch
|
|
181
|
-
| `staging` → `main` promotion | `main`
|
|
182
|
-
| Release Please version PR
|
|
178
|
+
| Change | Target | Merge method | Merge gate |
|
|
179
|
+
| ---------------------------- | --------- | ----------------------------------------------- | --------------------------------------------------------- |
|
|
180
|
+
| Working branch | `staging` | Squash | All applicable required checks pass |
|
|
181
|
+
| `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |
|
|
182
|
+
| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |
|
|
183
183
|
|
|
184
184
|
Reviewers focus on correctness, security, maintainability, test coverage, operational impact, and compatibility. Authors remain responsible for responding to feedback and verifying the final commit.
|
|
185
185
|
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.37.2](https://github.com/0xPlayerOne/code-foundry/compare/v0.37.1...v0.37.2) (2026-08-23)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **ci:** stabilize runners and release reconciliation ([#387](https://github.com/0xPlayerOne/code-foundry/issues/387)) ([ea2c503](https://github.com/0xPlayerOne/code-foundry/commit/ea2c503cb6ea9b944ffa5b70ff7fbfc3d56d3a10))
|
|
9
|
+
|
|
10
|
+
## [0.37.1](https://github.com/0xPlayerOne/code-foundry/compare/v0.37.0...v0.37.1) (2026-08-08)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* **sync:** prettier-canonical CONTRIBUTING.md tables for both topologies ([af9137b](https://github.com/0xPlayerOne/code-foundry/commit/af9137bc788853ed97c4c17aef9848b7f9d15fbf))
|
|
16
|
+
|
|
3
17
|
## [0.37.0](https://github.com/0xPlayerOne/code-foundry/compare/v0.36.2...v0.37.0) (2026-08-07)
|
|
4
18
|
|
|
5
19
|
|
package/docs/RELEASES.md
CHANGED
|
@@ -57,8 +57,9 @@ reject any non-`rebase` `merge_strategy` only when `staging-release` is
|
|
|
57
57
|
configured, and always reject a non-`rebase` `release_merge_strategy`; the
|
|
58
58
|
release workflow fails closed instead of falling back to `merge`. Both keep
|
|
59
59
|
`main` fully linear, which is what makes the post-release reconciliation
|
|
60
|
-
possible
|
|
61
|
-
|
|
60
|
+
possible. The final branch trees are inspected before mutation; validated
|
|
61
|
+
main-only changes are inherited by `staging`, while unpromoted staging work is
|
|
62
|
+
replayed on top of `main`.
|
|
62
63
|
|
|
63
64
|
The `staging` → `main` reconciliation exists only in the `staging-release`
|
|
64
65
|
topology. Patch-equivalent divergence between `main` and `staging` is treated
|
|
@@ -67,8 +68,8 @@ as aligned. When `staging` has pending commits that are not yet represented on
|
|
|
67
68
|
detached worktree rooted at `main`, and then updates `staging` with an exact
|
|
68
69
|
`--force-with-lease` to prevent
|
|
69
70
|
unintended branch rewrites. There is no unconditional mirror force-push and no
|
|
70
|
-
fallback synchronization commit path.
|
|
71
|
-
entirely.
|
|
71
|
+
fallback synchronization commit path. Indeterminate history, replay conflicts,
|
|
72
|
+
and stale leases fail closed. `direct` repositories skip this step entirely.
|
|
72
73
|
|
|
73
74
|
`auto` selects a supported manifest. Use `simple` with `version.txt` for a
|
|
74
75
|
repository without a package manifest and `none` for a repository that should
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -97,9 +97,11 @@ it opens (or reuses) a generated `code-foundry/reconcile/main-to-staging`
|
|
|
97
97
|
pull request whose head contains the exact target tip (the `main` tip for a
|
|
98
98
|
fast-forward, the replay tip when staging-only commits are replayed) and whose
|
|
99
99
|
body documents the reconciliation. Reruns reuse the open pull request instead
|
|
100
|
-
of duplicating it
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
of duplicating it. Validated changes that landed directly on `main` are synced
|
|
101
|
+
back into `staging`; unpromoted staging commits are replayed on top. Indeterminate
|
|
102
|
+
history, replay conflicts, authentication errors, and ambiguous or stale pull
|
|
103
|
+
request state still fail the job closed, and exact-lease protection stays in
|
|
104
|
+
place for every direct push.
|
|
103
105
|
|
|
104
106
|
For this reconciliation path, maintainer PATs and administrator roles are not
|
|
105
107
|
authorized bypasses; the job deliberately authenticates with `github.token`,
|
package/package.json
CHANGED
package/src/commands/sync.mjs
CHANGED
|
@@ -361,6 +361,12 @@ function renderWorkflow(content, config, repository, ref, rustCodeql) {
|
|
|
361
361
|
rendered = rendered.replace(/^(\s+unit-runner:)\s+.*$/m, `$1 ${config.unit_runner}`)
|
|
362
362
|
}
|
|
363
363
|
if (workflow === 'validation') {
|
|
364
|
+
// The mode classifier is a normal runner job in the caller rather than a
|
|
365
|
+
// reusable-workflow input. Keep it on the configured default runner so
|
|
366
|
+
// consumers that cannot use ubuntu-slim do not fail before validation.
|
|
367
|
+
if (config.runner) {
|
|
368
|
+
rendered = rendered.replace(/^ mode:\n name: Mode\n runs-on:\s+.*$/m, ` mode:\n name: Mode\n runs-on: ${config.runner}`)
|
|
369
|
+
}
|
|
364
370
|
/** @type {Record<string, string|undefined>} */
|
|
365
371
|
const runnerInputs = {
|
|
366
372
|
'ci-runner': config.ci_runner ?? config.runner,
|
|
@@ -481,12 +487,12 @@ const DIRECT_DOC_REPLACEMENTS = {
|
|
|
481
487
|
'7. Push to the fork and open a pull request targeting `main`.',
|
|
482
488
|
],
|
|
483
489
|
[
|
|
484
|
-
'| Event
|
|
485
|
-
'| Event
|
|
490
|
+
'| Event | Expected automation |\n| -------------------------------------------------- | ------------------------------------------------------------------------------------- |\n| Pull request targeting `staging` | Fast validation: CI plus unit tests, ending in `Validation / Gate` |\n| Ordinary pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |\n| Scheduled or manual validation | Full audit tier |\n| Push to a working branch | Draft PR workflow |\n| Push to `staging` | Promotion PR workflow; canonical validation waits for the PR event |\n| Push to `main` | Release workflow; canonical validation already ran on the merged PR |\n',
|
|
491
|
+
'| Event | Expected automation |\n|------------------------------------------------------------------------------------------------------------------------------------------------|\n| Pull request targeting `main` | Audit validation: CI, full tests, Security, and CodeQL, ending in `Validation / Gate` |\n| Exact Release Please pull request targeting `main` | Release-policy validation only, ending in `Validation / Gate` |\n| Scheduled or manual validation | Full audit tier |\n| Push to a working branch | Draft PR workflow |\n| Push to `main` | Release workflow; canonical validation already ran on the merged PR |',
|
|
486
492
|
],
|
|
487
493
|
[
|
|
488
|
-
'| Change
|
|
489
|
-
'| Change
|
|
494
|
+
'| Change | Target | Merge method | Merge gate |\n| ---------------------------- | --------- | ----------------------------------------------- | --------------------------------------------------------- |\n| Working branch | `staging` | Squash | All applicable required checks pass |\n| `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |\n| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |\n',
|
|
495
|
+
'| Change | Target | Merge method | Merge gate |\n|----------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| Working branch | `main` | Squash | All applicable required checks pass |\n| Release Please version PR | `main` | Rebase (`release_merge_strategy`, fails closed) | Validation gate and release policy pass |',
|
|
490
496
|
],
|
|
491
497
|
[
|
|
492
498
|
'1. Create a focused branch from `staging`.',
|
|
@@ -220,7 +220,7 @@ function compareVersions(a, b) {
|
|
|
220
220
|
* Classify the relationship between main and staging using the final tree delta
|
|
221
221
|
* when available. Historical commit paths can include equivalent workflow or
|
|
222
222
|
* configuration changes that are no longer present in the branch delta, so the
|
|
223
|
-
* final trees are the source of truth for
|
|
223
|
+
* final trees are the source of truth for reconciliation. When
|
|
224
224
|
* directChangedPaths is supplied, unexpected paths in historical main-only
|
|
225
225
|
* commits are ignored only when they are absent from the final tree delta
|
|
226
226
|
* (their content is already identical in both branches); unexpected main-only
|
|
@@ -281,9 +281,9 @@ export function classifyReconciliation(input) {
|
|
|
281
281
|
}
|
|
282
282
|
if (!stagingOnlyCommits.length) {
|
|
283
283
|
return {
|
|
284
|
-
action: '
|
|
285
|
-
|
|
286
|
-
|
|
284
|
+
action: 'fast-forward',
|
|
285
|
+
targetSha: mainSha,
|
|
286
|
+
reason: 'main contains validated changes that staging must inherit.',
|
|
287
287
|
}
|
|
288
288
|
}
|
|
289
289
|
}
|
|
@@ -300,7 +300,11 @@ export function classifyReconciliation(input) {
|
|
|
300
300
|
[...new Set(mainOnlyCommits.flatMap((commit) => commit.changedPaths || []))],
|
|
301
301
|
allowed,
|
|
302
302
|
).filter((path) => directTreePaths === null || directTreePaths.has(path))
|
|
303
|
-
|
|
303
|
+
// Without a final-tree comparison, retain the historical fail-closed
|
|
304
|
+
// behavior. When the final delta is known, main is the validated release
|
|
305
|
+
// source of truth: replay any staging-only work on top instead of deadlocking
|
|
306
|
+
// every later release because a hotfix landed directly on main.
|
|
307
|
+
if (unexpectedMain.length && directTreePaths === null) {
|
|
304
308
|
return {
|
|
305
309
|
action: 'fail',
|
|
306
310
|
reason: 'main contains commits that are not release metadata.',
|
|
@@ -373,7 +377,7 @@ export function buildReconciliationPullRequestBody(input) {
|
|
|
373
377
|
'',
|
|
374
378
|
`Merging this pull request synchronizes \`${targetHead}\` with the exact target tip above; no other commits are introduced.`,
|
|
375
379
|
'',
|
|
376
|
-
|
|
380
|
+
`Code Foundry treats validated \`${sourceBase}\` as the shipped source of truth and preserves unpromoted \`${targetHead}\` work by replaying it on top. Indeterminate history, replay conflicts, authentication failures, and ambiguous or stale state fail the release job closed and are never pushed around branch protection. Later releases retry the direct push first; when branch policy still rejects it, this pull request is updated instead of duplicated.`,
|
|
377
381
|
)
|
|
378
382
|
return lines.join('\n')
|
|
379
383
|
}
|