-
-
Notifications
You must be signed in to change notification settings - Fork 301
feat(#173): support CalVer tag formatting #385
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Just following up. I think these changes should be ready to merge. The failing issues in CI are unrelated to the changes
Just following up. Is there anything I can do to help merge this change?
Hey Kyle, sorry for the late reply, I've been quite busy. Thanks for the works, looks good.
FMPOV this PR still needs some tests. Specially under the changelog area, I don't want to find myself fixing bugs on it.
I'd like to see some changelog tests where the users transition from semver to calver, and also if they start with calver from the beginning.
The same for bump.
The pipelines should also pass in order to be merged, otherwise the burden falls on us. Most of the latests PRs have passed so doing a rebase should fix the mypy errors for you.
I'd also want a new check on the cz init
format: commitizen/commands/init.py:96
.
I'd use a regex to find the year or month and tell the user something like:
seems you are using calver, for more information read:
link to the docs
@Lee-W any thoughts on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens when going from calver to calver?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This currently fails because create_tag expects version.release to be three integers (in Version, splits on '.' and maps to int) so a CalVer of 21.5.1.2
would fail here:
Line 226 in bec20eb
This will definitely need to be fixed. I'll check how custom formats (dashes, etc.) are handled by commitizen and give this more thought
Okay great thanks for the feedback! I converted this PR to a draft while I expand the test cases (After rebase, the tests are passing locally 👍🏻 )
-
Make sure CI passes (pending
git push -f
) -
Resolve conversation above for bump from calver to calver {Hacky fix, but pending next steps for better architectural approach: https://github.com/commitizen-tools/commitizen/pull/385#issuecomment-912887876}
-
Add tests for:
-
changelog
for to/from calver - checks that version sequence and tags are correct -
bump
- to/from calver
-
-
In
init
(see commitizen/commands/init.py:96), add if statement to check if the repository appears to be using calverfrom datetime import datetime year = datetime.today().year # Check current year and prior two years # For each year, check if 4 digit year is anywhere in version (i.e. 2021.* or *.2021) # Then check if starts with last two digits of current year (^21.*)
Update: also feel free to @KyleKing
on any future issues related to CalVer and I will do my best to troubleshoot and triage
Thanks, the proposal looks super good 👍🏻
Here a regex I think we could use for calver for the init
command:
^(\d{4}|\d{2})\.(\d{2}|\d{1})
I think this would cover this cases:
# valid
21.05.06a1
2021年5月6日a1
21.5.1.2
# invalid
234.34
1.2.3a1
21-05.06a1
I don't know if there's a regex for calver, I'm just assuming the following:
- calver would start with the year
- calver would include year (4 or 2) and month
- calver is separated by dot
I think that would be enough for the init, covering most of the cases.
I'd also want a new check on the
cz init
format:commitizen/commands/init.py:96
.
I'd use a regex to find the year or month and tell the user something like:seems you are using calver, for more information read:
link to the docs@Lee-W any thoughts on this?
IMO, we'll need to redesign the question follow. Depending on different bump method used, we should as different quetsions
I haven't forgotten about this and have some time today to implement the changes! I was interviewing, studying for finals in my summer course, and on vacations, so all good things. Apologies for my any excess notifications as I remember how best to update a fork from upstream 😅
The main problem is that CalVer is so poorly defined (i.e. YYYY.MM.DD
, YY.M
, YY.MM
, YY.MM.Build
, YY.Major.Minor
, etc.) which makes adding CalVer a big scope creep for commitizen
There are a couple of ways to proceed:
- Right now, users could use bumpver to increment the version following CalVer rules
- commitizen could still be used for pre-commit checks on commit messages and to generate a Changelog using the git tags created by BumpVer
- A naive approach in commitizen might be to limit users to either CalVer or SemVer so that CalVer users do not receive any of the bump versioning logic and the bump/SemVer logic can continue to assume between 1-3 dot-separated integers
- I think this might be reasonable but this tradeoff adds scope creep that might distract from the core functionality of automatic SemVer that commitizen provides
- A refactoring approach might be to always use an instance of a to-be-built Version class (rather than a string)
- The version instance would provide all the methods for bumping and later string formatting to encapsulate the complexity of how
tag_formats
could be configured. This approach would require a parser for thetag_format
to retrieve the metadata from the string version (i.e. convertsv21.01.32rc1
withv%y.%m.$major.$prerelease
to each respective component) - The Version instance could use any 3rd party library under the hood (such as continuing to use
packaging.version.Version
), but would likely always need to provide some additional logic to understand what values are dates (i.e. auto-generated) vs. SemVer values of interest - In any implementation, one problem that might arise is going between tag_formats (i.e.
$version
to%Y.$version
) - While this is likely the nicest way to implement CalVer and SemVer in peaceful coexistence (and better support more complex versioning schemes, such as in prerelease can't comply with the semver.org specification #150 / Support bumping local version #302 ), this would require a wide-ranging refactor
- The version instance would provide all the methods for bumping and later string formatting to encapsulate the complexity of how
- One further workaround might be to create a plugin that can handle implementing CalVer around commitizen, but I haven't given this much thought yet
Let me know what you think! Each approach has its own Pros and Cons so any future work really depends on the vision and project scope of commitizen
Update: added numbers to the list
Test BumpVer
Config:
[bumpver] current_version = "v2021.112400.0-alpha" version_pattern = "vYYYY.BUILD.MAJOR.MINOR.PATCH[-TAG]" commit_message = "bump: {old_version} -> {new_version} [ci-publish]" commit = true tag = true push = true [bumpver.file_patterns] "commitizen/__version__.py" = [ '__version__ = "{version}"', ] "pyproject.toml" = [ 'version = "{version}"', ]
Codecov Report
@@ Coverage Diff @@ ## master #385 +/- ## ========================================== + Coverage 97.90% 97.94% +0.03% ========================================== Files 39 39 Lines 1383 1408 +25 ========================================== + Hits 1354 1379 +25 Misses 29 29
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report at Codecov.
|
both point 2 and point 3 sound good to me. are they mutually exclusive? or should they be done together?
btw I'll host a development sprint in PyCon Taiwan on 9/26 (Sun.) 09:00 (GMT+8) ~
if you could split this one to subtasks, maybe I could ask whether others are interesting in implementing this feature
Thanks for all this deep investigation into calver @KyleKing
I've been giving a thought to a class version (maybe a protocol?), but I don't have much time now to go deep into it. Is specially interesting to me the use of a proper semver library for rc
, alpha
, etc.
If I understand you correctly, calVer with commitizen would only be useful to generate a changelog based on conventional commits, because libraries like bumpver already adress the bumping side, right?
Thanks!
@Lee-W, you're right that 2 & 3 aren't mutually exclusive. 2 could be implemented as an initial check for either $
or %
and not both characters, while 3 would be the internal refactoring for how the Version instance is handled. I was thinking about some sort of CzVersion
class like this example below:
class CzVersion: """General concept for a class that encapsulates all versioning complexity through a clearly defined interface.""" def __init__(self, version: str, tag_format: str): self._raw_version = packaging.Version(version) # Parse the tag format for the ordered metadata, then properly handle release and # add methods for changing SemVer, converting back to a string, etc. self._version = ... @property def semver(self) -> Tuple[int, int, int]: return (self._version.major, self._version.minor, self._version.patch) @semver.setter def semver(self, major: int, minor: int, patch: int) -> None: self._version.major = major self._version.minor = minor self._version.patch = patch def bump_calver(self) -> None: self._version.bump_calver() def bump_major(cz_version: CzVersion) -> None: cz_version.bump_calver() cz_version.semver = (cz_version.major + 1, 0, 0) def bump_minor(cz_version: CzVersion) -> None: cz_version.bump_calver() cz_version.semver = (cz_version.major, cz_version.minor + 1, 0) # Example cz_version = CzVersion('2021.05.1.2.3', '%Y.%m.$major.$minor.$patch') print(cz_version.semver) # (1, 2, 3) cz_version.semver = bump_major() print(cz_version.semver) # (2, 0, 0)
@woile, I made a demo branch using bumpver to increment CalVer (poetry run bumpver update
) and cz to update the changelog (poetry run cz changelog
). Diff: https://github.com/KyleKing/commitizen/pull/5
Note: I tried poetry run bumpver update --patch
and the SemVer component reset to 0.0.0
and the build incremented a lot, but that is likely an issue with the commit/tag history on commitizen (i.e. would have worked on a fresh project)
Maybe bumpver could be used by commitizen internally for parsing versions and bumping? There is a lot of good code in the package and the update
CLI command demonstrates how that would be implemented: https://github.com/mbarkhau/bumpver/blob/master/src/bumpver/cli.py#L571-L602
I have come back to this PR a few times, but I think I've settled on the idea that CalVer and SemVer need to be separate and while mixing the two could be possible, in practice tools will not work as expected and I'm not sure there are really any good reasons to do so
CalVer is perfect for packages like certifi
which is bundling the latest version of certs and commit history is for the most part irrelevant. While packages like my calcipy
project require much more clarity for breaking changes, which is obscured by including date information
Additionally, poetry, npm, and other managers don't work well with date-based versioning schemes where the date information is first (i.e. ^*.1.*
for 2022年1月3日.1
). Not to mention there are additional issues when dashes or underscores are used or when more than three numbers are used
Overall, I think commitizen should keep focused on SemVer and this PR and issue can be closed. I'm personally staying with or returning to SemVer on all of my projects (which while they were on CalVer, they luckily have little adoption. Yay obscurity!)
Thanks for your time reviewing this PR!
Closes: #173
Description
Adds flexible support for CalVer using
strftime
Checklist
./script/format
and./script/test
locally to ensure this change passes linter check and testExpected behavior / Steps to Test This Pull Request
Include
strftime
code intag_format
(i.e.cz bump --tag-format="%Y.%M.$version"
)FYI: there are type tests failing unrelated to this PR. All of
pytest
, formatting, and other tests pass locally except formypy