allegro / axion-release-plugin

Gradle release & version management plugin.
https://axion-release-plugin.readthedocs.io/
Apache License 2.0
559 stars 149 forks source link

Working with git flow and develop branch #52

Closed coco1979ka closed 7 years ago

coco1979ka commented 9 years ago

I am using the git flow model to manage my repository. Unfortunately this leads to a problem with the currentVersion task. All my work is going to the development branch. At some time I make a release, let's say 0.1.0. My master now contains a Tag 0.1.0. Now I start working for 0.2.0 in development. First Problem: Current Version in development branch still is 0.1.0-SNAPSHOT (which I can solve by setting a Tag with release-0.2.0-alpha) Second Problem: I make a hotfix for version 0.1.0 which leads to a Tag release-0.1.1 in Master, but with the merge of the hotfix branch back to development branch, currentVersion now is 0.1.1-SNAPSHOT, because now the Tag of my first release also is known in the development branch. Is there a solution with a special versionCreator? bildschirmfoto 2015-02-19 um 10 57 38

adamdubiel commented 9 years ago

I see the problem. axion-gradle tries to find first tag in commit history, without evaluating if there were any higher-version markers before this one. This behavior could be changed to:

This would solve the problem and i think it's quite easy to implement.

coco1979ka commented 9 years ago

I agree, but it only solves the second problem and implies manually setting the nextVersion marker. If it would be possible to search for a merge commit in history (usually this is automated commit message like "merge branch release/0.1.0"), it could be improved by:

With this convention based version increment, it would only be necessary to set the next version marker, if a new major release is planned. So I would suggest a git flow version creator, which can be configured with a few options like:

I could start to implement it and send you a pull request.

adamdubiel commented 9 years ago

Do you mean something like i proposed in #50? :) Maybe we should merge those issues and come up with one solution.

coco1979ka commented 9 years ago

Yes this looks quite similar. The feature should be implemented based on:

Second link is a high level extension to git, which is very useful, as it handles merges automatically based on the current workflow step.

martinda commented 9 years ago

I like the idea of coming with one solution between #52 and #50 if possible. To help with the discussion, I have created a couple diagrams that I'd like to share (made in google draw). The problem I'd like to address is the long term maintenance of releases (they might need patches and new features). What I present below is not a pure form of the famous Git Flow, it is a variant.

I have a project where multiple applications with lots of common code are created and maintained in one branch (master). They are kept separate by the build scripts and can be built and released by choosing the right build script.

In the following diagram, the master branch holds the code for all releases (no development branch). I also show one bugfix, and I show that it is merged into the release branch, and also back to the master branch. Git Workflow master with single release branch

The following diagram is similar, with two release branches. Git Workflow master with multiple release branches

Update (2015-02-24): The diagrams above do not support a "feature freeze" like the Git Flow does with its definition of release branches. I now consider this flaw to be a non-starter for me.

The decision to initiate a commit of a bugfix or a feature into any branch is a decision only the user can make. The start of a release is also a decision only the user can make. Of course there should be a CI server involved.

I am not sure what scope of the whole problem the axion-release-plugin should cover. I am all for keeping it simple. My ideas are not entirely clear on this yet. At first I thought it would be useful if the plugin created the release commits, but I am not so sure anymore. I think that's a job for the CI server. It looks to me like semantic versioning should only be concerned by computing the version number on a given commit by looking at the prior commits and where the merge arrows come from.

I do not use snapshot or pre-release numbers.

adamdubiel commented 9 years ago

Thanks for the graphs and input! I get best ideas and understanding of problems while writing draft code, so i will wage on that bit more when i start coding. So far i think the common ground between both issues is making axion-release track history of current branch and decide which part of version should be incremented. As most things in this plugin, i will try to make this "strategy" easily customizable, so even if the end result won't fit the exact need, you will have the chance to override it with own implementation (having the data like merged branches available).

coco1979ka commented 9 years ago

@martinda having multiple releases, which must be supported is a common issue. Git flow addresses this issue with support branches. So usually with each major release a support branch is created and Hotfixes can be cherry picked from one branch into another. I tested the plugin with support branches and a special version creator for "support/.*" which works perfectly for me. Btw. I do not use the createVersion task because git flow does all the merging/tagging stuff for me. @adamdubiel could you publish your working source, so we could test the behavior? I very like the idea to let the user implement its own strategy.

adamdubiel commented 9 years ago

@coco1979ka i will as soon as i have any - didn't have time to start yet.

coco1979ka commented 9 years ago

@adamdubiel okay, let me know, when I can help you.

martinda commented 9 years ago

@coco1979ka when you say "let the user implement their own strategy", do you mean the branching model strategy or the versioning model strategy?

Disclaimer: I have not used any flow right now, just trying to sort these things out, it's hard!

It seems there are two aspects: the branching model and the versioning model. It looks to me that once the branching model is determined (git flow or other), one would want to implement a versioning model on top of it. So it looks to me that the axion-release-plugin is about to make some important decision: will it commit itself to a specific branching model?

adamdubiel commented 9 years ago

@martinda my goal is to give both of you tools to implement versioning model (by which i mean: how to interpret history of current commit to calculate/get version number). I don't think i need to commit to any specific branching model to do this.

Jarodiv commented 9 years ago

Any news on this topic? I ran into the same problem a few month ago, which ever since causes touble everytime a feature release (1.x.0) is preceded by a bugfix release (1.0.x), which happens quite often.

adamdubiel commented 9 years ago

I don't know if it will resolve your issue completly, but a nifty feature - custom incrementers - have been added in fresh-released 1.3.0 version. You might want to check branchSpecific predefined rule, which allows you to use different schemas based on branch (like bump patch only on bugfix/* branches and minor on master). See docs for more.

coco1979ka commented 9 years ago

Hi Adam,

I just tried to implement my own Strategy... But I still cannot manage it to fit perfectly to my workflow.

What I tried to do is to create a branchVersionCreator and incrementer with the following rules:

1.) If on develop, incrementMinor - works perfectly. I never call a release task on develop 2.) If on branch release/ use version + rc1, incrementPrerelease strategy. My CI Server should call the release task here to set the tag 3.) If on master generally increment Patch, if previous tag was a prerelease tag, use version and release 4.) If on branch hotfix, incrementPatch and add rc1

So the problem is, that currentVersion outputs the correct version (+SNAPSHOT), but if I use the release task I get a wrong version as tag. I'm not sure how to handle this... Should it be in the serialization part? If yes, I would need more information from the VCS (like version and position).

Perhaps you have an idea, how to solve this. A prototype of the branchVersionCreator looks like this:

'release/.*': { version, position ->
     if (position.onTag) {
         version
      } else {
         "release" + position.branch.substring(position.branch.indexOf("/")) + ".rc1"
 }
adamdubiel commented 9 years ago

Okay, i will test it and come back with results.

coco1979ka commented 8 years ago

Hi Adam,

I now wrote a plugin which uses your plugin and supports a release naming scheme that fits to the git flow workflow. It automatically uses prerelease versions in hotfix and release branches. It increments the patch version in master branch except there was a prerelease version tag before. In this case it will use the prerelease version as a non snapshot version. In a release branch it calculates the version from the branch name and then increments the prerelease version.

Example: 1.) I branch of develop to release/3.0.0 2.) The calculated version now is 3.0.0-rc1, next 3.0.0-rc2 3.) I merge release/3.0.0 to master 4.) Calculated version now is 3.0.0 (although my master increments the patch version)

The only problem is the Release Task: I have to force the version with release.forceVersion, since your releaser has its own logic to create the tag. I could upload the sources to github, perhaps you can have a look at it.

EDIT: I have to mention, that I use Stash, which merges differently from the original Git Flow extension. It first merges to master and after that from master to develop. So the version in the develop branch is also correct, because the plugin sees the last tag in master branch. In my example the next version in develop branch will be 3.1.0-SNAPSHOT, which is correct. I can still decide if I use the next version marker, if I want to switch to a 4.0.0 version, but it is not necessary, as I can decide this with my next release branch too.

Regards,

Christian

adamdubiel commented 8 years ago

Yes, if you can share the code in any way that might be useful, i never used automagic branch management from Stash (it's our internal repo as well) so i don't know what to expect exactly.

adamdubiel commented 8 years ago

Can you also post the Strategy you mentioned in one but last post? It should not behave like described, code would be perfect :)

rafik777 commented 7 years ago

@coco1979ka @adamdubiel Is there a working, described solution which resolves problems described in first comment?

ProTrent commented 7 years ago

I'm running into this same basic problem with git-flow. If I mark a release on the release branch before it merges to Master, when the merge back to develop happens, the version gets reverted back to a previous version (since any 'markNextVersion' tags will now show up after those newly merged tags in the the git-tree). Any ideas or status updates here?

agusmba commented 7 years ago

@ProTrent I have solved this by using custom incrementers like @adamdubiel said.

    // Incrementing policy
    versionIncrementer 'incrementMinor'  // default
    branchVersionIncrementer = [
       'master': 'incrementPrerelease',
       'release/.*': 'incrementPrerelease',
       'hotfix/.*': 'incrementPrerelease'
    ]

You can see this real world example here

No need to mark next version normally.

ProTrent commented 7 years ago

@agusmba I don't think that will solve what I'm currently seeing. I'm working with @adamdubiel right now to come up with a better solution overall. The biggest issue is when either a release branch or a master branch gets merged back into the develop branch and whatever tag was last released on either of those two branches suddenly becomes the new 'base' version. This would be the case even if I had created a 'release' tag on develop that was greater than the one merged from master during a hotfix. The idea now is to find all of the tags and then find the largest one and return that.

ProTrent commented 7 years ago

@agusmba, I tried out what you suggested, and so far it appears to be working... At least for the current status of my code. I'll walk through the whole flow and verify it. I'm still not sure why it works, but if it does work, that will be great!

ProTrent commented 7 years ago

@agusmba, it didn't end up covering this use case. Here's the use case:

  1. Create a release branch '1.0.0'
  2. Tag the development for next version at '2.0.0'
  3. Make mods to either branch
  4. Perform a hotfix and release bump on the hotfix branch
  5. The resulting merge will bump the development branch down to some 1.0.1 or other version...
agusmba commented 7 years ago

@ProTrent yes, my configuration breaks down a bit when you need to increase the major version number. In my case I can live with it. I'm not sure this will be an issue often enough to warrant complicating matters much. But of course, your mileage may vary.

Note that in your last example, develop woud go "down" to 1.1.0-snapshot, which is undesired since you were "working" on 2.0.0-snapshot. There are several workarounds for this, but they need an extra step of tagging develop again, or procedural changes in the sense of only marking 2.0.0 when you create the release branch...

Mmm, would a hot-fix 1.0.1 in master break also your 2.0.0 release branch if merged? probably. In this case I'd re-tag my release branch with 2.0.0-rc[X+1]

ProTrent commented 7 years ago

@agusmba To answer your last question, yes, hotfixes or any merge from master or any release branch back into develop with a lower tagged version would cause the version to drop. The latest pull request that @adamdubiel is adding now should allow somebody to specify they want the highest version, so any merge of some branch back to develop should still result in the higher version being pulled.