Bump semver for git repos with a single command
Project description
bumpsemver
Current version: v2.3.0
Table of contents
Overview
A utility to simplify the version bumping for git repos.
This application is a rework of the famous bumpversion
tool. The
original repo seems like abandoned. Several fundamental changes are
introduced, which make the fork-and-extend approach infeasible:
- dropped Python 2 support
- boosted the test coverage to 95%+
- dropped many irrelevant features to reduce complexity. (e.g. customized version component support)
- introduced JSON support to make it work for package-lock.json
- introduced YAML support to make it work for Ansible playbooks
- introduced TOML support to make it work for pyproject.toml
- narrowed the versioning scheme to semver-only
Installation
pip install --upgrade bumpsemver
Usage
This application supports both the CLI mode and config file mode. Options on the command line take precedence over those from the config file, which take precedence over those from the defaults.
Command Line Interface
bumpsemver [options] part
options
(optional)
Most of the configuration values described below can also be given as an option on the command-line. Additionally, the following options are available:
--dry-run
Don't touch any files, just pretend. Best used with --verbose
.
--allow-dirty
Normally, bumpsemver will abort if the working directory is dirty to avoid releasing not versioned files
and/or overwriting unsaved changes. Use this option to override this check.
--verbose
Print useful information about the action details.
-h, --help
Print help and exit.
part
(required)
The part of the version to increase. As we support semver only, the valid values include: major
, minor
, and patch
.
For example, bumping from 0.5.1 to 0.6.0:
bumpsemver --current-version 0.5.1 minor
Configuration file
bumpsemver
looks up configuration file .bumpsemver.cfg
at the current directory.
The config file uses ini
syntax.
It consists of one general section [bumpsemver]
and zero or more [bumpsemver:type(suffix):filename]
file sections.
Example .bumpsemver.cfg
:
[bumpsemver]
current_version = 0.2.9
commit = True
tag = True
[bumpsemver:plaintext:README.md]
search = Version: **{current_version}**
replace = Version: **{new_version}**
[bumpsemver:plaintext(header):home.md]
search = Version: **{current_version}**
replace = Version: **{new_version}**
[bumpsemver:plaintext(footer 1):home.md]
search = Current version: {current_version}
replace = Current version: {new_version}
[bumpsemver:json:example.json]
jsonpath = foobar.items[1].version
[bumpsemver:yaml:example.yml]
yamlpath = dummy.version
[bumpsemver:toml:example.toml]
tomlpath = project.version
General config section
General configuration is grouped in a [bumpsemver]
section of .bumpsemver.cfg
.
It has the following properties:
current_version =
(required). default: none
The current version of the software package before bumping.
Also available as CLI argument --current-version
(e.g. bumpsemver --current-version 0.5.1 patch
)
tag = (True | False)
(optional). default: False
Whether to create a git tag, that is the new version, prefixed with the character "v
".
Also available as CLI argument --tag
or --no-tag
.
sign_tags = (True | False)
(optional). default: False
Whether to sign tags.
Also available as CLI argument --sign-tags
or --no-sign-tags
.
tag_name =
(optional). default: v{new_version}
The name of the tag that will be created. Only valid when tag = True
.
It can be a template using the Python Format String Syntax.
Available in the template context are current_version
and new_version
as well as current_[part]
and new_[part]
(e.g. 'current_major
' or 'new_patch
'). You can also use the variables now
or utcnow
to get a current timestamp.
Both accept datetime formatting (when used like as in {now:%d.%m.%Y}
).
Also available as CLI argument --tag-name
, for example: bumpsemver --tag-name 'release-{new_version}' patch
In addition, it is also possible to provide a tag message by using CLI --tag-message TAG_MESSAGE
. Example usage:
bumpsemver --tag-name 'release-{new_version}' --tag-message "Release {new_version}" patch
If neither tag message nor sign tag is provided, we use a lightweight
tag in git. Otherwise, we utilize an annotated
git tag. Read more about Git tagging here.
commit = (True | False)
(optional). default: False
Create a commit using git when true.
Also available as CLI argument --commit
or --no-commit
.
message =
(optional). default: build(repo): bumped version {current_version} → {new_version}
The commit message to use when creating a commit. Only valid when using --commit
/ commit = True
.
It can be a template using the Python Format String Syntax.
Available in the template context are current_version
and new_version
as well as current_[part]
and new_[part]
(e.g. 'current_major
' or 'new_patch
'). You can also use the variables now
or utcnow
to get a current timestamp.
Both accept datetime formatting (when used like as in {now:%d.%m.%Y}
).
Also available as CLI argument --message
, for example: bumpsemver --tag-name 'release-{new_version}' patch
File-specific config sections
A file-specific config section is required for each file to specify the handling of the particular file.
One config file can have zero or more file-specific config sections.
The section name looks like [bumpsemver:type:filename]
.
It specifies the action to be done for a specific file.
We do have the use case that one file has multiple places to change, a popular example is package-lock.json
:
{
"name": "app-cli",
"version": "1.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "app-cli",
"version": "1.1.0",
"license": "SEE LICENSE IN LICENSE"
}
}
}
We need two config sections for the same file in this case, but INI format does not allow duplicated section names.
To make it work, we could append a description between parens to the
type
keyword: [bumpsemver:plaintext(special one):…]
. It does not matter what inside the parens, just make it unique.
For the example below, the two patterns will be applied separately to the same file README.md
:
[bumpsemver:plaintext(1):README.md]
search = current version: {current_version}
replace = current version: {new_version}
[bumpsemver:plaintext(footer):README.md]
search = **Version: {current_version}**
replace = **Version: {new_version}**
File types supported in the file-specific config section
All the famous bump*version
utilities family has a common pattern to handle the files as a plain text file.
The advantage of this approach is that in fact it makes the use scenario programming language-neutral.
Be it a package-lock.json for node.js project, or pyproject.toml for a Python application,
the bump*version
is applicable as long as a proper regex pattern for version extraction can be defined.
However, it will bring significant side effect for complex file for example package-lock.json
.
A typical (relatively) complex React projects contains 1000+ npm packages indirectly.
For randomly sampled 30 public projects at GitHub written in node.js/TypeScript,
the classical bumpversion
or the renovated bump2version
both made mistakes
for all 30 projects which changed something shouldn't be changed.
For instance, the facebook/create-react-app
application has a large fleet of indirect
npm dependencies.
If we define the search pattern as "version": "4.0.0"
, we will screw up the other 210 packages.
Or if we are unluckily releasing our app bumping the version from 7.16.0
to 8.0.0
,
other 132 npm packages in the version lock will be changed to 8.0.0
, which likely do not exist.
To address this issue, bumpsemver
added the support of some popular file types
to access the particular version attribute using a deterministic locator/selector without regex.
The supported file types are:
- plaintext
- json
- yaml
- toml
bumpsemver
will use the file extension to determine the file type and throw an error if the detected file type
mismatches with the specified one.
This behavior can be overridden by specifying the file type with a !
suffix.
For example, [bumpsemver:json!:config.yaml]
will treat config.yaml
as a JSON file.
Plain text file
The file-specific config section looks like:
[bumpsemver:plaintext:filename]
search = Version: {current_version}
replace = Version: {new_version}
A deprecated syntax is also supported:
[bumpsemver:file:filename]
We renamed (in a backward compatible way) file
or plaintext
to emphasize
that the file being processed is considered as a plain text file.
You can easily destroy a JSON file by a missing a double-quote or a comma in the regex pattern.
This file type should generally only be used for the files that are not JSON, YAML, or TOML.
README.md
is a good use case for this one.
[bumpsemver:plaintext:...]
can have two properties:
search =
default: {current_version}
Template string how to search for the string to be replaced in the file. Useful if the remotest possibility exists that the current version number might be present multiple times in the file, and you mean to only bump one of the occurrences.
replace =
default: {new_version}
Template to create the string that will replace the current version number in the file.
Given this requirements.txt
:
Django>=1.5.6,<1.6
MyProject==1.5.6
using the following .bumpsemver.cfg
will ensure only the line containing MyProject
will be changed:
[bumpsemver]
current_version = 1.5.6
[bumpsemver:plaintext:requirements.txt]
search = MyProject=={current_version}
replace = MyProject=={new_version}
JSON file
The file-specific config section looks like:
[bumpsemver:json:package.json]
jsonpath = version
It accepts only one property:
jsonpath =
(required) default: none
Value of the parameter jsonpath
is a JSONPath string,
it points to the exact property of the version string to be bumped.
For the typical package.json
, using version
or its jQuery-style alternative $.version
is sufficient.
Otherwise, anything can be selected with JSONPath is support, so, nothing we can't do.
The underlying JSONPath processor is jsonpath-ng.
Checkout their document for some examples and hints.
The suffix is also supported for json file:
[bumpsemver:json(1):example.json]
jsonpath = version
[bumpsemver:json( same file):example.json]
jsonpath = dependencies[2].*.version
[bumpsemver:json (once again):example.json]
jsonpath = dependencies[0].*.lodash.dependencies[1].version
YAML file
Comparably, YAML is supported for the same reason that we should support native JSON, like
[bumpsemver:yaml:playbook.yml]
yamlpath = version
OR
[bumpsemver:yaml(1):playbook.yml]
yamlpath = *.vars.project_version
[bumpsemver:yaml( same file):playbook.yaml]
yamlpath = *.vars.version
[bumpsemver:yaml (once again):playbook.yaml]
yamlpath = *.vars.app_version
Please note that we use
yamlpath here.
yamlpath
is not a popular "standard" widely adopted as jsonpath
.
For complex scenarios, it makes sense to test the expression with yamlpath cli
before putting anything in the config file.
TOML file
The file-specific config section looks like:
[bumpsemver:toml:pyproject.toml]
tomlpath = tool.poetry.version
For whatever reason toml gets its acceptance and popularity, especially in the Go, Rust, and later Python community.
Despite the unlogical fashion and religion drives, in fact we have many toml files in the wild.
For instance pyproject.toml
is everywhere now.
We cannot even find out a "tomlpath" or similar library to read/update the properties in a toml file by giving a string as the "path" to the property. We rolled our own tomlpath processor, which is not a standard, but offering similar functionality as yamlpath.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file bumpsemver-2.3.0.tar.gz
.
File metadata
- Download URL: bumpsemver-2.3.0.tar.gz
- Upload date:
- Size: 28.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.11.4 Darwin/23.4.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | f4b038f71b2f21b655c895cc1a7e3a05052e4a768cc329af4f6065f77a99c50a |
|
MD5 | 7846132dd2e8330b8a50102961b28e59 |
|
BLAKE2b-256 | 9a17efb4345f20a90d8781ee11c9e927855d26652263dbfe29ffa96f64ed6d81 |
File details
Details for the file bumpsemver-2.3.0-py3-none-any.whl
.
File metadata
- Download URL: bumpsemver-2.3.0-py3-none-any.whl
- Upload date:
- Size: 29.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.8.2 CPython/3.11.4 Darwin/23.4.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 7984ac308f7b829a92f4e977687f339b1e8b412b602e111cbce5d6e6422af41d |
|
MD5 | 90623596472e6c2809a1135b97baf3af |
|
BLAKE2b-256 | 07070b2060347d18287530e92dc079bfff7e7f093fb4aa2c058330f1a1a196d8 |