When should the code be tagged? How is the release/branch/tag process related to deployment? How should we branch during the release process? Should we branch early on in the release? Or, should we just continue on in trunk and only branch when we need to start parallel development? Who performs the release and from what machine? Do we run this plugin from Hudson?
This is a sample of some of the questions I’ve been asked by customers over the past few years, and, believe it or not, my answers are always a little less than satisfying. My stock answer to one of these questions is along the lines of: Well, Maven has a certain set of opinions about how you should manage releases, but it isn’t set in stone and there are as many variations in a project’s release process as there are corporations that code Java.
What we call “The Release Process” is seldom simply a technology problem and more than often involves process, organizational structure, and definitions of responsibilities. These are the intangibles that lead to the reality: everyone’s “Release Process” tends to be unique, especially as your projects become more important and more complex.
The Maven Release plugin provides one model that solves a few of the technical problems involved in the release process. Put simply, the Release plugin provides a low-level operation that involves the following sequence of operations:
- Prepare: build, test, release version update, commit, tag, next snapshot version update, commit
- Perform: export a release from SCM, run the deploy goal
To be clear, this is all the Release plugin does, it isn’t a substitute for organizational process, it wasn’t designed to be customized to meet your specific process.
This post is motivated by a recent interaction – I was talking to someone about how the Release plugin didn’t satisfy a particular quirk of a deployment process in that it wasn’t designed to start and stop application servers and deploy WAR files to various production networks. Inherent in the question was the assumption that the Maven Release plugin would be able to solve all of these extra problems that the questioner had tacked on to it.
To answer the question I had to enumerate some of the assumptions made by the Release plugin. I can tell you about these baseline assumptions and you can decide whether or not something like the Maven Release plugin is appropriate for you.What are these assumptions?
- Your codebase is going to be versioned and released as a “unit”. What does this mean? This means that you are going to be releasing an entire project at once with all of its submodules. In Subversion this means that you are running the Maven Release plugin from a trunk directory or from a named branch. In Github it means that the Maven Release plugin is going to operate on an entire repository.
- You are using an SCM tool and a repository manager. This might seem like an odd assumption to put in this list, but it is here for a reason. Maven releases, distributing binary artifacts, versioning source code – it all depends on the fact that you are using a standard SCM tool in a standard way and a compatible repository manager. Maven works because it follows standards.
- You are performing your release from a single, “versionable” unit in SCM. Don’t break the Subversion “trunk”, “tags”, “branches” convention, and in Git don’t try to store massive projects in a single Git repository and selectively release portions of projects (that’s not what Git was made for).
- You are using standard version numbers. Around 20% of the customers I speak to don’t understand that the version number pattern isn’t optional. If you are trying to tweak the version format to include dashes or other characters instead of numbers, or if you are trying to prefix versions with letters (“r07″), you are going to run into problems.
- You are publishing artifacts to a repository. A lot of people take a look at the deploy phase and try to make it “deploy” an application to a production network. This is easy to do if you are creating a WAR file, one very reasonable idea is to just add in some options to SCP the file to the right server and follow up your release plugin call with a server restart. I’m here to say this isn’t how Maven was designed to work. Deployment, production automation, all of these things are useful, but I caution people mistaking the Maven lifecycle with something akin to Puppet. If you want to get into the business of production automation through Maven, create a separate process. In my own experience, I’ve found that conflating builds with production automation is a very sticky tar pit and that it makes much more sense to view Nexus as a neutral staging area for production-bound binary artifacts.
If you break any of these assumptions, my recommendation will almost always be that you should figure out a way to script your release process (with bash or something straightforward). Or you should look into writing a custom version of the Maven Release plugin. Now, the Maven Release plugin is large chunk of code, so I wouldn’t recommend that anyone branch locally and customize. What I would recommend is that people invest the time necessary to understand how to write a custom plugin. GMaven is a great place to start because Groovy is accessible and you can do anything you need to do with it. In short, if you have a quirky release process that requires customization, don’t try to shoehorn Maven to your process, create a custom plugin. In the end it’ll be worth the effort, and you can avoid having to battle a plugin who’s assumption you don’t agree with.
I will always try to convince a customer to adopt convention, but if they persist in doing anything off the Maven Release road map, I always let them know that they are taking responsibility for any customization. Maven provides solid options, solid conventions, and if you break the convention you assume the cost of customization. This is a difficult idea to get across, but the analogy i like to use is: “Would you ever call up Oracle’s support line and tell them you had a better idea for implementing Foreign Keys? Probably not.”
If you take anything away from reading this post it should be that the Maven Release plugin needs to be appreciated for what it is not for what you want it to be. That’s an almost universal rule that could be applied to all of Maven: Use Maven for what it is not for what you think is should be. It isn’t Ant, it isn’t a free-form procedural “language”, and it has opinions.
There are many alternatives to the Maven Release plugin, but they don’t provide the same single, unified experience. For example, I prefer a solution for the Maven books that relies on a long-lived “production” branch and a set of Hudson tasks configured to build from these persistent branches. Then again, the Maven books are not a canonical example of a Maven project as they build PDFs and HTML from XML and are delivered in an almost constant basis.