github-next-semantic-version
is a little CLI binary (written in golang) to
guess the next semantic version from:
- existing git tags (read from a locally cloned git repository)
- and recently merged pull-requests labels (read from the GitHub API)
Unlinke plenty of "similar" tools, we don't use any "commit message parsing" here but only configurable PR labels.
Example (with a repo cloned in the current directory):
$ github-next-semantic-version .
v1.10.0 => v1.10.1
$ # v1.10.0 is the latest version
$ # v1.10.1 is the next version
Tip
How do we determine the next version? How do we determine if the next version is a patch/minor/major version?
- we list PRs merged since the latest tag
- we examine corresponding PR labels:
- if we find at least one
breaking
orType: Major
label => this is a major release (so we increment the major version number) - if we find at least one
feature
orType: Feature
label => this is a minor release (so we increment the minor version number) - else this is a patch release
- if we find at least one
(of course, you can define your own labels to configure the logic)
Note
We also provide:
- a dedicated GitHub Action in this dedicated repository if you want to use this tool inside a GHA workflow
- another CLI binary:
github-create-next-semantic-release
(in this current repository) to use the previous rules to automatically create a GitHub release with the guessed version and the corresponding release notes (made from merged PRs and a configurable template) - another GitHub Action in this other repository if you want to use this alternate tool:
github-create-next-semantic-release
inside a GHA workflow - a full changelog generator CLI:
github-generate-changelog
(configurable by a golang text/template)
- support full semver specification (basic
1.2.3
but also1.0.0-beta.2
,0.1.9-post.24_a5256f1
...) - can filter tags with regex (see
--tag-regex
option) - support prefixed tags (example:
v1.2.3
but alsofoo/bar/v1.2.3
...) when parsing the semantic version - configure your own PR labels for major and minor increments
- ... (see "CLI reference" in this document)
- addon binary to automatically create GitHub releases with the guessed version and corresponding release notes
- addon binary to generate full changelog
- "commit message parsing": there are plenty of tools to do that, here, we want to rely only on merged PR labels
- "other providers support": we support only "GitHub" (feel free to fork if you want to add other providers support)
We provide compiled binaries for various architecture in the release page.
- download the corresponding file
- set the "executable bit"
- clone a public repository locally (with all tags)
- execute
./github-next-semantic-version .
(same for github-create-next-semantic-release
binary)
Note
Of course it also works with private repositories but you will need a GitHub token
set to GITHUB_TOKEN
env var (for example).
CLI reference of github-next-semantic-version
$ github-next-semantic-version --help
NAME:
github-next-semantic-version - Compute the next semantic version with merged PRs and corresponding labels
USAGE:
github-next-semantic-version [global options] command [command options] LOCAL_GIT_REPO_PATH
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--log-level value log level (DEBUG, INFO, WARN, ERROR) (default: "INFO") [$LOG_LEVEL]
--log-format value log format (text-human, text, json, json-gcp) (default: "text-human") [$LOG_FORMAT]
--github-token value github token [$GITHUB_TOKEN]
--repo-owner value repository owner (organization); if not set, we are going to try to guess [$GNSV_REPO_OWNER]
--repo-name value repository name (without owner/organization part); if not set, we are going to try to guess [$GNSV_REPO_NAME]
--branches value, --branch value Coma separated list of branch names to filter on for getting tags and prs (if not set, the default branch is guessed/used) [$GNSV_BRANCH_NAME]
--consider-also-non-merged-prs Consider also non-merged PRs (default: false) [$GNSV_CONSIDER_ALSO_NON_MERGED_PRS]
--tag-regex value Regex to match tags (if empty string (default) => no filtering) [$GNSV_TAG_REGEX]
--ignore-labels value Coma separated list of PR labels to consider as ignored PRs (OR condition) (default: "Type: Hidden") [$GNSV_HIDDEN_LABELS]
--must-have-labels value Coma separated list of PR labels that PRs must have to be considered (OR condition, empty => no filtering) [$GNSV_MUST_HAVE_LABELS]
--minimal-delay-in-seconds value Minimal delay in seconds between a PR and a tag (if less, we consider that the tag is always AFTER the PR) (default: 5)
--major-labels value Coma separated list of PR labels to consider as major (OR condition) (default: "major,breaking,Type: Major") [$GNSV_MAJOR_LABELS]
--minor-labels value Coma separated list of PR labels to consider as minor (OR condition) (default: "feature,Type: Feature,Type: Minor") [$GNSV_MINOR_LABELS]
--dont-increment-if-no-pr Don't increment the version if no PR is found (or if only ignored PRs found) (default: false) [$GNSV_DONT_INCREMENT_IF_NO_PR]
--next-version-only If set, output only the next version (without the old one) (default: false) [$GNSV_NEXT_VERSION_ONLY]
--help, -h show help
CLI reference of github-create-next-semantic-release
$ github-create-next-semantic-release --help
NAME:
github-create-next-semantic-release - Create the next semantice release on GitHub (depending on the PRs merged since the last release)
USAGE:
github-create-next-semantic-release [global options] command [command options] LOCAL_GIT_REPO_PATH
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--log-level value log level (DEBUG, INFO, WARN, ERROR) (default: "INFO") [$LOG_LEVEL]
--log-format value log format (text-human, text, json, json-gcp) (default: "text-human") [$LOG_FORMAT]
--github-token value github token [$GITHUB_TOKEN]
--repo-owner value repository owner (organization); if not set, we are going to try to guess [$GNSV_REPO_OWNER]
--repo-name value repository name (without owner/organization part); if not set, we are going to try to guess [$GNSV_REPO_NAME]
--branches value, --branch value Coma separated list of branch names to filter on for getting tags and prs (if not set, the default branch is guessed/used) [$GNSV_BRANCH_NAME]
--consider-also-non-merged-prs Consider also non-merged PRs (default: false) [$GNSV_CONSIDER_ALSO_NON_MERGED_PRS]
--tag-regex value Regex to match tags (if empty string (default) => no filtering) [$GNSV_TAG_REGEX]
--ignore-labels value Coma separated list of PR labels to consider as ignored PRs (OR condition) (default: "Type: Hidden") [$GNSV_HIDDEN_LABELS]
--must-have-labels value Coma separated list of PR labels that PRs must have to be considered (OR condition, empty => no filtering) [$GNSV_MUST_HAVE_LABELS]
--minimal-delay-in-seconds value Minimal delay in seconds between a PR and a tag (if less, we consider that the tag is always AFTER the PR) (default: 5)
--major-labels value Coma separated list of PR labels to consider as major (OR condition) (default: "major,breaking,Type: Major") [$GNSV_MAJOR_LABELS]
--minor-labels value Coma separated list of PR labels to consider as minor (OR condition) (default: "feature,Type: Feature,Type: Minor") [$GNSV_MINOR_LABELS]
--release-draft if set, the release is created in draft mode (default: false) [$GNSV_RELEASE_DRAFT]
--release-body-template value golang template to generate the release body (default: "{{ range . }}- {{.Title}} (#{{.Number}})\n{{ end }}") [$GNSV_RELEASE_BODY_TEMPLATE]
--release-body-template-path value golang template path to generate the release body (if set, release-body-template option is ignored) [$GNSV_RELEASE_BODY_TEMPLATE_PATH]
--release-force if set, force the version bump and the creation of a release (even if there is no PR) (default: false) [$GNSV_RELEASE_FORCE]
--help, -h show help
CLI reference of github-generate-changelog
$ github-generate-changelog --help
NAME:
github-generate-changelog - Make a changelog from local git tags and GitHub merged PRs
USAGE:
github-generate-changelog [global options] command [command options] LOCAL_GIT_REPO_PATH
COMMANDS:
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--log-level value log level (DEBUG, INFO, WARN, ERROR) (default: "INFO") [$LOG_LEVEL]
--log-format value log format (text-human, text, json, json-gcp) (default: "text-human") [$LOG_FORMAT]
--github-token value github token [$GITHUB_TOKEN]
--repo-owner value repository owner (organization); if not set, we are going to try to guess [$GNSV_REPO_OWNER]
--repo-name value repository name (without owner/organization part); if not set, we are going to try to guess [$GNSV_REPO_NAME]
--branches value, --branch value Coma separated list of branch names to filter on for getting tags and prs (if not set, the default branch is guessed/used) [$GNSV_BRANCH_NAME]
--consider-also-non-merged-prs Consider also non-merged PRs (default: false) [$GNSV_CONSIDER_ALSO_NON_MERGED_PRS]
--tag-regex value Regex to match tags (if empty string (default) => no filtering) [$GNSV_TAG_REGEX]
--ignore-labels value Coma separated list of PR labels to consider as ignored PRs (OR condition) (default: "Type: Hidden") [$GNSV_HIDDEN_LABELS]
--must-have-labels value Coma separated list of PR labels that PRs must have to be considered (OR condition, empty => no filtering) [$GNSV_MUST_HAVE_LABELS]
--minimal-delay-in-seconds value Minimal delay in seconds between a PR and a tag (if less, we consider that the tag is always AFTER the PR) (default: 5)
--future if set, include a future section (default: false) [$GNSV_CHANGELOG_FUTURE]
--template-path value if set, define the path to the changelog template [$GNSV_CHANGELOG_TEMPLATE_PATH]
--starting-tag value if set, defining a starting tag (excluded) for changelog generation, the special value 'LATEST' (combined with --future) will use the latest semantic tag to get only the future section [$GNSV_CHANGELOG_STARTING_TAG]
--help, -h show help
This tool is fully developped in Golang 1.21+ with following libraries:
- github.com/Masterminds/semver V3: for semver parsing
- github.com/google/go-github V62: for GitHub API
- github.com/urfave/cli V2: for CLI
We follow golang-standards/project-layout directories structure and we use "hexagonal architecture" with:
- domain/use-cases code in the
app
subdir - IO adapters in the
infra/adapters
subdir - CLI controller in the
infra/controllers
subdir
Dev commands are implemented inside a Makefile
with following targets:
$ make help
build Build Go binaries
clean Clean the repo
doc Generate documentation
lint Lint the code (also fix the code if FIX=1, default)
no-dirty Check if the repo is dirty
test-integration Run integration tests
test-unit Execute all unit tests
test Execute all tests