RetargetRelease
What it does
RetargetRelease repairs an already-recorded release.
It finds the release’s durable ReleaseRecord, plans a retarget operation, and then moves the release tag set to a later commit.
This is intentionally separate from PrepareRelease-driven steps. It works from git history and durable release metadata, not from newly prepared release state.
Why use it
Use RetargetRelease when the release already happened but the tags or hosted release state need to move.
It is a repair step, not a planning step.
Typical use cases include:
- a release commit landed, but tags must move to a later fix commit
- the hosted release should stay aligned with the corrected tag position
- a recent release needs to be repaired without generating a brand-new release plan
- a previous
CommitReleaseleft the durable release record you now want to reuse safely
Inputs
from— tag or commit-ish used to discover the release recordtarget— commit-ish to move the release to; defaults toHEADforce— allow non-descendant retargetssync_provider— whether hosted provider state should be synchronizedformat—textorjson
Step-level when condition
All CLI steps support an optional when = "..." condition.
If the expression resolves to false at runtime, monochange skips the step and continues with the next step.
when = "{{ inputs.enabled }}"
Step-level always_run flag
All CLI steps support an optional always_run = true flag.
When set, the step executes even if a previous step in the same command has failed. This is useful for cleanup, notification, or dry-run preview steps that must run regardless of earlier outcomes.
always_run = true
Prerequisites
None.
Unlike publication-oriented steps, RetargetRelease does not require PrepareRelease first.
Side effects and outputs
RetargetRelease is a stateful maintenance step.
It can:
- discover the release record from history
- plan and optionally execute tag movement
- optionally synchronize provider release state
- expose a rich
retarget.*namespace to laterCommandsteps
Commonly useful fields include:
retarget.fromretarget.targetretarget.record_commitretarget.resolved_from_commitretarget.distanceretarget.tagsretarget.provider_resultsretarget.status
In --dry-run mode, it reports the planned repair without mutating tags or provider state.
Safety model
RetargetRelease is designed to make repair explicit.
A few rules matter in practice:
- you identify the release to repair with
from - by default, the target is
HEAD - non-descendant repairs require
force = true - provider synchronization is optional and controlled with
sync_provider
That means you can start with a safe preview, confirm the proposed movement, and only then run the real repair.
Example
[cli.repair-release]
help_text = "Repair a recent release by retargeting its tags"
[[cli.repair-release.inputs]]
name = "from"
type = "string"
required = true
[[cli.repair-release.inputs]]
name = "target"
type = "string"
default = "HEAD"
[[cli.repair-release.inputs]]
name = "force"
type = "boolean"
default = "false"
[[cli.repair-release.inputs]]
name = "sync_provider"
type = "boolean"
default = "true"
[[cli.repair-release.inputs]]
name = "format"
type = "choice"
choices = ["text", "json"]
default = "text"
[[cli.repair-release.steps]]
type = "RetargetRelease"
inputs = ["from", "target", "force", "sync_provider"]
Composition ideas
Repair and print a custom notification
[cli.repair-and-notify]
help_text = "Repair a release and print the retarget result"
[[cli.repair-and-notify.inputs]]
name = "from"
type = "string"
required = true
[[cli.repair-and-notify.inputs]]
name = "target"
type = "string"
default = "HEAD"
[[cli.repair-and-notify.steps]]
type = "RetargetRelease"
inputs = ["from", "target"]
[[cli.repair-and-notify.steps]]
type = "Command"
command = "echo moved {{ retarget.tags }} to {{ retarget.target }} with status {{ retarget.status }}"
shell = true
Use it in a dedicated maintenance command
RetargetRelease usually belongs in a maintenance-oriented command rather than a day-to-day release command.
It represents a different lifecycle phase: post-release repair.
Preview first, then perform the repair
A good operational pattern is:
- run the repair command with
--dry-run - inspect
retarget.status,retarget.tags, and the proposed target - rerun without
--dry-runonce the plan is correct
Good fit / bad fit
Good fit:
- release repair workflows
- operational commands owned by maintainers or release engineers
- commands that need structured
retarget.*output for notifications or audits
Bad fit:
- normal release publishing flows
- commands that should create a brand-new release plan
- situations where a simple patch release is the safer response
Why choose it over manually moving tags?
Because the built-in step repairs the release as a coherent unit based on the stored ReleaseRecord.
That means it can:
- find the release record from history
- reason about the release as monochange recorded it
- coordinate provider synchronization at the same time
- expose structured repair results to later steps
A manual tag move can change refs, but it does not preserve that workflow-level structure.
Common mistakes
Do not mix up RetargetRelease and PrepareRelease.
PrepareReleaseanswers: “what should be released now?”RetargetReleaseanswers: “how should an already-recorded release be repaired?”
Also avoid:
- skipping
--dry-runwhen the repair is high risk - using
forcewithout first understanding why the target is not a descendant - treating retargeting as a substitute for publishing a new patch release when a real follow-up release is more appropriate