I mentioned in a meeting recently that I would like to find a better way to make releases with by leveraging (or another CI tool) to save us work and as a result time.

The main problem currently is created because of the flexibility of using Maven’s SNAPSHOT dependency mechanism. Currently when CC does a build, it just creates a simple SNAPSHOT build and does not change the pom file at all. This is a good thing, as it pushes the latest out to the shared repository and then when developers do their next build they automatically get the latest , even if they are not working directly on that project.

The down side is that the builds created by CC are not formal releases and so are not ready to go to QA or production. When we do want to move something to QA we have to stop and do a manual release, and then a second manual release for Production. This is caused by a few reasons:

  1. Currently when CC does a build there is no tag applied to our CVS repository to mark the build, which means the build is not repeatable. This is intentional currently, since there is really no need to be able to repeat a SNAPSHOT build. This can easily be solved though, we can have CC apply a tag, but that still leaves the next issue which is more significant.
  2. Because CC is making a Maven SNAPSHOT build, it does not resolve the SNAPSHOT dependencies to other projects, so the build is still not repeatable, even if we had a CVS tag applied.
  3. The QA releases are tagged/named with suffixes like 1.0.0-rc## (for release candidate) or 1.0.0-beta## (where the #s are numbers indicating iterative releases to QA are being made) to clearly indicate they have not passed QA yet.
  4. Because the QA releases are tagged/named in such a way a whole second release needs to be done to clean up the tag/name to just something like 1.0.0

Here is what I think needs to happen instead:

  1. We continue to have CC create and publish SNAPSHOT builds to the shared repository, just as it does now, no changes.
  2. We add an extra step to the CC build that (on a successful build) tags CVS, then creates a branch based on that tag.
  3. It then does a checkout on the newly created branch.
  4. It then updates all of the pom.xml files where SNAPSHOT versions are used in dependencies to other projects/plugins etc. More on these updates in a second.
  5. It then checks those updated poms back into the branch.
  6. It then does a proper Maven release on that branch and publishes that to the shared repository. That is the end of life for that branch, it only exists to allow the release to be made, nobody would ever use this branch directly.

So, for regular development work, nothing changes, you would continue to use SNAPSHOT versions where appropriate. But, we now no longer need to do a special release when we go to QA, and in addition, if a QA build gets approved, it can go straight to production, we do not need to do a special production build anymore.

This all sounds good, but the tricky part is the “updates the poms” part that I mentioned above in the 4th bullet point. I do not think this functionality exists today in Maven.

So here is how I think it would work:

  • We change to use build numbers that look like this “<major version>.<minor version>.<micro version>.<build number>” – the big difference is the “build number” part. Whenever there is a successful CC build, this number gets incremented. One of these releases with a unique build number will be given to QA. If QA approves that build number, that same build number goes to production.
  • Once a build goes to production, the major, minor and/or micro version numbers get incremented (just like we do now), and the build number automatically rolls back to zero.
  • When CC does a build, it examines the pom file of the project for dependencies to other projects/plugins that are SNAPSHOT versions. It then looks in the shared repository for the latest build number of those artifacts and changes the pom to depend on that specific build number instead of the SNAPSHOT. For example, if CC finds a dependency to version 1.0.1-SNAPSHOT of artifact-X, CC goes to the shared repository and finds that the highest build number for that release is 1.0.1.0064, so it changes the dependency in the pom to be that release number.
  • CC continues until there are no SNAPSHOT dependencies left.
  • Now CC checks in the updated pom (or poms plural if it is a multi-module project) into the branch.
  • Now CC just does a normal Maven release based on the branch and deploys the release to the shared repository. However, it needs to determine the correct build number for the main project being released. Basically this is the same algorithm used to determine the highest build numbers for all of the dependencies that we just finished. Except this time when we find the highest existing build number, we add 1 to it and use that for the release process.
  • The Maven release process finishes with the project in question being released with an incremented build number based on a branch in CVS. The trunk is unchanged, hence the normal SNAPSHOT releases continue as before.

That’s it.

Now I see the Maven release plugin has had some updates in recent releases with features like the non-interactive build now being possible by passing build numbers on the command-line. But I do not see any mention of the type of functionality I outlined above.

Am I just missing it, or is there a project out there for us to sink our teeth into?