The default direct flow is:
topic branch -> main -> versioned release
Repositories that maintain a preview/staging environment opt into the
staging-release flow:
topic branch -> staging -> main -> versioned release
Keep commits Conventional Commit-shaped (feat:, fix:, docs:, ci:,
chore:, and so on). Release Please uses them to select patch/minor/major
versions and generate grouped changelog notes.
The merge audit pins one merge method per transition. In the staging-release
topology, feature and fix branches land on staging with squash merges,
the staging → main promotion PR merges with rebase (merge_strategy: rebase), and Release Please version PRs merge with rebase
(release_merge_strategy: rebase). In the direct topology, feature and fix
branches squash straight into main and Release Please version PRs squash into
main (release_merge_strategy: squash). sync, doctor, and release
automation reject any other strategy. Release automation never defaults to a
merge method and never merges with --admin.
The release workflow opens or updates a versioned PR after changes reach
main. For generated consumer callers, merging that PR updates the changelog,
creates the Git tag and GitHub Release, and can trigger npm publication. Code
Foundry's own caller uses the qualified path: it qualifies the package first,
creates a draft release, stages the exact qualified archive, then publishes the
immutable release and package through the verified publisher. See Qualified
publication.
For an explicit version, put Release-As: 2.0.0 in a commit or pull request
body. Existing CHANGELOG.md history remains repository-owned.
Set these values in .github/code-foundry.yml:
release_type: auto # auto, node, python, rust, simple, or none
npm_publish: false # true only for an npm package
git_workflow: direct # direct (default) or staging-release
merge_strategy: rebase # staging-release only: staging -> main promotion PRs rebase
release_merge_strategy: squash # direct default; staging-release requires rebasegit_workflow: staging-release is opt-in; without it, repositories use the
direct flow and no promotion PR exists. When the staging-release topology is
selected, merge_strategy applies to promotion PRs (staging into main)
and release_merge_strategy to Release Please version PRs; feature PRs into
staging use squash merges. code-foundry doctor, code-foundry sync, and
the release workflow reject any non-rebase merge_strategy or release
strategy in staging-release; direct requires squash for
release PRs and never falls back to merge. Both keep main fully linear,
which is what makes the post-release reconciliation possible. The final
branch trees are inspected before mutation; validated main-only changes are
inherited by staging, while unpromoted staging work is replayed on top of
main.
Promotion never opens a pull request directly from a divergent staging
history. The workflow creates or refreshes a deterministic promotion branch
whose single commit has the current main tip as its parent and the exact
validated staging tree. This keeps the review diff limited to the actual
environment delta even after squash or rebase merges have changed ancestry.
The generated commit preserves the staged tip's conventional subject so
Release Please still detects the appropriate release type after promotion.
The staging → main reconciliation exists only in the staging-release
topology. The reusable release workflow defaults to direct and requires its
caller to opt into staging-release, so a stale remote staging branch cannot
activate reconciliation in a direct repository. Patch-equivalent divergence
between main and staging is treated as aligned. When staging has pending
commits that are not yet represented on
main, the release workflow replays those staging-only commits in order onto a
detached worktree rooted at main, and then updates staging with an exact
--force-with-lease to prevent
unintended branch rewrites. There is no unconditional mirror force-push and no
unreviewed fallback synchronization commit path. Indeterminate history, replay
conflicts, and stale leases fail closed. direct repositories skip this step
entirely.
When branch policy requires reconciliation through a pull request, Code
Foundry creates a deterministic one-commit delivery head instead of pointing
the pull request branch at the divergent main or replay history. Its parent
is the current protected staging tip and its tree is the exact reconciled
target tree. This keeps the review limited to release metadata and any genuine
replayed staging work, while preserving exact-lease updates and idempotent PR
reuse.
auto selects a supported manifest. Use simple with version.txt for a
repository without a package manifest and none for a repository that should
not release automatically.
Release Please runs in manifest mode whenever the release config declares
packages or a top-level release-type; code-foundry sync bootstraps
.release-please-manifest.json from the current package versions the first
time it is needed. Release Please owns the manifest after the first release
and sync never overwrites existing manifest versions. Legacy configs without
packages or release-type continue to run in simple mode and need no
manifest; code-foundry doctor fails when a manifest-mode config is missing
its manifest.
The release job validates the configured automation token
(CODE_FOUNDRY_TOKEN) against the
current repository with an authenticated REST probe before any write. When no
automation token is configured, or the configured token is rejected by GitHub
(observed with long-lived fine-grained tokens that GitHub rejects with HTTP
403 even on REST), the release job fails over to the repository's short-lived
GITHUB_TOKEN. In that mode, Code Foundry opens or updates the version pull
request, leaves it for manual merge, and completes the release job
successfully. The token value is never printed or written to step outputs.
Guarded automatic merging and the downstream workflows triggered by the
resulting release are enabled only when the configured automation token was
validated successfully; a rejected token never falls through to any write.
Configure a valid, narrowly scoped CODE_FOUNDRY_TOKEN
repository or organization secret to enable guarded
automatic merging and downstream workflows triggered by the resulting
release. The token needs contents, issues, and pull-requests write
permissions. Code Foundry validates every changed path in the generated
version pull request before requesting its merge with GitHub's auto-merge
feature and the configured canonical method (squash for direct, rebase
for staging-release). GitHub performs the merge only after the branch's
required checks and reviews pass; the release runner exits after submitting
that request rather than waiting for every workflow to finish. This keeps a
healthy release from failing just because required checks outlast a bounded
runner-side wait. No checks, reviews, or branch rules are bypassed. The
request uses the exact head SHA returned by Code Foundry's path audit and is
refused if the branch changed during that audit.
Repositories using a valid CODE_FOUNDRY_TOKEN must allow auto-merge in their
GitHub settings when release checks may still be pending. GitHub rejects the
request if auto-merge is unavailable. If the PR is already eligible, the same
command merges it immediately under branch policy. A head change detected
between the path audit and enqueueing fails the release job. Conflicts remain
subject to GitHub's branch policy and keep the merge from completing until
resolved. GitHub's
automatic head-branch deletion setting removes branches after deferred merges;
the CLI's --delete-branch option also removes a branch when the merge completes
immediately. GitHub can keep auto-merge enabled if a later Release Please run
updates the branch. With the documented required Validation / Gate, each
synchronized head reruns the release-diff policy, and GitHub waits for that
head's required checks before merging.
- Merge tested changes into
main(direct: feature PRs; staging-release: promotestagingintomain). - Review the generated Release Please PR and changelog. A validated
CODE_FOUNDRY_TOKENlets the release workflow merge it automatically after required checks; without that token, merge it manually with the configured topology method: squash fordirect, rebase forstaging-release. - For a generated consumer caller, confirm the GitHub Release and any package publication.
- For Code Foundry itself, do not advance the self-referencing runtime pin as part of a release; self-sync preserves that compatibility pin and avoids a self-update release loop. Confirm qualification, draft staging, immutable publication, and the retained identity receipts.
- In
staging-release, synchronizestagingwith the newmainrelease commit.