iTranslated by AI

The content below is an AI-generated translation. This is an experimental feature, and may contain errors. View original article
🔖

I Created "bump", a Version Bumping Tool for Any Project

に公開

Introduction

How do you handle versioning when updating your OSS projects? Since I write Go frequently, I use gobump by motemen. It is a handy tool that finds the version variable in Go source code and bumps the version according to semantic versioning.

gobump patch -w

With just this, const version = "1.2.3" in your Go source code becomes "1.2.4". This ease of use is so fantastic that some of my OSS projects even have monstrous tags like v0.0.223.

However, because gobump works by parsing Go's AST to rewrite variables, it can only be used with Go source code. In projects other than Go, we often have version information in files like package.json, pyproject.toml, or Cargo.toml. Manually rewriting these and committing them every time was becoming tedious.

I thought, "Why not just find version-like strings with regular expressions and rewrite them?" and so I created bump.

https://github.com/mattn/bump

Installation

go install github.com/mattn/bump@latest

Usage

bump uses -f to specify the file and -p for the regular expression pattern. The pattern must include one capture group, which will be recognized as the version string.

bump patch -w -f package.json -p '"version":\s*"(\d+\.\d+\.\d+)"'

This will rewrite "version": "1.2.3" in package.json to "version": "1.2.4". If you do not use -w, it will output the result to standard output without overwriting the file, allowing you to preview the changes.

The subcommands follow the same interface as gobump.

Command Description
major Bump major version (1.2.3 → 2.0.0)
minor Bump minor version (1.2.3 → 1.3.0)
patch Bump patch version (1.2.3 → 1.2.4)
up Select with an interactive prompt
set <version> Explicitly set a custom version
show Only display the current version

Use it with anything

Since it uses regular expressions to find versions, it works with any file format.

pyproject.toml

bump minor -w -f pyproject.toml -p 'version\s*=\s*"(\d+\.\d+\.\d+)"'

Cargo.toml

bump major -w -f Cargo.toml -p 'version\s*=\s*"(\d+\.\d+\.\d+)"'

Go source code

bump patch -w -f main.go -p 'version\s*=\s*"(\d+\.\d+\.\d+)"'

You can also use it instead of gobump, but since it does not parse the AST, it is not as precise. This is for those who are fine with that approach.

Interactive mode

Using the up subcommand allows you to choose whether to bump the patch, minor, or major version via a prompt.

bump up -w -f package.json -p '"version":\s*"(\d+\.\d+\.\d+)"'
? Bump up package.json:
  ▸ patch (1.2.3 -> 1.2.4)
    minor (1.2.3 -> 1.3.0)
    major (1.2.3 -> 2.0.0)

Since the bumped version value is displayed in the prompt, it is easy to spot mistakes. In non-interactive environments such as CI, adding the -y flag treats it as a patch bump.

Integrating with Makefile

The real strength of bump lies in its integration with Makefile. I actually use bump to manage the versioning of bump itself.

.PHONY: bump

bump:
	@VERSION=$$(go run . up -w -f main.go -p 'version\s*=\s*"(\d+\.\d+\.\d+)"') && \
		[ -n "$$VERSION" ] && \
		git commit -am "bump version to $$VERSION" && \
		git tag "v$$VERSION" && \
		git push origin "v$$VERSION"

Just by running make bump, it handles everything from version selection and file rewriting to committing, tagging, and pushing all at once.

Since this pattern can be used in projects for any language, you do not need to change your versioning workflow for each project.

Conclusion

I created bump so I could use the great experience of gobump elsewhere. I even use bump to bump up bump. It is a single Go binary and requires no configuration files, so you can just drop it in and it works. Please try out the experience of bumping your version, tagging it, and pushing it with a single make bump command.

Discussion