Short for "Branch Release" - this is a CLI that allows you to create releases
off any branch and either merge back into that branch or into a different
branch. It allows you to follow the git-flow methodology if you want to but
also allows you the freedom to create release versions on different branches
without merging into main.
This project extends the commit-and-tag-version project. So it uses their versioning and bumping logic, but builds a workflow on top of it.
To install this package, you can pull the tar files from the
releases page, or you can use
Homebrew (which is much easier):
brew install kerren/brrelease-tap/brreleaseHere's a video on how to use the CLI for different workflows,
You can do single branch workflows or multibranch workflows. For a single branch
your git commit graph would look something like this:
For a multi-branch workflow, your git graph would look something like this:
Check out the release command below for more information on how to use it!
$ npm install -g brrelease
$ brrelease COMMAND
running command...
$ brrelease (--version)
brrelease/1.16.1 linux-x64 node-v26.7.0
$ brrelease --help [COMMAND]
USAGE
$ brrelease COMMAND
...Display autocomplete installation instructions.
USAGE
$ brrelease autocomplete [SHELL] [-r]
ARGUMENTS
SHELL (zsh|bash|powershell) Shell type
FLAGS
-r, --refresh-cache Refresh cache (ignores displaying instructions)
DESCRIPTION
Display autocomplete installation instructions.
EXAMPLES
$ brrelease autocomplete
$ brrelease autocomplete bash
$ brrelease autocomplete zsh
$ brrelease autocomplete powershell
$ brrelease autocomplete --refresh-cache
See code: @oclif/plugin-autocomplete
Display help for brrelease.
USAGE
$ brrelease help [COMMAND...] [-n]
ARGUMENTS
COMMAND... Command to show help for.
FLAGS
-n, --nested-commands Include all nested commands in the output.
DESCRIPTION
Display help for brrelease.
See code: @oclif/plugin-help
Run a release on the branch that you're on
USAGE
$ brrelease release [-P <value>] [-G <value>] [-R <value>] [-c <value>] [-C] [--changelog-commit-message
<value>] [-r <value>...] [-m <value>] [-b <value>] [--bump-files-commit-message <value>] [-p <value>...] [-B
<value>...] [-u <value>...] [--release-as major|minor|patch] [--first-release] [--prerelease <value>] [-s] [-A]
[--skip-preflight] [--fail-on-uncommitted] [--skip-fetch]
FLAGS
-A, --auto-push Automatically push the branches and tag once the release has
been merged (this is more for convenience)
-B, --bump-file=<value>... The files where the version should be bumped with out the
previous version being considered (see
https://github.com/absolute-version/commit-and-tag-version)
-C, --skip-changelog Skip writing to a changelog file
-G, --git-binary-path=<value> [default: git] The path to the git binary (default is "git"
since it assumes it is globally accessible)
-P, --tag-prefix=<value> [default: v] The prefix that should be before the number on
the tag made in git (default is "v")
-R, --release-branch-prefix=<value> [default: release/] The prefix that is used to create release
branches (default is "release/")
-b, --merge-into-branch=<value> If you would like the release to merge into a different
branch, specify it here. The default is the current branch
you're on. Please note that this branch will be merged into
the branch you're on after the release runs to ensure the
changelog generates correctly.
-c, --changelog-file-path=<value> [default: CHANGELOG.md] The path to the file that the
changelog should be written to
-m, --run-script-during-release-commit-message=<value> [default: chore: generate the release file changes] The commit
message that should be used to commit the changed files that
occur after running the custom release job
-p, --package-file=<value>... [default: package.json] The package files that should be used
to determine the current version of the project (see
https://github.com/absolute-version/commit-and-tag-version)
-r, --run-script-during-release=<value>... One or many scripts that should be run during the release,
it's recommended that you make these npm scripts and they
don't contain the '"' character
-s, --[no-]sign Sign the git commits and the release tag
-u, --updater=<value>... The updater files/scripts that should run during execution
(see
https://github.com/absolute-version/commit-and-tag-version)
--bump-files-commit-message=<value> [default: chore: bump the version in project files] The commit
message to use when bumping the version in files
--changelog-commit-message=<value> [default: chore: generate the changelog] The commit message
that should be used to commit the changelog file
--fail-on-uncommitted Fail the preflight checks when there are uncommitted changes
in the working tree. By default uncommitted changes are only
reported as a warning, because a build run before the release
usually leaves generated files behind.
--first-release If this is the first release being created (see
https://github.com/absolute-version/commit-and-tag-version)
--prerelease=<value> The prerelease prefix that should be used if necessary (see
https://github.com/absolute-version/commit-and-tag-version)
--release-as=<option> Specify the type of release (see
https://github.com/absolute-version/commit-and-tag-version)
<options: major|minor|patch>
--skip-fetch Do not contact the remote during the preflight checks.
Branches are then compared against the last known state of the
remote and the remote tag check is skipped.
--skip-preflight Skip the preflight checks that run before the release starts.
This is an escape hatch, you are strongly encouraged to fix
what the checks report instead.
DESCRIPTION
Run a release on the branch that you're on
EXAMPLES
$ brrelease release
$ brrelease release --release-as=major
$ brrelease release --merge-into-branch=main
$ brrelease release --merge-into-branch=main --run-script-during-release="npm run update-readme"
$ brrelease release --merge-into-branch=main --run-script-during-release="npm run update-readme" --run-script-during-release="echo $(date) > .latest-build-time"
$ brrelease release --prerelease=beta --skip-changelog
$ brrelease release --package-file=package.json --bump-file=package-lock.json --bump-file=.versionrc
See code: src/commands/release.ts
Before it touches your repository, brrelease release runs a set of preflight
checks. They exist because the release stages every change it finds and discards
unstaged files while building the changelog, so starting from a bad state can
commit work you did not mean to release, or lose it entirely.
The checks are:
| Check | Why it matters |
|---|---|
| You are inside a git repository | Gives a clear error instead of a raw git failure |
| Uncommitted changes are reported | The release runs git add -A, so uncommitted work is swept into the release commits. This is a warning by default, since a build run before the release usually leaves generated files behind, and a failure with --fail-on-uncommitted |
| The merge target exists locally | --merge-into-branch pointing at a branch you have not checked out fails halfway through the release |
| Each branch involved is level with its remote | Releasing from a stale or diverged branch tags the wrong commit and the push is rejected |
| An upstream is configured | --auto-push runs a bare git push, which fails without one |
| The tag does not already exist, locally or on the remote | A tag someone else already pushed is only discovered when your push is rejected, after the release has run |
| The release branch does not already exist | Usually left behind by a release that failed part way through |
Anything that would break the release stops it before any changes are made. Things that are worth knowing but not fatal, such as being unable to reach the remote, are reported as warnings and the release continues.
Three flags adjust the behaviour:
--fail-on-uncommittedturns the uncommitted changes warning into a failure, so the release stops when the working tree is dirty. Use it when nothing in your release should be generating files, and you would rather be told than have them committed into the release.--skip-fetchavoids contacting the remote. Branches are compared against the last known state of the remote and the remote tag check is skipped, which is useful offline.--skip-preflightbypasses the checks entirely. It is an escape hatch, and you are much better off fixing what the checks report.
In order to get the other libraries to work the way I wanted, I needed to use
patches on the node_modules libraries installed. I thought that the
postinstall script would run on my library when you npm install it, but it
looks like it skips that lifecycle hook. So I've had to create full builds for
this and rather provide other ways of installing!
