René's URL Explorer Experiment


Title: fix(tags): widen prerelease and devrelease tag regexes for SemVer2 by bearomorphism · Pull Request #1972 · commitizen-tools/commitizen · GitHub

Open Graph Title: fix(tags): widen prerelease and devrelease tag regexes for SemVer2 by bearomorphism · Pull Request #1972 · commitizen-tools/commitizen

X Title: fix(tags): widen prerelease and devrelease tag regexes for SemVer2 by bearomorphism · Pull Request #1972 · commitizen-tools/commitizen

Description: Description Closes #1614. Why When a project uses version_scheme = "semver2" together with a custom tag_format that includes ${prerelease} — for example "${major}.${minor}-${patch}${prerelease}" — the tags that commitizen creates (e.g. 0.0-2rc.0) cannot be recognised on the next invocation. Every subsequent cz bump --prerelease rc prints Invalid version tag: '0.0-2rc.0' does not match any configured tag format and then exits with code 16, making it impossible to chain prerelease bumps without manually running cz changelog in between. The culprit is the prerelease entry in get_tag_regexes (commitizen/defaults.py:159). The old pattern r"(?P\w+\d+)?" requires the prerelease segment to end with a decimal digit — matching PEP-440 forms like rc0 or alpha1, but not SemVer2 forms like rc.0 or alpha.beta.1 (the dot terminates \w+, and the mandatory \d+ then fails to match .0). Commitizen itself generates the SemVer2 form when version_scheme = "semver2" is active, so the tag it just wrote is immediately unreadable by the regex that should recognise it. Triage in #1964 reproduced the exact failure against master (v4.15.1): after cz bump --prerelease rc --yes, git tag --list shows 0.0-2rc.0; the following cz bump --prerelease rc --yes fails as described. A related defect in the devrelease regex — it required a leading dot (\.dev\d+) while the ${devrelease} substitution can produce the dot-less form dev1 in some tag formats — is fixed in the same change, as both regexes live side-by-side in get_tag_regexes. What changed File Change commitizen/defaults.py Widened prerelease regex from \w+\d+ to \w+(?:\.\w+)* and made the leading dot in devrelease optional (\.?dev\d+) inside get_tag_regexes (lines 159–160) tests/test_tags.py Added test_is_version_tag_accepts_semver2_prerelease_in_custom_tag_format — regression test asserting is_version_tag accepts 0.0-2rc.0, 0.0-2, and 0.0-2alpha.beta.1 with the custom tag format from the issue How it works get_tag_regexes (commitizen/defaults.py:151–165) returns a dict that maps tag-format placeholders like ${prerelease} to named-capture-group regex fragments. Those fragments are assembled into a full tag-matching regex elsewhere in the tag-parsing pipeline. prerelease change — \w+(?:\.\w+)* replaces \w+\d+. The old suffix \d+ forced the token to end with a digit: rc0 ✓, rc.0 ✗. The new pattern is an initial \w+ segment (matching rc, alpha, dev) followed by zero or more .\w+ repetitions (matching .0, .beta, .1), making it greedy enough for multi-segment SemVer2 prereleases (alpha.beta.1) without over-matching. The whole group remains optional (?) so plain releases continue to match. devrelease change — \.?dev\d+ replaces \.dev\d+. The leading dot is optional so that ${devrelease} substitutions that omit the dot separator (see #1615) still round-trip correctly. The literal dev prefix is preserved — a bare \d+ suffix without it would let the regex match arbitrary numeric noise. Why not [^\s+]* for prerelease? That would be too permissive — it would consume literal characters from adjacent placeholders or from structural separators in the tag_format string (e.g. a + used for build metadata), corrupting the overall tag regex. Why not fix normalize_tag instead? The tag format chosen in the issue (${major}.${minor}-${patch}${prerelease}) is valid; the tag string 0.0-2rc.0 is what commitizen correctly produces for version 0.0.2-rc.0 under that format. The bug is purely in the regex used to re-read those tags — widening the regex is the minimal, safe fix. Backward compatibility \w+\d+ is a strict subset of \w+(?:\.\w+)*: every tag string matched by the old regex is still matched by the new one. No previously-valid tag is rejected. The optional whole-group ? is preserved for both prerelease and devrelease, so plain version tags (no prerelease, no devrelease) continue to match without changes. All existing tests in test_tags.py, test_bump_normalize_tag.py, test_changelog.py, and test_bump_command.py still pass. The change is internal to get_tag_regexes; no public API or config key is altered. Checklist I have read the contributing guidelines Was generative AI tooling used to co-author this PR? Yes (please specify the tool below) Generated-by: Claude following the guidelines Code Changes Add test cases to all the changes you introduce Run uv run poe all locally to ensure this change passes linter check and tests Manually test the changes (see "Steps to Test" below) Update the documentation for the changes Expected Behavior Scenario Outcome cz bump --prerelease rc with version_scheme = "semver2" and tag_format containing ${prerelease} Succeeds; no Invalid version tag warnings on subsequent bumps cz changelog --dry-run after creating a SemVer2 prerelease tag Renders the release without warnings Multi-segment prerelease alpha.beta.1 in a custom tag_format Recognised and round-tripped correctly Plain version tag (no prerelease) Matched as before — the ? quantifier is preserved Tag with PEP-440-style prerelease (rc0, alpha1) Still matched — \w+ with no dot segments covers these Steps to Test This Pull Request git fetch fork fix/1614-prerelease-regex-allow-dots git checkout fork/fix/1614-prerelease-regex-allow-dots # 1. Targeted regression test. uv run pytest tests/test_tags.py::test_is_version_tag_accepts_semver2_prerelease_in_custom_tag_format -v # 2. Reproduce the bug, then verify the fix. mkdir /tmp/cz1614 && cd /tmp/cz1614 git init -b main git config user.name test && git config user.email test@test.com cat > cz.toml << 'EOF' [tool.commitizen] name = "cz_conventional_commits" tag_format = "${major}.${minor}-${patch}${prerelease}" version_scheme = "semver2" version = "0.0.1" update_changelog_on_bump = true EOF echo "# test" > README.md git add README.md cz.toml git commit -m "fix: initial commit" # First prerelease bump — creates tag 0.0-2rc.0 cz bump --prerelease rc --yes # Add another commit echo "change" >> README.md && git add README.md git commit -m "fix: add changes" # Second bump — failed before this fix with "Invalid version tag" error. # After the fix: succeeds and creates 0.0-2rc.1. cz bump --prerelease rc --yes # Changelog — emitted warnings before; should be clean now. cz changelog --dry-run Additional Context This is one of three bugs surfaced by the triage audit in #1964. The devrelease half of this fix is closely related to #1615, which addresses the companion issue where ${devrelease} substitution itself produced the wrong form; both defects share the same get_tag_regexes function (commitizen/defaults.py:151–165) as their root.

Open Graph Description: Description Closes #1614. Why When a project uses version_scheme = "semver2" together with a custom tag_format that includes ${prerelease} — for example "${major}.${minor}-${patch}${...

X Description: Description Closes #1614. Why When a project uses version_scheme = &quot;semver2&quot; together with a custom tag_format that includes ${prerelease} — for example &quot;${major}.${minor...

Opengraph URL: https://github.com/commitizen-tools/commitizen/pull/1972

X: @github

direct link

Domain: github.com

route-pattern/:user_id/:repository/pull/:id/files(.:format)
route-controllerpull_requests
route-actionfiles
fetch-noncev2:a9d47761-6bd8-fb84-f9b7-f3a920c14a7b
current-catalog-service-hashae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b
request-id8536:34DA5A:229D1D4:2FF0E0A:6A4F4615
html-safe-nonce22ce4637ca8cffb7fd865bfac0b5e126c7c9d9641b592ac5fbce057a7b7954e3
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4NTM2OjM0REE1QToyMjlEMUQ0OjJGRjBFMEE6NkE0RjQ2MTUiLCJ2aXNpdG9yX2lkIjoiNTEwNzExMTQzODQwMjQwNTkwOSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9
visitor-hmac7adcc0d8343c4cb4e61c84d5935d8c9c680255de7531f06053bc954973b6711e
hovercard-subject-tagpull_request:3654718626
github-keyboard-shortcutsrepository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///pull_requests/show/files
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/commitizen-tools/commitizen/pull/1972/files
twitter:imagehttps://avatars.githubusercontent.com/u/26526132?s=400&v=4
twitter:cardsummary_large_image
og:imagehttps://avatars.githubusercontent.com/u/26526132?s=400&v=4
og:image:altDescription Closes #1614. Why When a project uses version_scheme = "semver2" together with a custom tag_format that includes ${prerelease} — for example "${major}.${minor}-${patch}${...
og:site_nameGitHub
og:typeobject
hostnamegithub.com
expected-hostnamegithub.com
Noneb92d11c0aa4a77d54ef4af1078b6a15fb5a70a215b30c4ecf28889d5a8e656d9
turbo-cache-controlno-preview
diff-viewunified
go-importgithub.com/commitizen-tools/commitizen git https://github.com/commitizen-tools/commitizen.git
octolytics-dimension-user_id62252524
octolytics-dimension-user_logincommitizen-tools
octolytics-dimension-repository_id106127589
octolytics-dimension-repository_nwocommitizen-tools/commitizen
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id106127589
octolytics-dimension-repository_network_root_nwocommitizen-tools/commitizen
turbo-body-classeslogged-out env-production page-responsive full-width
disable-turbotrue
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release4b249b445842943ed31549e027f57a8ade9881ed
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/commitizen-tools/commitizen/pull/1972/files#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fcommitizen-tools%2Fcommitizen%2Fpull%2F1972%2Ffiles
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2Fcommitizen-tools%2Fcommitizen%2Fpull%2F1972%2Ffiles
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fpull_requests%2Fshow%2Ffiles&source=header-repo&source_repo=commitizen-tools%2Fcommitizen
Reloadhttps://github.com/commitizen-tools/commitizen/pull/1972/files
Reloadhttps://github.com/commitizen-tools/commitizen/pull/1972/files
Reloadhttps://github.com/commitizen-tools/commitizen/pull/1972/files
Please reload this pagehttps://github.com/commitizen-tools/commitizen/pull/1972/files
commitizen-tools https://github.com/commitizen-tools
commitizenhttps://github.com/commitizen-tools/commitizen
Please reload this pagehttps://github.com/commitizen-tools/commitizen/pull/1972/files
Notifications https://github.com/login?return_to=%2Fcommitizen-tools%2Fcommitizen
Fork 344 https://github.com/login?return_to=%2Fcommitizen-tools%2Fcommitizen
Star 3.5k https://github.com/login?return_to=%2Fcommitizen-tools%2Fcommitizen
Code https://github.com/commitizen-tools/commitizen
Issues 116 https://github.com/commitizen-tools/commitizen/issues
Pull requests 45 https://github.com/commitizen-tools/commitizen/pulls
Discussions https://github.com/commitizen-tools/commitizen/discussions
Actions https://github.com/commitizen-tools/commitizen/actions
Projects https://github.com/commitizen-tools/commitizen/projects
Security and quality 0 https://github.com/commitizen-tools/commitizen/security
Insights https://github.com/commitizen-tools/commitizen/pulse
Code https://github.com/commitizen-tools/commitizen
Issues https://github.com/commitizen-tools/commitizen/issues
Pull requests https://github.com/commitizen-tools/commitizen/pulls
Discussions https://github.com/commitizen-tools/commitizen/discussions
Actions https://github.com/commitizen-tools/commitizen/actions
Projects https://github.com/commitizen-tools/commitizen/projects
Security and quality https://github.com/commitizen-tools/commitizen/security
Insights https://github.com/commitizen-tools/commitizen/pulse
Sign up for GitHub https://github.com/signup?return_to=%2Fcommitizen-tools%2Fcommitizen%2Fissues%2Fnew%2Fchoose
terms of servicehttps://docs.github.com/terms
privacy statementhttps://docs.github.com/privacy
Sign inhttps://github.com/login?return_to=%2Fcommitizen-tools%2Fcommitizen%2Fissues%2Fnew%2Fchoose
bearomorphismhttps://github.com/bearomorphism
commitizen-tools:masterhttps://github.com/commitizen-tools/commitizen/tree/master
bearomorphism:fix/1614-prerelease-regex-allow-dotshttps://github.com/bearomorphism/commitizen/tree/fix/1614-prerelease-regex-allow-dots
Conversation 4 https://github.com/commitizen-tools/commitizen/pull/1972
Commits 2 https://github.com/commitizen-tools/commitizen/pull/1972/commits
Checks 20 https://github.com/commitizen-tools/commitizen/pull/1972/checks
Files changed https://github.com/commitizen-tools/commitizen/pull/1972/files
Please reload this pagehttps://github.com/commitizen-tools/commitizen/pull/1972/files
fix(tags): widen prerelease and devrelease tag regexes for SemVer2 https://github.com/commitizen-tools/commitizen/pull/1972/files#top
Show all changes 2 commits https://github.com/commitizen-tools/commitizen/pull/1972/files
32e983b fix(tags): widen prerelease and devrelease tag regexes bearomorphism May 9, 2026 https://github.com/commitizen-tools/commitizen/pull/1972/commits/32e983b176a0be9fb7e034e1ad8a9b3d07784fd7
099ae33 test(tags): add devrelease round-trip regression for #1614 bearomorphism May 9, 2026 https://github.com/commitizen-tools/commitizen/pull/1972/commits/099ae33b6dbc8e45d5c0d9bd9deaf417cfdb4996
Clear filters https://github.com/commitizen-tools/commitizen/pull/1972/files
Please reload this pagehttps://github.com/commitizen-tools/commitizen/pull/1972/files
Please reload this pagehttps://github.com/commitizen-tools/commitizen/pull/1972/files
defaults.py https://github.com/commitizen-tools/commitizen/pull/1972/files#diff-c951de16d627d82e01eb3ce8d7c4f0b28973ffe147520620762e7140ede2dd80
test_tags.py https://github.com/commitizen-tools/commitizen/pull/1972/files#diff-c2a8158c2ea75e325dc5d418fe408374d215b771f40be4a907dca380ad4a6701
commitizen/defaults.pyhttps://github.com/commitizen-tools/commitizen/pull/1972/files#diff-c951de16d627d82e01eb3ce8d7c4f0b28973ffe147520620762e7140ede2dd80
View file https://github.com/bearomorphism/commitizen/blob/099ae33b6dbc8e45d5c0d9bd9deaf417cfdb4996/commitizen/defaults.py
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/commitizen-tools/commitizen/pull/1972/{{ revealButtonHref }}
https://github.com/commitizen-tools/commitizen/pull/1972/files#diff-c951de16d627d82e01eb3ce8d7c4f0b28973ffe147520620762e7140ede2dd80
Please reload this pagehttps://github.com/commitizen-tools/commitizen/pull/1972/files
https://github.com/commitizen-tools/commitizen/pull/1972/files#diff-c951de16d627d82e01eb3ce8d7c4f0b28973ffe147520620762e7140ede2dd80
tests/test_tags.pyhttps://github.com/commitizen-tools/commitizen/pull/1972/files#diff-c2a8158c2ea75e325dc5d418fe408374d215b771f40be4a907dca380ad4a6701
View file https://github.com/bearomorphism/commitizen/blob/099ae33b6dbc8e45d5c0d9bd9deaf417cfdb4996/tests/test_tags.py
Open in desktop https://desktop.github.com
https://github.co/hiddenchars
https://github.com/commitizen-tools/commitizen/pull/1972/{{ revealButtonHref }}
https://github.com/commitizen-tools/commitizen/pull/1972/files#diff-c2a8158c2ea75e325dc5d418fe408374d215b771f40be4a907dca380ad4a6701
Please reload this pagehttps://github.com/commitizen-tools/commitizen/pull/1972/files
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.