Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

PrepareRelease

What it does

PrepareRelease is the core release execution step.

It discovers packages, loads authored changesets, computes the release plan, updates manifests and changelogs, and prepares the structured release result that later steps can consume.

In other words: most release-oriented commands are really PrepareRelease plus something else.

Why use it

Use PrepareRelease whenever the command needs real release state.

It is the step that unlocks:

  • release file updates
  • changelog rendering
  • release target calculation
  • structured release.* template context
  • the cached .monochange/release-manifest.json artifact exposed as manifest.path
  • later steps such as CommitRelease, PublishRelease, OpenReleaseRequest, and CommentReleasedIssues

If your command eventually needs release metadata, start with PrepareRelease rather than trying to reconstruct that state in shell.

Inputs

  • format: markdown, text, or json
  • write_empty_release_record: boolean; write a release record even when no packages were released
  • release_json: boolean; write the release record (.monochange/releases/<hash>/release.json) during dry-run preview. By default monochange preview skips the release record; pass --release-json to write it.

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. PrepareRelease is the producer step for the rest of the release workflow.

Side effects and outputs

PrepareRelease is stateful.

It can produce:

  • updated manifests
  • updated changelogs
  • deleted or consumed changeset files
  • release target information
  • a cached release manifest at .monochange/release-manifest.json
  • final command output in markdown, text, or JSON form
  • structured release.* template values for later Command steps
  • manifest.path for later Command steps that need the on-disk JSON artifact

Built-in release-oriented commands default their human-readable format input to text. Use markdown for a raw Markdown artifact or json for automation.

When you only need the resolved package and group versions, use the dedicated DisplayVersions step or the built-in monochange versions command instead of overloading PrepareRelease.

It also fills the shorthand template values commonly used by Command steps:

  • {{ version }}
  • {{ group_version }}
  • {{ released_packages }}
  • {{ changed_files }}
  • {{ changesets }}

Example

[cli.release]
help_text = "Prepare a release from discovered change files"

[[cli.release.inputs]]
name = "format"
type = "choice"
choices = ["text", "json", "json-min"]
default = "text"

[[cli.release.steps]]
type = "PrepareRelease"
inputs = ["format"]

Composition ideas

Prepare and run a custom follow-up command

[cli.release-with-notes]
help_text = "Prepare a release and print a custom summary"

[[cli.release-with-notes.inputs]]
name = "format"
type = "choice"
choices = ["text", "json", "json-min"]
default = "text"

[[cli.release-with-notes.steps]]
type = "PrepareRelease"
inputs = ["format"]

[[cli.release-with-notes.steps]]
type = "Command"
command = "echo Releasing {{ release.version }} for {{ released_packages }}"
shell = true

Prepare and then branch into provider automation

Typical production commands look like:

  • PrepareRelease → PublishRelease
  • PrepareRelease → OpenReleaseRequest
  • PrepareRelease → CommitRelease
  • PrepareRelease → Command

Prepare once, consume several outputs

Because the later steps all depend on the same prepared state, you should generally do one PrepareRelease and then fan out from it with several typed steps rather than trying to run several independent release commands.

Reuse prepared state across separate commands

When you do need to split the workflow across separate commands, monochange can reuse a prepared release artifact instead of recomputing the release plan from scratch.

When a repository defines workflow wrappers, the default cache path is automatic. For example, a repo with release and release-pr wrappers might run:

monochange step prepare-release
monochange step open-release-request --dry-run

The first PrepareRelease step stores prepared state in .monochange/local/prepared-release-cache.json, and later commands with a PrepareRelease step reuse it only while every input it was computed from still matches: the pending changeset bytes and set, package manifests and their ancestor workspace manifests, monochange.toml, prerelease state, release records, the git HEAD, and the workspace status. Because the changeset bytes are fingerprinted, editing a changeset’s severity or body in place — even when it is untracked or already dirty — replans instead of reusing the stale plan.

.monochange/local/ is the only directory under .monochange/ that should be gitignored. monochange adds it to .git/info/exclude automatically, so reusable prepared state, the cached release manifest, and other local release metadata do not pollute reviewable commits.

Never add .monochange/ as a whole to .gitignore. Release records under .monochange/releases/<id>/release.json and .monochange/prerelease-state.json are committed state that CommitRelease, publish-readiness, tag-release, and provider release automation read from git history. Ignoring them makes releases unpublishable.

If your configured workflow exposes a prepared_release input and you need to pass the artifact between explicit jobs or custom commands, wire that input to PrepareRelease and pass the artifact path:

monochange run release --prepared-release /tmp/release-plan.json
monochange step open-release-request --prepared-release /tmp/release-plan.json --format json

Here release and release-request are example workflow names; use the names shown by monochange help for your repository.

If the artifact is stale, monochange falls back to a fresh PrepareRelease run instead of trusting outdated release data.

Good fit / bad fit

Good fit:

  • any release workflow
  • commands that need release metadata
  • commands that need changelog or version updates

Bad fit:

  • simple validation-only CI gates
  • discovery-only inspection commands
  • post-release repair flows (RetargetRelease is separate)

Common mistakes

  • putting PublishRelease or OpenReleaseRequest before PrepareRelease
  • assuming PrepareRelease is just a read-only planner in non-dry-run mode
  • forgetting that later Command steps can consume its structured output directly
  • forgetting that --quiet suppresses output but does not replace --dry-run