rlsbl v0.113.0 /rlsbl.commands.undo
On this page

Undo command that reverts a release by deleting the GitHub Release, removing the git tag, and reverting the version bump commit. Supports older versions.

#rlsbl.commands.undo

#rlsbl.commands.undo

Undo command that reverts a release.

The undo flow is plan-driven: an :class:UndoPlan is computed UPFRONT (for both the latest-release path and the --version non-latest path) before anything is mutated. The plan enumerates the release commits to revert (found by walking git history from the release tag toward the pre-release boundary), companion tags to delete, whether a GitHub Release exists, and the registry evidence verdict. --dry-run prints the plan and exits without touching anything; a real run consumes the identical plan object.

#UndoPlan

A fully-computed description of what an undo will do.

Computed once, before any mutation. --dry-run prints it and exits; a real run executes it. revert_shas is a list of (sha, subject) tuples ordered newest-first (the order they must be reverted in so each revert applies cleanly).

#_resolve_undo_changelog_paths

python
def _resolve_undo_changelog_paths(project_path, ws_root, releasable_name)

Resolve the changes dir, regenerate callable, and git-add paths for changelog restoration -- releasable-aware.

In explicit releasable mode the finalized JSONL lives in the releasable's changes dir and the canonical CHANGELOG.md in the releasable dir (plus the combined root CHANGELOG.md); otherwise everything is per-project.

#_resolve_undo_releases_dir

python
def _resolve_undo_releases_dir(project_path, ws_root, releasable_name)

Resolve the releases dir holding the release-file family -- releasable-aware.

In explicit releasable mode the archived v{x}.toml (and unreleased.toml) live under the releasable's own releases dir; otherwise per-project.

#_clear_release_state

python
def _clear_release_state(project_path, ws_root)

Clear any in-progress release state after a successful rollback.

A rolled-back release's preserved in-progress.json is meaningless and would hard-block the next rlsbl release run.

#_print_summary

python
def _print_summary(results)

Print a summary table of step results. Only called when at least one step failed.

#_resolve_context

python
def _resolve_context(ctx)

Detect the monorepo / releasable context shared by both undo paths.

#_find_latest_tag

python
def _find_latest_tag(uc)

Resolve the latest release tag (scoped to releasable/project in monorepos).

#_version_and_msg

python
def _version_and_msg(uc, tag)

Return (bare_version, expected_version_bump_message) for a tag.

#_build_tag_from_version

python
def _build_tag_from_version(uc, version)

Build the release tag string for a given version (non-latest path).

#_classify_release_commit

python
def _classify_release_commit(subject, expected_msg)

Return the shape of a release commit, or None if it is not one.

#_walk_release_commits

python
def _walk_release_commits(tag, expected_msg)

Walk history from the tag's commit toward the pre-release boundary.

Collects contiguous release-shaped commits newest-first. Message-shape matching only VALIDATES what the walk finds; the walk itself (not the shape of the current HEAD) drives iteration, so it is immune to the "revert changes HEAD's subject" bug. Stops at the first non-release-shaped commit (the boundary) or after collecting the version-bump commit (the oldest commit of a release -- this keeps back-to-back releases from bleeding into each other).

Returns (revert_shas, captured_finalize_changelog, captured_finalize_release_file).

#_plan_companion_tags

python
def _plan_companion_tags(uc, tag, version)

Enumerate companion tags to delete (both paths, releasable mode only).

#_plan_gate

python
def _plan_gate(uc, ctx, version)

Run the registry evidence gate for the release (both paths).

Resolution goes through MemberContext so targets/paths inherit releasable-level config. resolved_targets is available on the context for future per-pipeline evidence checks, but the evidence gate currently operates per-target-object only.

#_build_plan

python
def _build_plan(uc, flags, ctx)

Compute the full UndoPlan for either path, before any mutation.

#_enforce_gate

python
def _enforce_gate(plan)

Refuse the undo when the evidence gate did not clear.

PUBLISHED -> route to release yank / release deprecate (no bypass). INCONCLUSIVE / all-inconclusive -> hard block (same semantics as the non-latest path). Applies to BOTH the latest and non-latest paths.

#_restore_changelog

python
def _restore_changelog(plan, uc, results)

Reconcile CHANGELOG.md with the restored changelog state.

Runs on BOTH paths. It first un-finalizes the version's JSONL (renaming {version}.jsonl back to unreleased.jsonl; a no-op when a revert already restored it, and the repair when it didn't -- e.g. the non-latest path or a finalize commit outside the collected release commits). It then ALWAYS regenerates CHANGELOG.md so the generated file matches the restored unreleased.jsonl -- reverting the finalize commit restores the JSONL but leaves CHANGELOG.md showing the released version rather than ## Unreleased. Commits only when git reports an actual change, so it is idempotent.

#_restore_release_file

python
def _restore_release_file(plan, uc, results)

Repair the release file when its finalize commit was NOT reverted.

unfinalize_release_file is a no-op when the file is already restored (e.g. the finalize commit was reverted), so this is safe on both paths.

#_execute_plan

python
def _execute_plan(plan, uc, flags, ctx)

Execute a computed UndoPlan. Writes the audit journal BEFORE any deletion.

#run_cmd

python
def run_cmd(registry, args, flags, *, ctx)
Search