On this page
Release execution: version bump, commit, tag, push, GitHub Release, and post-release steps.
#rlsbl.commands.release.execute
#rlsbl.commands.release.execute
Release execution: version bump, commit, tag, push, GitHub Release, and post-release steps.
#ReleaseAbortError
Raised when the release must abort (e.g., unexpected dirty files).
#_bump_selfdoc_version
def _bump_selfdoc_version(project_dir, new_version)Bump version in selfdoc.json if it exists. Returns list of modified file paths.
#_rel_to_git_root
def _rel_to_git_root(path, git_root)Normalize path; make relative to git root if absolute.
#resolve_target_paths
def resolve_target_paths(project_dir='.')Build a dict mapping target names to their resolved paths.
Uses detect_targets() which reads .rlsbl/config.json "targets" (supporting both plain strings and dicts with "name"/"path") and falls back to auto-detection.
Returns dict[str, str] mapping target name -> resolved directory path.
#resolve_release_targets
def resolve_release_targets(primary, flags, project_dir='.', *, config)Compute the effective set of secondary targets for this release.
Reads the baseline from config "release_targets" list. If absent, falls back to auto-detect (all targets that detect(".")). Entries can be plain strings or dicts with "name" and optional "path".
The primary target is always excluded from the secondary set (it's handled separately by the main release flow).
Returns a dict mapping target name -> resolved directory path.
#_refresh_selfdoc_hashes
def _refresh_selfdoc_hashes(files_to_commit, log, project_dir='.')Re-run selfdoc check after version bump to refresh content hashes.
The early selfdoc check (before tests) validates documentation correctness, but its hashes are based on pre-bump file contents. After the version bump modifies pyproject.toml, selfdoc.json, etc., the hashes in .selfdoc/hashes/hashes.json become stale. This function re-runs selfdoc check to recalculate hashes based on bumped versions, then adds the hash file to files_to_commit if it changed.
Non-fatal: errors are warned about but do not abort the release.
#_sync_lockfiles
def _sync_lockfiles(target_paths, files_to_commit, log)Re-sync lockfiles after version bumps so they stay consistent.
For each known lockfile found in a target directory, runs the corresponding sync command. If the lockfile is modified, its path is appended to files_to_commit so it is included in the release commit and not flagged by the unexpected-files guard.
Missing tools and sync failures are warnings, not errors.
#archive_blog_body
def archive_blog_body(project_dir, version)Archive unreleased.md to v{version}.md during release finalization.
Returns the archived path if the file existed, None otherwise.
#collect_companion_tags
def collect_companion_tags(member_package_paths, workspace_root, version, primary_tag)Collect companion tags from all non-private member packages.
Iterates member packages in an explicit releasable, detects their targets, and collects companion tags (e.g. Go module proxy tags).
Guards:
- Only meaningful in explicit releasable mode (caller checks).
- Skips companion creation if the primary tag already contains a
/v pattern (Go-compatible), to avoid duplicate tags.
- Skips private packages (same logic as _sync_member_package_versions).
Args:
member_package_paths: workspace-relative paths for member packages.workspace_root: absolute path to the monorepo root.version: version string being released.primary_tag: the primary release tag string.
Returns:
- List of companion tag strings (deduplicated, excluding the primary tag).
#_sync_member_package_versions
def _sync_member_package_versions(member_package_paths, monorepo_root, new_version, files_to_commit, git_root, log, ctx, exclude_path=None, releasable_config_dir=None)Sync version to published member packages in explicit releasable mode.
For each member package that has publishing pipelines (non-private, has a detected target), writes the version to the manifest. Private-only packages are left untouched.
Uses read_project_config with releasable inheritance so that releasable-level private: false is respected by member packages that don't set private themselves.
Args:
member_package_paths: list of workspace-relative paths for member packages.monorepo_root: absolute path to the monorepo root.new_version: version string to write.files_to_commit: list to append modified file paths to.git_root: absolute path to the git root.log: logging callable.ctx: ProjectContext.exclude_path: optional workspace-relative path to skip (already handled).releasable_config_dir: optional path to the releasable's state directory
for config inheritance.
#ReleaseState
All state needed by _run_release_mutating, grouped logically.
#_find_publish_workflows
def _find_publish_workflows(project_dir='.')Scan .github/workflows/ for YAML files matching publish*.yml.
Returns a list of filenames (not full paths) matching the pattern. Used to populate the dispatch field in pending.json.
#_run_pr_release
def _run_pr_release(state, run, run_gh, commit_files, log, *, release_branch_name, project_dir, _git_root, _state_path, vpath)Execute PR-mode release: write pending.json, push branch, create PR, switch back.
Called from _run_release_mutating after version bump, changelog finalization, and release file finalization are complete on the release branch. This replaces the imperative-mode tag+push+GitHub Release steps.
#_run_release_mutating
def _run_release_mutating(state: ReleaseState)Inner release logic that runs under the advisory lock (mutating phase).