Skip to content

Determine bump type between two different versions #262

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

Open
tlaferriere opened this issue Jun 10, 2020 · 8 comments
Open

Determine bump type between two different versions #262

tlaferriere opened this issue Jun 10, 2020 · 8 comments
Labels
Enhancement Not a bug, but increases or improves in value, quality, desirability, or attractiveness Release_3.x.y Only for the major release 3

Comments

@tlaferriere
Copy link
Contributor

Use Case

When using a staging branch, you can stack changes on the staging branch by bumping the prerelease number for every change pushed.
Determining whether to use a major, minor or patch bump on each push requires you check the whether the current prerelease version has had the appropriate bump with respect to the currently released version on master.
For example, pushing a minor change to staging when staging is at 1.0.1-rc.1 and master is at 1.0.1, the appropriate bump here would be bump_minor() since the staging version is not more recent than the master version.
Subsequently (when staging is at 1.1.0-rc.1 and master still at 1.0.1), a minor change or a patch change would not bump minor or patch, but instead bump the prerelease.
On the other hand, a major change would require a bump_major().
Hopefully the example illustrates where you would need to find the bump type needed to go from one version to another.

Situation

At the moment there is no simple explicit (or implicit) way to determine the diff bump between versions.
One must compare each part of the version to determine which is the bumped part.
This is trivial code that is prone to errors since it must be rewritten by anyone who wishes to achieve this task.

Proposition

Write a function maybe called diff that takes two VersionInfo objects and returns the differential bump (type: tbd).

At first, I was going to request that __sub__ be implemented for VersionInfo, but I figured out what I really wanted to do with this feature. I do think this would be a possible implicit way to achieve this goal, but there are simpler and better ways to do this explicitly, such as looping through the parts and returning the first one that is different.

@tomschr tomschr added Enhancement Not a bug, but increases or improves in value, quality, desirability, or attractiveness Release_3.x.y Only for the major release 3 labels Jun 11, 2020
@tomschr
Copy link
Member

tomschr commented Jun 11, 2020

Thanks @tlaferriere for your idea! Haven't thought of that, that's an interesting use case. 👍

I marked it for release 3 of semver as I think, this is a completely new functionality. Would prefer to implement this in a major release.

Not sure if I completely understood the details, therefor some questions:

  1. Should the "diff" return the first part which could be found or all parts?
    For example, the "diff" between 1.0.0 and 1.1.5 would be to raise the minor (1.0.0 -> 1.1.0) and then set the patch part (1.1.0 -> 1.1.5).
  2. As you already noted, what type should be the "diff"?
    That probably depends on how we consider point (1). It could be a string if we only want to know "major", "minor", "patch" etc. Or it could be a tuple/list if we allow more.
  3. Are you trying to find the appropriate (bump) function or just the version part?
  4. Do we allow a "diff" only from low to high?
    What happens when you try to create a diff from 2.0.1 -> 1.0.5? There is no bump version which could do that (although there is .replace). Should we raise an exception?

@tlaferriere
Copy link
Contributor Author

  1. Should the "diff" return the first part which could be found or all parts?

Because IMO the biggest use of the "diff" would in determining the relevance of a potential bump, I believe that only returning the first part raised would be enough for most uses. It would keep the complexity at a minimum, which is important for its maintainability.
There could exist uses for having all the different parts returned, but to be really useful, I believe it would also require knowing how many times each bump was applied. This is would then be more like a subtraction, and would probably warrant implementing __sub__ for VersionInfo. But that's out of scope for this issue (although I am curious to see if anyone has a use case for this).

  1. As you already noted, what type should be the "diff"?

It could be a

  • string, which can be used as:
    • an argument to getattr in order to get the same part of another version
    • an argument to VersionInfo.next_version
  • int, which can be used as:
    • an index to get the same part of another version

Numerically, I'm leaning towards the str return type.

  1. Are you trying to find the appropriate (bump) function or just the version part?

In my use case it would be simply the part, in order to know whether or not to apply the bump that I could apply. Thanks to VersionInfo.next_version, having the part as a string would allow us the obtain the appropriate bump function.

  1. Do we allow a "diff" only from low to high?

Because of the unidirectionality of the bump functions, I think we can ignore the order in which the versions are passed in the function, just to KISS.

@tlaferriere
Copy link
Contributor Author

@tomschr I think we should disuss the location of this function.
As I mentioned here, it seems this project is on a trend of centralising functionality in the VersionInfo class.
Therefore I think this new function should be a method (with signature (self, other: VersionInfo) -> str) of VersionInfo.
Does this make sense?

@tomschr
Copy link
Member

tomschr commented Jun 13, 2020

@tlaferriere
Thanks for the detailed description. 👍 From what I've seen, it does make sense. Unless I've overlooked something important. 😉

@tomkcook
Copy link

tomkcook commented Feb 7, 2025

I see this is still open from 2020 but wanted to come here to say something similar.

It's a significant pain that python3 -m semver bump prerelease 1.1.1 produces 1.1.1-rc1. This is a defect, in my view. bump should always increase the version number and 1.1.1-rc1 is a version less than 1.1.1. The correct output would be 1.1.2-rc1.

For a point of comparison, the semver nodejs package does this:

$ semver -i prerelease 1.1.1
1.1.2-0

I realise this is a different point to the one raised in this ticket but it is trying to address the same underlying problem: It is very difficult to produce a useable prerelease version from an existing released version number. You can't just bump both the patch and the prerelease versions unconditionally, because the patch version only needs to be bumped if there isn't already a prerelease tag in the version number.

@tomschr
Copy link
Member

tomschr commented Feb 11, 2025

@tomkcook Thanks for your comment! I'm also not happy, but changing it would introduce a backward incompatibility that could break existing code which rely on the current behavior.

I'm thinking about to change this and try to decide about these options:

  1. Release semver 4 and change the behavior of it.
    Pro: Would fix the issue, existing code does not need to be changed.
    Con: Would leave all previous major releases with this flaw.
  2. Introduce a new optional parameter in bump_prerelease which could switch between new and old behavior.
    Pro: Makes it easier to migrate.
    Con: Optional parameters can easily be forgotten, too confusing?
  3. Introduce a new method (inc, bump etc.) which doesn't have this issue and deprecate all other bump_* methods.
    Pro: Better naming; internally it can still use the old code
    Con: Existing code needs to be maybe adjusted
  4. Just fix the issue in version 3.1.0 and deal with the fallout later.
    Pro: Fixes the problem instantly
    Con: May break existing code if some rely on the current behavior.

Probably there are other options. I am currently considering what the best option would be. 🤔

Maybe you have an additional idea?

@tomkcook
Copy link

@tomschr I agree those are the available options. Personally, I would go for option 3. Deprecation doesn't mean every piece of code needs to be updated immediately.

@tomschr
Copy link
Member

tomschr commented Feb 14, 2025

Thanks @tomkcook for your opinion. Just to let you know, I forgot to mention that recently I've merged PR #460 which could mitigate the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Enhancement Not a bug, but increases or improves in value, quality, desirability, or attractiveness Release_3.x.y Only for the major release 3
Projects
None yet
Development

No branches or pull requests

3 participants