Skip to content

fix(version): recognize PEP 440 development tags - #2026

Open
ychampion wants to merge 1 commit into
commitizen-tools:masterfrom
ychampion:fix/pep440-devrelease-tags
Open

fix(version): recognize PEP 440 development tags#2026
ychampion wants to merge 1 commit into
commitizen-tools:masterfrom
ychampion:fix/pep440-devrelease-tags

Conversation

@ychampion

Copy link
Copy Markdown

Description

Fixes #1367.

The default $version parser rejected .devN tags that Commitizen itself creates. This keeps generated PEP 440 prerelease, development, and local-version combinations discoverable so the next incremental changelog can find the previous tag.

Checklist

Was generative AI tooling used to co-author this PR?

  • Yes (OpenAI Codex)

Generated-by: OpenAI Codex following the guidelines

Code Changes

  • Added regression coverage for the parser and sequential uv-provider bumps
  • Ran uv run poe all locally
  • Manually reproduced two sequential development bumps with incremental changelogs
  • Verified existing PEP 440, SemVer, custom tag-format, and invalid-tag coverage
  • Documentation is unchanged because no option or workflow changed

Expected Behavior

After creating 0.2.0.dev0, a subsequent --devrelease 1 bump should recognize that tag and generate the 0.2.0.dev1 changelog, tag, pyproject.toml, and uv.lock updates.

Steps to Test This Pull Request

  1. Configure the uv version provider with update_changelog_on_bump and changelog_incremental enabled.
  2. Run cz bump --devrelease 0 --yes after a feature commit.
  3. Add another feature commit and run cz bump --devrelease 1 --yes.
  4. Confirm the second bump succeeds and writes 0.2.0.dev1 to the tag, changelog, pyproject.toml, and uv.lock.

Keep development-release tags discoverable across sequential bumps while preserving custom tag embedding and existing suffix behavior.

Constraint: Preserve custom tag formats and SemVer-compatible parsing.

Rejected: Replace the shared parser with the anchored PEP 440 reference regex | it breaks embedded tag formats and unrelated schemes.

Confidence: high

Scope-risk: narrow

Directive: Keep generated version forms round-trippable through TagRules.

Tested: uv run poe all; 446 focused tag, version, bump, and changelog tests; exact uv-provider sequential bump regression; git diff --check.

Not-tested: Full tox matrix across every supported Python version and operating system.
@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.23%. Comparing base (7812abe) to head (bca8975).
⚠️ Report is 34 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff           @@
##           master    #2026   +/-   ##
=======================================
  Coverage   98.23%   98.23%           
=======================================
  Files          61       61           
  Lines        2784     2784           
=======================================
  Hits         2735     2735           
  Misses         49       49           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@Manny7717 Manny7717 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bca8975

Verified locally against head bca897506ad1242431ac6365347f62fd694015e0 (commitizen master + this PR's 3 files):

  • Regression proven: on master's code, TagRules().is_version_tag("0.2.0.dev0") is False and extract_version raises InvalidVersion — same for 0.2.0.dev0+build.1, 0.2.0a1.dev0, 0.2.0a1.dev0+build.1, 2.0.0.dev0, and 1.2.3rc1+build5. With this PR all parse correctly; the new test_is_version_tag_accepts_pep440_devrelease fails on master and passes here.
  • No regressions (differential battery, 15 tags incl. 1.2.3, v1.2.3, 1.2.3rc1, 1.2.3-dev1, 1.2.3+build.1, 0.2.0dev0, 0.1.0): every tag recognized on master is recognized identically here; 0.2.0.not-a-release stays rejected. The change is strictly additive — it only accepts previously-rejected valid PEP 440 forms.
  • Group numbering unchanged ((\w+)?(?:\w+)?, build group was never captured), so nothing referencing the old groups breaks.
  • Tests: tests/test_tags.py + tests/test_version_schemes.py = 16 passed; test_bump_command.py::test_bump_devrelease_with_incremental_changelog passes (exercises two real bump --devrelease runs incl. uv-provider version sync + incremental changelog); ruff clean on all touched files.

One non-blocking nit: the dotless forms (0.2.0dev0) normalize correctly via packaging, but the new test's 0.2.0.dev0+build.1 round-trip depends on str(Version) normalization — worth keeping in mind if a custom tag_format ever needs the literal string preserved. Not a blocker.

Fix is correct, minimal, and well-tested — approving.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

The --devrelease option in cz bump is not correctly incrementing the version

2 participants