Skip to content
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

fix(release): allow multiple tags on the same commit for separate branches #2621

Draft
wants to merge 12 commits into
base: main
Choose a base branch
from

Conversation

abdsahin
Copy link
Contributor

Example use case: after testing a pre-release, if all good with the pre-release, it should be promotable to the next stage with the same commit.


By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@mrgrain
Copy link
Contributor

mrgrain commented Apr 19, 2023

Hi @abdsahin Can you confirm the scenario with you. Do I understand this correctly, with this PR merged, if the release workflow (or task) is run multiple times in a row a new version is released everytime?

I'm also a bit confused how one would achieve the change without a new commit, since you have to add/remove/modify the prerelease property.

@abdsahin
Copy link
Contributor Author

Following is from the content of the .projenrc.ts

defaultReleaseBranch: "main",
prerelease: "pre", //main branch is designed to be a pre-release of the major release
releaseBranches: {
  "release/0.x": {
    majorVersion: 0,
  },
},

The use case is our developers are creating features branches and merges to main. Ones all tests are done, we create another merge request to release/0.x.

Now, assume the merge strategy is fast-forward without "squash commit" ,so no merge commits are created. release/0.x and main has the same commits.

I am trying to create a re-usable library, cannot be certain which teams will use merge commits and which not, therefore I thought this might be an improvement, but happy to hear your feedback.

@mrgrain
Copy link
Contributor

mrgrain commented Apr 19, 2023

Thanks for the explanation @abdsahin ! This is very cool usage of the release branch feature. It didn't occur to me yet that you could do it that way! 🤯

I think my main concern here is that current users might be working on the assumptions that releases are idempotent. By that I mean that running the release task/workflow on the same commit they will get exactly one version.

It seems (but I'm not 100% sure) that this PR changes this behavior. So I'd like to understand better if that's a desirable change to the default behavior. For example if the re-releasing can only happen under very specific circumstances, we might be okay merging it as a default. If not, we will need an option for it.

If any default behavior is changed, we should run campaign before applying it.

@abdsahin
Copy link
Contributor Author

For the above configuration I mentioned, if there is a v1.0.0-pre.0 release on main branch and if you apply the same commit on release/0.x branch, you try to release v1.0.0-pre.0 again on the wrong branch.

The PR changes only this behaviour by strictly checking the current branch.

Probably everyone is using merge commits and don't see that issue, so I can enforce using merge commits as well.

@abdsahin
Copy link
Contributor Author

@mrgrain , how about adding a new property named branchIdenpotentRelease( I am open to suggestions for the name), set it as false by default and if true then we can activate the changes in this PR?

I can update the PR accordingly.

Copy link
Contributor

@mrgrain mrgrain left a comment

Choose a reason for hiding this comment

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

Yeah I think a property would definitely be the safest option. But tbh I'm still trying to understand how this change is working. It might be okay to be released as a default.

Comment on lines 131 to 137
const latestTagPrerelease = getPreRelease(latestTag);
// returns true if the latest tag on this commit is on the same release branch
const latestTagSamePrerelease =
(prerelease &&
latestTagPrerelease &&
latestTagPrerelease[0] === prerelease) ||
(!prerelease && !latestTagPrerelease);
Copy link
Contributor

Choose a reason for hiding this comment

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

I have a hard time understanding what this check is semantically doing.

Could you try and refactor this somehow? Maybe using helper methods that are descriptively named.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried to explain it a bit better.

@codecov-commenter
Copy link

codecov-commenter commented Apr 20, 2023

Codecov Report

Merging #2621 (52a65f9) into main (0825edd) will increase coverage by 0.00%.
The diff coverage is 100.00%.

❗ Your organization is not using the GitHub App Integration. As a result you may experience degraded service beginning May 15th. Please install the Github App Integration for your organization. Read more.

@@           Coverage Diff           @@
##             main    #2621   +/-   ##
=======================================
  Coverage   96.30%   96.31%           
=======================================
  Files         181      181           
  Lines       33385    33401   +16     
  Branches     3061     3066    +5     
=======================================
+ Hits        32153    32171   +18     
+ Misses       1232     1230    -2     
Impacted Files Coverage Δ
src/release/bump-version.ts 99.44% <100.00%> (+0.02%) ⬆️

... and 1 file with indirect coverage changes

@abdsahin
Copy link
Contributor Author

Yeah I think a property would definitely be the safest option. But tbh I'm still trying to understand how this change is working. It might be okay to be released as a default.

@mrgrain, is it clear now? Do you still think we need a property to enable that behavior?

(!prerelease && !latestTagPrerelease); // If we are bumping a regular release( example: 1.0.5) now and also latest release was a regular release

/**
* Skip the bump only if the current commit is already tagged within the same branch
Copy link
Contributor

Choose a reason for hiding this comment

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

With all the previous assertions, I don't follow how we can make the conclusion that the current commit is tagged on the same branch. Can you elaborate on this please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Each branch is mapped to a specific prerelease component.

  releaseBranches:{
    "release/1.x.alpha": {
      majorVersion: 1,
      prerelease: "alpha"
    },
    "release/1.x.beta": {
      majorVersion: 1,
      prerelease: "beta"
    },
    "release/1.x.rc": {
      majorVersion: 1,
      prerelease: "rc"
    },
    "release/1.x": {
      majorVersion: 1
    }
  }

So now

  • If it is a regular release and getPrereleaseComponent(latestTag) returns null meaning latest release was also a regular release.
  • If it is a prerelease, we compare the current commit prerelease component with the latest release one. As suggested I will try to add that into a helper function.

Copy link
Contributor

@mrgrain mrgrain left a comment

Choose a reason for hiding this comment

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

Okay thanks for the explanations so far. I still have one question of understanding, but I'm sure you'll be able to clear that up for me.

We will need a new options for this that is false by default. Something along the lines of allowMultipleReleasesOfSameCommit and makes sure the docstring explains this scenario in detail.

src/release/bump-version.ts Outdated Show resolved Hide resolved
if (releaseTags && compare(releaseTags[0], prereleaseTags[0]) === 1) {
if (
releaseTags &&
releaseTags.length > 0 &&
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this fixing a bug or something?

If it is required, let's also pull this out into a helper function.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes this is for bug fixing, there are cases where releaseTags is returned as empty array and going directly into the if case rather than else.

@mrgrain
Copy link
Contributor

mrgrain commented Apr 25, 2023

Alternatively taking a step back @abdsahin - Maybe what we actually want here is a --force option on the command that users can use to always force a new bump. You could then implement additional checks in userland.

I think I would very much prefer this alternative option. Do you think this would allow you to solve your problem in userland?

@abdsahin
Copy link
Contributor Author

Alternatively taking a step back @abdsahin - Maybe what we actually want here is a --force option on the command that users can use to always force a new bump. You could then implement additional checks in userland.

I think I would very much prefer this alternative option. Do you think this would allow you to solve your problem in userland?

I believe the option ** allowMultipleReleasesOfSameCommit** is a better choice since there is a complex logic to decide when to use --force. We can even make it per branch rule. I will update the PR soon.

@abdsahin
Copy link
Contributor Author

@mrgrain , I've updated the branch, let me know if it looks better, we merge or close it accordingly.

@abdsahin abdsahin requested a review from mrgrain June 14, 2023 08:39
@abdsahin abdsahin marked this pull request as draft June 14, 2023 11:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants