code-foundry 0.34.12 → 0.34.13
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/code-foundry.yml +1 -1
- package/.github/dependabot.yml +4 -0
- package/.github/workflows/release.yml +7 -6
- package/CHANGELOG.md +8 -0
- package/README.md +2 -2
- package/docs/CONFIGURATION.md +1 -1
- package/docs/RELEASES.md +5 -5
- package/docs/WORKFLOWS.md +3 -3
- package/package.json +1 -1
- package/src/commands/doctor.mjs +2 -2
- package/src/commands/sync.mjs +3 -3
- package/src/lib/release-policy.mjs +6 -0
package/.github/CONTRIBUTING.md
CHANGED
|
@@ -48,7 +48,7 @@ docs/* test/* refactor/* │ │
|
|
|
48
48
|
| `staging` | Integration branch | Target normal pull requests here. Required checks must pass before merge. |
|
|
49
49
|
| `feat/*`, `fix/*`, `chore/*`, `refactor/*`, `docs/*`, `test/*` | Focused work | Branch from `staging`; keep changes small and reviewable. |
|
|
50
50
|
|
|
51
|
-
The Git workflow is `staging-release`: topic branches **squash** into `staging`, a promotion PR **rebases** validated changes into `main` (`merge_strategy: rebase`), and the Release Please version PR **
|
|
51
|
+
The Git workflow is `staging-release`: topic branches **squash** into `staging`, a promotion PR **rebases** validated changes into `main` (`merge_strategy: rebase`), and the Release Please version PR **rebases** into `main` (`release_merge_strategy: rebase`). Release automation never defaults to a merge method and never merges with `--admin`; `code-foundry doctor` and `code-foundry sync` fail closed on any other merge strategy. Re-align `staging` with `main` after a release when needed.
|
|
52
52
|
|
|
53
53
|
## Before you start
|
|
54
54
|
|
|
@@ -179,7 +179,7 @@ Security checks can be skipped when repository visibility or the GitHub plan doe
|
|
|
179
179
|
| ----------------- | --------- | ------------------------------------------------------- | --------------------------------------------------------- |
|
|
180
180
|
| Working branch | `staging` | Squash | All applicable required checks pass |
|
|
181
181
|
| `staging` → `main` promotion | `main` | Rebase (`merge_strategy`) | Current staging checks, release review, and rollout notes |
|
|
182
|
-
| Release Please version PR | `main` |
|
|
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/.github/code-foundry.yml
CHANGED
package/.github/dependabot.yml
CHANGED
|
@@ -9,6 +9,7 @@ updates:
|
|
|
9
9
|
open-pull-requests-limit: 99
|
|
10
10
|
groups:
|
|
11
11
|
github-actions:
|
|
12
|
+
applies-to: version-updates
|
|
12
13
|
patterns: ['*']
|
|
13
14
|
- package-ecosystem: npm
|
|
14
15
|
directory: /
|
|
@@ -19,6 +20,7 @@ updates:
|
|
|
19
20
|
open-pull-requests-limit: 99
|
|
20
21
|
groups:
|
|
21
22
|
npm-dependencies:
|
|
23
|
+
applies-to: version-updates
|
|
22
24
|
patterns: ['*']
|
|
23
25
|
- package-ecosystem: cargo
|
|
24
26
|
directory: /
|
|
@@ -29,6 +31,7 @@ updates:
|
|
|
29
31
|
open-pull-requests-limit: 99
|
|
30
32
|
groups:
|
|
31
33
|
cargo-dependencies:
|
|
34
|
+
applies-to: version-updates
|
|
32
35
|
patterns: ['*']
|
|
33
36
|
- package-ecosystem: pip
|
|
34
37
|
directory: /
|
|
@@ -39,4 +42,5 @@ updates:
|
|
|
39
42
|
open-pull-requests-limit: 99
|
|
40
43
|
groups:
|
|
41
44
|
python-dependencies:
|
|
45
|
+
applies-to: version-updates
|
|
42
46
|
patterns: ['*']
|
|
@@ -84,17 +84,18 @@ jobs:
|
|
|
84
84
|
: {}
|
|
85
85
|
let releaseType = config.release_type || 'auto'
|
|
86
86
|
let npmPublish = config.npm_publish || 'false'
|
|
87
|
-
// The merge audit topology requires
|
|
88
|
-
// pull requests into main
|
|
89
|
-
// merge method: an unset or
|
|
90
|
-
// the release job before any
|
|
87
|
+
// The merge audit topology requires rebase for Release Please version
|
|
88
|
+
// pull requests into main, matching the linear-history ruleset.
|
|
89
|
+
// Release automation never defaults to a merge method: an unset or
|
|
90
|
+
// non-rebase release_merge_strategy fails the release job before any
|
|
91
|
+
// pull request is created or merged.
|
|
91
92
|
const releaseMergeStrategy = String(config.release_merge_strategy || '').trim().toLowerCase()
|
|
92
93
|
if (releaseType === 'auto') {
|
|
93
94
|
releaseType = fs.existsSync('package.json') ? 'node' : fs.existsSync('pyproject.toml') ? 'python' : fs.existsSync('Cargo.toml') ? 'rust' : fs.existsSync('version.txt') ? 'simple' : 'none'
|
|
94
95
|
}
|
|
95
96
|
if (!['node', 'python', 'rust', 'simple', 'none'].includes(releaseType)) throw new Error(`Unsupported release_type: ${releaseType}`)
|
|
96
|
-
if (releaseMergeStrategy !== '
|
|
97
|
-
throw new Error(`release_merge_strategy must be "
|
|
97
|
+
if (releaseMergeStrategy !== 'rebase') {
|
|
98
|
+
throw new Error(`release_merge_strategy must be "rebase" for automated release merges; got ${releaseMergeStrategy || '(unset; release automation never defaults to merge)'}`)
|
|
98
99
|
}
|
|
99
100
|
if (releaseType === 'none' || !fs.existsSync('package.json')) npmPublish = 'false'
|
|
100
101
|
let legacyReleaseType = ''
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.34.13](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.12...v0.34.13) (2026-08-03)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **reconcile:** classify patch-equivalent trees consistently ([#360](https://github.com/0xPlayerOne/code-foundry/issues/360)) ([c95f1bd](https://github.com/0xPlayerOne/code-foundry/commit/c95f1bdeaa69fc5fbcd42821bc633edbbd31de49))
|
|
9
|
+
* **release:** use rebase for release PRs ([#358](https://github.com/0xPlayerOne/code-foundry/issues/358)) ([3b2b2f5](https://github.com/0xPlayerOne/code-foundry/commit/3b2b2f5cee15e3f61a1688e5b3ef0847a6eb8c55))
|
|
10
|
+
|
|
3
11
|
## [0.34.12](https://github.com/0xPlayerOne/code-foundry/compare/v0.34.11...v0.34.12) (2026-08-02)
|
|
4
12
|
|
|
5
13
|
|
package/README.md
CHANGED
|
@@ -90,8 +90,8 @@ checks, runners, coverage, caching, and custom workflow extensions.
|
|
|
90
90
|
|
|
91
91
|
The contribution policy uses the `staging-release` workflow: feature PRs squash
|
|
92
92
|
into `staging`, the promotion PR rebases into `main` (`merge_strategy: rebase`),
|
|
93
|
-
and Release Please version PRs
|
|
94
|
-
|
|
93
|
+
and Release Please version PRs rebase into `main` (`release_merge_strategy:
|
|
94
|
+
rebase`). Release automation never defaults to a merge method and never merges
|
|
95
95
|
with `--admin`; `code-foundry doctor` and `code-foundry sync` fail closed on
|
|
96
96
|
any other strategy. GitHub Stacks is not part of this topology and does not
|
|
97
97
|
reduce the required workflow runs.
|
package/docs/CONFIGURATION.md
CHANGED
|
@@ -49,7 +49,7 @@ repository manifests and source
|
|
|
49
49
|
| `license` | `gpl-3.0-or-later`, `agpl-3.0-or-later`, `mit`, `preserve`, `none` | License policy; new repositories default to GPLv3 |
|
|
50
50
|
| `git_workflow` | `staging-release` | Branch/release model; the standard model promotes `staging` into `main` |
|
|
51
51
|
| `merge_strategy` | `rebase` | Promotion merge method for `staging` → `main`; the staging-release topology requires rebase |
|
|
52
|
-
| `release_merge_strategy` | `
|
|
52
|
+
| `release_merge_strategy` | `rebase` | Merge method for Release Please version PRs into `main`; release automation fails closed unless rebase |
|
|
53
53
|
| `runner` fields | GitHub runner names | Per-workflow runner policy |
|
|
54
54
|
|
|
55
55
|
Supported features are `ci`, `codeql`, `security`, `test`, `draft-pr`,
|
package/docs/RELEASES.md
CHANGED
|
@@ -15,10 +15,10 @@ versions and generate grouped changelog notes.
|
|
|
15
15
|
The merge audit pins one merge method per transition in this topology. Feature
|
|
16
16
|
and fix branches land on `staging` with **squash** merges, the `staging` → `main`
|
|
17
17
|
promotion PR merges with **rebase** (`merge_strategy: rebase`), and Release
|
|
18
|
-
Please version PRs merge with **
|
|
18
|
+
Please version PRs merge with **rebase** (`release_merge_strategy: rebase`).
|
|
19
19
|
Release automation never defaults to a merge method and never merges with
|
|
20
20
|
`--admin`: the release workflow fails closed unless `release_merge_strategy` is
|
|
21
|
-
exactly `
|
|
21
|
+
exactly `rebase`. The current supported `git_workflow` is `staging-release`.
|
|
22
22
|
|
|
23
23
|
The release workflow opens or updates a versioned PR after changes reach
|
|
24
24
|
`main`. Merging that PR updates the changelog, creates the Git tag and GitHub
|
|
@@ -35,13 +35,13 @@ Set these values in `.github/code-foundry.yml`:
|
|
|
35
35
|
release_type: auto # auto, node, python, rust, simple, or none
|
|
36
36
|
npm_publish: false # true only for an npm package
|
|
37
37
|
merge_strategy: rebase # required: staging -> main promotion PRs rebase
|
|
38
|
-
release_merge_strategy:
|
|
38
|
+
release_merge_strategy: rebase # required: Release Please version PRs rebase only
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
`merge_strategy` applies to promotion PRs (`staging` into `main`) and
|
|
42
42
|
`release_merge_strategy` to Release Please version PRs; feature PRs into
|
|
43
43
|
`staging` use squash merges. The topology requires `merge_strategy: rebase`
|
|
44
|
-
and `release_merge_strategy:
|
|
44
|
+
and `release_merge_strategy: rebase`; `code-foundry doctor` and
|
|
45
45
|
`code-foundry sync` reject any other value, and the release workflow fails
|
|
46
46
|
closed instead of falling back to `merge`. Both keep `main` fully linear,
|
|
47
47
|
which is what makes the post-release reconciliation possible: release-only
|
|
@@ -103,6 +103,6 @@ already passed).
|
|
|
103
103
|
|
|
104
104
|
1. Merge tested changes from `staging` into `main`.
|
|
105
105
|
2. Review the generated Release Please PR and changelog.
|
|
106
|
-
3. Merge the release PR with the repository's configured `release_merge_strategy` (**
|
|
106
|
+
3. Merge the release PR with the repository's configured `release_merge_strategy` (**rebase**; the release workflow fails closed on any other value).
|
|
107
107
|
4. Confirm the GitHub Release and any package publication.
|
|
108
108
|
5. Synchronize `staging` with the new `main` release commit.
|
package/docs/WORKFLOWS.md
CHANGED
|
@@ -42,13 +42,13 @@ enabled for the repository profile.
|
|
|
42
42
|
|
|
43
43
|
The merge audit pins one merge method per transition. `code-foundry doctor`
|
|
44
44
|
and `code-foundry sync` fail closed on any other strategy, and the release
|
|
45
|
-
workflow refuses to run unless its strategy is exactly `
|
|
45
|
+
workflow refuses to run unless its strategy is exactly `rebase`.
|
|
46
46
|
|
|
47
47
|
| Transition | Merge method | Enforcement |
|
|
48
48
|
| --- | --- | --- |
|
|
49
49
|
| Feature/fix PR into `staging` | Squash | Contribution policy; see `CONTRIBUTING.md` |
|
|
50
50
|
| `staging` → `main` promotion PR | Rebase (`merge_strategy: rebase`) | `merge_strategy` must be `rebase`; merge commits are rejected |
|
|
51
|
-
| Release Please version PR into `main` |
|
|
51
|
+
| Release Please version PR into `main` | Rebase (`release_merge_strategy: rebase`) | Release automation fails closed unless `rebase`; never defaults to `merge`, never uses `--admin` |
|
|
52
52
|
|
|
53
53
|
Release auto-merge waits for required checks and then polls `mergeStateStatus`
|
|
54
54
|
until it is `CLEAN`, or `UNSTABLE` with `mergeable` `MERGEABLE`, before
|
|
@@ -59,7 +59,7 @@ additional required checks after earlier ones have passed (for example
|
|
|
59
59
|
merge policy-blocked. The mergeability poll is bounded and fails closed on
|
|
60
60
|
conflicts or timeout; releases without an automation token remain manual.
|
|
61
61
|
|
|
62
|
-
Keeping `main` linear — rebase promotions and
|
|
62
|
+
Keeping `main` linear — rebase promotions and rebase release PRs — is what
|
|
63
63
|
lets the post-release reconciliation fast-forward or replay `staging` safely.
|
|
64
64
|
|
|
65
65
|
Protect `staging` with the aggregate `Validation / Gate`, squash-only pull
|
package/package.json
CHANGED
package/src/commands/doctor.mjs
CHANGED
|
@@ -75,8 +75,8 @@ export function doctor(root, options = {}) {
|
|
|
75
75
|
error(`merge_strategy must be "rebase" for the staging-release promotion topology; got "${mergeStrategy}".`)
|
|
76
76
|
}
|
|
77
77
|
const releaseMergeStrategy = config.release_merge_strategy ?? ''
|
|
78
|
-
if (includesValue(features, 'release') && releaseMergeStrategy !== '
|
|
79
|
-
error(`release_merge_strategy must be "
|
|
78
|
+
if (includesValue(features, 'release') && releaseMergeStrategy !== 'rebase') {
|
|
79
|
+
error(`release_merge_strategy must be "rebase" for automated release merges; got "${releaseMergeStrategy || '(unset; release automation never defaults to merge)'}".`)
|
|
80
80
|
}
|
|
81
81
|
for (const workflow of ['validation', 'draft-pr', 'release-pr', 'release']) {
|
|
82
82
|
if (includesValue(features, workflow) && !existsSync(join(target, `.github/workflows/${workflow}.yml`))) error(`missing enabled workflow: ${workflow}.yml`)
|
package/src/commands/sync.mjs
CHANGED
|
@@ -84,8 +84,8 @@ export function syncRepository(options) {
|
|
|
84
84
|
throw new Error(`Unsupported merge_strategy: ${mergeStrategy}; the staging-release topology requires rebase for staging to main promotions.`)
|
|
85
85
|
}
|
|
86
86
|
const releaseMergeStrategy = configured(config.release_merge_strategy, '')
|
|
87
|
-
if (includesValue(features, 'release') && releaseMergeStrategy !== '
|
|
88
|
-
throw new Error(`Unsupported release_merge_strategy: ${releaseMergeStrategy || '(unset)'}; release automation requires
|
|
87
|
+
if (includesValue(features, 'release') && releaseMergeStrategy !== 'rebase') {
|
|
88
|
+
throw new Error(`Unsupported release_merge_strategy: ${releaseMergeStrategy || '(unset)'}; release automation requires rebase for Release Please version pull requests and never defaults to merge.`)
|
|
89
89
|
}
|
|
90
90
|
const license = configured(config.license, existsSync(join(target, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later')
|
|
91
91
|
const changed = []
|
|
@@ -460,7 +460,7 @@ function createDefaultConfig(root, source) {
|
|
|
460
460
|
post_release: 'false', post_release_workflow: '', post_release_mode: 'auto',
|
|
461
461
|
opencode_security: 'false',
|
|
462
462
|
sync_mode: 'overlay', custom_workflows: 'preserve',
|
|
463
|
-
license: existsSync(join(root, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later', git_workflow: 'staging-release', merge_strategy: 'rebase', release_merge_strategy: '
|
|
463
|
+
license: existsSync(join(root, 'LICENSE')) ? 'preserve' : 'gpl-3.0-or-later', git_workflow: 'staging-release', merge_strategy: 'rebase', release_merge_strategy: 'rebase',
|
|
464
464
|
}
|
|
465
465
|
}
|
|
466
466
|
|
|
@@ -256,6 +256,12 @@ export function classifyReconciliation(input) {
|
|
|
256
256
|
if (Array.isArray(directChangedPaths)) {
|
|
257
257
|
const paths = [...new Set(directChangedPaths.map((path) => path.trim()).filter(Boolean))]
|
|
258
258
|
const unexpected = unexpectedReleasePaths(paths, allowed)
|
|
259
|
+
// Git may hide patch-equivalent commits when divergentCommits uses
|
|
260
|
+
// --cherry-pick. If the final trees are identical and no non-equivalent
|
|
261
|
+
// commits remain, classify the branches consistently as aligned.
|
|
262
|
+
if (!paths.length && !mainOnlyCommits.length && !stagingOnlyCommits.length) {
|
|
263
|
+
return { action: 'aligned', targetSha: mainSha, reason: 'Branches have different history but identical content.' }
|
|
264
|
+
}
|
|
259
265
|
const stagingOnlyReleaseOnly = stagingOnlyCommits.length > 0 && stagingOnlyCommits.every((commit) =>
|
|
260
266
|
Array.isArray(commit.changedPaths) && commit.changedPaths.length > 0 && unexpectedReleasePaths(commit.changedPaths, allowed).length === 0,
|
|
261
267
|
)
|