Release Workflow
Every Craft release moves through the same stages:
craft prepare ──► release branch ──► CI builds artifacts ──► craft publish ──► targets └──► merge backThis page walks through each stage and the configuration that controls it. For a first-time setup, start with the Quick Start.
Prepare
Section titled “Prepare”craft prepare [NEW-VERSION] runs locally or in CI and:
- Resolves the new version: an explicit version, a bump type,
auto, orcalver. See Versioning. - Creates the release branch
{releaseBranchPrefix}/{version}from the current branch head (or--rev). - Runs the pre-release command or Craft’s automatic version bumping.
- Checks or generates the changelog according to the changelog policy.
- Commits the changes and pushes the release branch (skip with
--no-push).
Pass --publish to run craft publish right after a successful prepare.
See the CLI reference for every flag.
Release branch name
Section titled “Release branch name”Release branches are named {releaseBranchPrefix}/{version}. The default
prefix is release:
releaseBranchPrefix: publishThe prefix may contain slashes, such as release/cli. That keeps branches for
independently versioned products apart; see
Monorepos & Release Workspaces.
Pre-release command
Section titled “Pre-release command”This command runs on your release branch as part of craft prepare. Default: bash scripts/bump-version.sh.
preReleaseCommand: bash scripts/bump-version.shThe command is executed with the following environment variables:
CRAFT_OLD_VERSION: The previous version (or0.0.0if no previous version exists)CRAFT_NEW_VERSION: The new version being released
The script should:
- Use these environment variables to perform version replacement
- Replace version occurrences
- Not commit changes
- Not change git state
Note: For backward compatibility, the old and new versions are also passed as the last two command-line arguments to the script, but using environment variables is safer and recommended.
Example script:
#!/bin/bashset -eux
# Use CRAFT_NEW_VERSION provided by craftexport npm_config_git_tag_version=falsenpm version "${CRAFT_NEW_VERSION}"Pushing the release branch triggers your CI. CI must build the release artifacts and upload them somewhere the artifact provider can find them. Craft does not build anything itself.
Publish
Section titled “Publish”craft publish NEW-VERSION finds the release branch for the version, then:
- Waits for the status provider to report a successful
build (skip with
--no-status-check). - Downloads the artifacts through the artifact provider and checks required files.
- Runs each configured target in the order they are listed.
- Merges the release branch into the merge target and deletes it (see Merging the release branch).
- Runs the post-release command.
Limit a run to specific targets with -t:
craft publish 1.2.3 -t npm # only npmcraft publish 1.2.3 -t registry[browser] # a target with an idcraft publish 1.2.3 -t none # skip targets, just mergeWhen you publish to specific targets, Craft doesn’t merge the release branch.
Run craft publish 1.2.3 -t none once every target is done.
See the CLI reference for every flag.
Status provider
Section titled “Status provider”Before publishing, Craft waits for CI on the release commit to finish. By
default, the github status provider combines every commit status and check
run on that commit. List contexts to only wait for specific checks:
statusProvider: name: github config: contexts: - Travis CI - BranchArtifact provider
Section titled “Artifact provider”The artifact provider is where Craft downloads the files your CI built. The
default is github (GitHub Actions artifacts). Use gcs for Google Cloud
Storage, or none when your targets don’t need artifacts:
artifactProvider: name: github # or 'gcs' or 'none'By default, the GitHub artifact provider looks for artifacts named exactly as the commit SHA. You can customize this with the artifacts configuration option.
Pattern syntax
Section titled “Pattern syntax”- Regex patterns: Wrapped in
/(e.g.,/^build-.*$/) - Exact strings: Plain text (e.g.,
build,release-artifacts)
Configuration formats
Section titled “Configuration formats”1. Single artifact pattern - searches all workflows:
artifactProvider: name: github config: artifacts: /^sentry-.*\.tgz$/2. Multiple artifact patterns - searches all workflows:
artifactProvider: name: github config: artifacts: - /^sentry-.*\.tgz$/ - release-bundle3. Workflow-scoped patterns - filter by workflow name:
artifactProvider: name: github config: artifacts: build: release-artifacts # exact workflow → exact artifact /^build-.*$/: artifacts # workflow pattern → exact artifact ci: # exact workflow → multiple artifacts - /^output-.*$/ - bundle /^release-.*$/: # workflow pattern → multiple artifacts - /^dist-.*$/ - checksumsCommon examples
Section titled “Common examples”Fetch artifacts named craft-binary and craft-docs from the “Build & Test” workflow:
artifactProvider: name: github config: artifacts: Build & Test: - craft-binary - craft-docsFetch all .tgz files from any workflow:
artifactProvider: name: github config: artifacts: /\.tgz$/Backward compatibility
Section titled “Backward compatibility”When artifacts is not configured, the provider uses the legacy behavior where it searches for an artifact with a name matching the commit SHA exactly. This ensures existing configurations continue to work without changes.
Required files
Section titled “Required files”Ensure specific artifacts exist before publishing:
requireNames: - /^sentry-craft.*\.tgz$/ - /^gh-pages.zip$/Merging the release branch
Section titled “Merging the release branch”After publishing, Craft merges the release branch into the merge target and
deletes the branch. The merge target defaults to the repository’s default
branch; override it with --merge-target.
--no-mergeskips the merge.--keep-branchmerges but keeps the branch.- Set
noMerge: truein.craft.ymlto never merge. Craft turns this on automatically for compiled Node.js GitHub Actions (repositories with adist/folder), unlessnoMergeis set explicitly.
Post-release command
Section titled “Post-release command”This command runs after a successful craft publish. Default: bash scripts/post-release.sh.
postReleaseCommand: bash scripts/post-release.shThe released version is available as CRAFT_RELEASED_VERSION. Unlike the
pre-release command, this command handles its own git operations, so it can
commit and push changes such as a development version bump. If the default
script doesn’t exist, Craft skips this step; set postReleaseCommand: '' to
skip it explicitly.
Remote
Section titled “Remote”Craft pushes to and reads from the origin remote by default. Use --remote
or set CRAFT_REMOTE to use a different one.
Recovering from a failed prepare
Section titled “Recovering from a failed prepare”If version bumping succeeds but craft prepare fails mid-way (e.g., during changelog generation or git operations), you may need to clean up manually:
-
Check the release branch: If a release branch was created, you can delete it:
Terminal window git branch -D release/<version> -
Revert version changes: If files were modified but not committed, reset them:
Terminal window git checkout -- package.json pyproject.toml Cargo.toml # or whichever files were changed -
Re-run prepare: Once the issue is fixed, run
craft prepareagain. Version bumping is idempotent—running it multiple times with the same version is safe.