Config file formats#
bumpversion looks for its configuration in the directory it runs in — the current directory, or the one given by --dir.
Discovery order#
Four filenames are tried, in this order:
| # | File | Section |
|---|---|---|
| 1 | .bumpversion.toml | [tool.bumpversion] |
| 2 | .bumpversion.cfg | [bumpversion] |
| 3 | pyproject.toml | [tool.bumpversion] |
| 4 | setup.cfg | [bumpversion] |
The first file that contains a usable section wins, and only that file is used — configuration is never merged across files. A pyproject.toml with no [tool.bumpversion] table (or with an empty one) is skipped as though it were not there, so the search continues to setup.cfg.
If no file yields a configuration, the run fails with missing config file.
Cargo.tomlis checked last but reading configuration from it is not implemented — a[package.metadata.bumpversion]table has no effect today.
TOML#
The native format. Everything lives under [tool.bumpversion], per-file entries are an array of tables, and per-component settings are nested tables:
[project]
name = "widget"
version = "0.3.1"
[tool.bumpversion]
current_version = "0.3.1"
commit = true
tag = true
tag_name = "v{new_version}"
message = "chore(release): {current_version} → {new_version}"
# pyproject.toml holds the config, so bumpversion already rewrites
# `current_version` here. This entry additionally rewrites `[project].version`.
[[tool.bumpversion.files]]
filename = "pyproject.toml"
[[tool.bumpversion.files]]
filename = "src/widget/__init__.py"Running against it produces:
$ bumpversion --dry-run -v bump minor [DRY-RUN] [current version] [DRY-RUN] 0.3.1 [DRY-RUN] [setup] [DRY-RUN] no setup hooks defined [DRY-RUN] [new version] [DRY-RUN] 0.4.0 [DRY-RUN] [DRY-RUN] [./pyproject.toml] [DRY-RUN] replacing `{current_version}` (0.3.1) with `{new_version}` (0.4.0) [DRY-RUN] [DRY-RUN] Differences (-before|+after): [DRY-RUN] [project] [DRY-RUN] name = "widget" [DRY-RUN] -version = "0.3.1" [DRY-RUN] +version = "0.4.0" [DRY-RUN] [DRY-RUN] [tool.bumpversion] [DRY-RUN] -current_version = "0.3.1" [DRY-RUN] +current_version = "0.4.0" [DRY-RUN] commit = true [DRY-RUN] tag = true [DRY-RUN] tag_name = "v{new_version}" [DRY-RUN] message = "chore(release): {current_version} → {new_version}" [DRY-RUN] [DRY-RUN] [./src/widget/__init__.py] [DRY-RUN] replacing `{current_version}` (0.3.1) with `{new_version}` (0.4.0) [DRY-RUN] [DRY-RUN] Differences (-before|+after): [DRY-RUN] -__version__ = "0.3.1" [DRY-RUN] +__version__ = "0.4.0" [DRY-RUN] [DRY-RUN] [./pyproject.toml] [DRY-RUN] replacing `{current_version}` (0.3.1) with `{new_version}` (0.4.0) [DRY-RUN] [DRY-RUN] Differences (-before|+after): [DRY-RUN] name = "widget" [DRY-RUN] version = "0.3.1" [DRY-RUN] [DRY-RUN] [tool.bumpversion] [DRY-RUN] -current_version = "0.3.1" [DRY-RUN] +current_version = "0.4.0" [DRY-RUN] commit = true [DRY-RUN] tag = true [DRY-RUN] tag_name = "v{new_version}" [DRY-RUN] message = "chore(release): {current_version} → {new_version}" [DRY-RUN] [pre-commit] [DRY-RUN] no pre-commit hooks defined [DRY-RUN] [commit] [DRY-RUN] add ./pyproject.toml [DRY-RUN] add ./src/widget/__init__.py [DRY-RUN] commit chore(release): 0.3.1 → 0.4.0 [DRY-RUN] [tag] [DRY-RUN] tag = v0.4.0 [DRY-RUN] message = Bump version: 0.3.1 → 0.4.0 [DRY-RUN] sign = false [DRY-RUN] [post-commit] [DRY-RUN] no post-commit hooks defined
Two details worth noting in that output:
[project].versionand[tool.bumpversion].current_versionare both rewritten, becausepyproject.tomlis listed as a file and is the config file.- The tag name and commit message come from the
tag_nameandmessagetemplates in the config.
Regexes in TOML#
The parse key is a regex, and regexes are full of backslashes. Use a TOML literal string (single quotes) so they are taken as written:
parse = '(?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)'In a basic string (double quotes) every backslash has to be doubled, which is easy to get wrong:
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"INI#
.bumpversion.cfg and setup.cfg use the legacy INI layout from bump2version, supported so an existing project works unchanged:
[metadata]
name = widget
version = 4.2.0
[bumpversion]
current_version = 4.2.0
commit = True
tag = True
tag_name = release-{new_version}
serialize =
{major}.{minor}.{patch}
[bumpversion:file:setup.cfg]
[bumpversion:file:widget/__init__.py]
[bumpversion:glob:docs/*.rst]The differences from TOML:
Global keys go in
[bumpversion].Per-file entries are their own sections, named
[bumpversion:file:<path>]. A disambiguating suffix is allowed, so two entries can target the same file:[bumpversion:file(version heading):CHANGELOG.md].Glob entries are
[bumpversion:glob:<pattern>].glob_excludeis not supported in INI.Component entries are
[bumpversion:part:<name>].Values are unquoted, and booleans accept
True/Falseas well astrue/false.Lists are written one item per line (indented), or comma-separated on one line:
serialize = {major}.{minor}.{patch}-{release} {major}.{minor}.{patch}The literal value
Nonemeans “unset” for most keys.In
[bumpversion:part:<name>],valuesmust be multi-line or comma-separated — a bare single value is not accepted.
In setup.cfg, sections unrelated to bumpversion are ignored silently. In .bumpversion.cfg — a file that exists only for this tool — an unrecognized section is reported as a diagnostic.
The INI parser currently prints a few
=> section: …debug lines to stdout while reading the file. They come from the underlyingserde-ini-spannedparser and are harmless, but they do clutter the output — TOML is the quieter choice for a new project.
Choosing a file#
- New project —
.bumpversion.toml. It is found first and keeps release configuration out of your package manifest. - Python project —
[tool.bumpversion]inpyproject.toml, next to the rest of your tooling. - Existing
bump2versionproject — leavesetup.cfgor.bumpversion.cfgwhere it is; it is read as-is.