Chapter 23. Please Release Me

I heard an Angel singing

When the day was springing,

“Mercy, Pity, Peace

Is the world’s release.”

William Blake, I Heard an Angel

Creating a software release is an incredibly important step in your software development process, and not one that should left to the last minute. It requires discipline and planning.

bbpg 23in01

Many times I have run into silly, perfectly avoidable problems that were caused by a lackadaisical approach to the construction of software releases.

Most of these were caused by the sloppy habit of creating a “release” from a local working directory, rather than from a clean checkout. (Hint: this is not a real software release, it’s a “build” of your code, you need a lot more process and diligence to create a proper release.)

Some examples:

  • A software release was made from a developer’s local working directory. The developer hadn’t cleaned the code first, and the directory contained uncommitted source file changes. He noticed, but made the “release” anyway. When problems were reported, we had no record of exactly what went into that build. The result: debugging the software was a nightmare, mostly guesswork.

  • A software release was made from a local directory that wasn’t up-to-date; the developer hadn’t updated to the HEAD of the Subversion code repository. So the release was missing features and bug fixes. Helpfully, the developer tagged the HEAD of the repository as the “release point,” claiming he’d build that version. The result: much confusion, embarrassment, and a dent in the project’s reputation.

  • A project was released whose code was not under source control; it lived locally on the hard disk of one machine which—as I’m sure you can guess—was not being backed up. The code was based upon an original software release by another organisation. We had no record of where the original code came from, which version it was based on, or how it had been subsequently modified. For bonus points, the machine’s exact build environment was unknown—the result of years of tweaks and adjustments. Murphy’s law struck. The machine died. The result: all copies of the source were lost, along with the understanding of how to build it for the target platform. Game over.

Each was an incredibly frustrating experience.

Creating a serious high-quality software release is a lot more work than just hitting “build” in your IDE and shipping whatever comes out. If you are not prepared to put in this extra work, then you should not be creating releases.

Key

Creating software releases requires discipline and planning. It is more than hitting “build” in a developer’s IDE.

In the previous chapter we looked at “code freeze,” where we attempted to stabilise our code in the run up to a release. We also questioned whether a code freeze period should exist at all. Once you have your code ready to release, be it a snapshot of your mainline, or a frozen branch of development, you need rigour and discipline to construct a sound release from it.

A Cog in the Machine

The bare outline of a good release process, specifically for a “shrink-wrap” distributable application, is shown next.footnote::[Other kinds of releases—for example, to a live web server—largely follow this pattern with few adjustments.]

Step 1: Initiate the Release

Agree that it’s time to spin a new release. A formal release is treated differently than a developer’s test build, and should never come from an existing working directory.

Agree what the name and type of the release is (e.g., “5.06 Beta1” or “1.2 Release Candidate”).

Step 2: Prepare the Release

Determine exactly what code will constitute this release. In most cases, you will already be working on a release branch in your source control system, so it’s the state of that branch right now. You should rarely release code directly from your source control system’s mainline of code development (i.e., trunk or master).

A release branch is a stable snapshot of the code that allows you to continue development of “unstable” features on the trunk. You can merge in the good, stable, known work from the mainline into the release branch once it is proven. This maintains the integrity of the release codebase whilst allowing other new work to continue on the mainline.

If you run unit tests and a continuous integration system on your code’s mainline, then you must also arrange to run these on the release branch, for as long as the branch is alive. The release process should be short, and so release branches should be short-lived.

Tag the code in source control to record what is going into the release. The tag name must reflect the release name.

Step 4: Package the Release

Ideally, this is an integral part of the previous step.

Construct a set of “release notes” describing how the release differs from the previous release: the new features and the bugs that have been fixed. (This can be automated, pulled from source control logs. However, check-in messages might not be the best customer-facing notes.)

Package the code (create an installer image, CD ISO images, etc.). This step should also be part of the automated build script for the same reason.

Step 5: Deploy the Release

Store the generated artefacts and the build log for future reference. Put them on a shared file server.

Test the release! Yes, you tested the code already to prove that it was time to release, but now you should test this “release” version to ensure that everything is correct, and that the artefacts are of suitable release quality.

Key

Never release software without testing the final artefacts.

There should be an initial smoke test to ensure that the installers work OK (on all supported deployment platforms) and that the software appears to run and function correctly.

Then perform whatever testing is appropriate for this type of release. Internal test releases may be run through test scripts by in-house testers. Beta releases may be released to select external testers. Release candidates should see suitable final regression checks. A software release should not be distributed until it has been thoroughly checked.

Finally, deploy the release. If you ship directly to an end user, then this perhaps involves putting the installer on your website, and sending out emails or press releases. Perhaps it means sending the software to a manufacturer to burn onto physical media.

If your code is deployed on a live, running production server, then we enter the world of devops (development/operations, where software development meshes with IT operations). This is the art of deploying new code onto a remote server, upgrading any required software components, upgrading datastores (e.g., performing database schema migration), and restarting the server with the new code; all with as little downtime as possible. This process needs to offer sensible fallback in case of any installation issues. As with many other software processes, automation is very much the key to an effecient and successful server deployment.

Release Early and Often

One of the worst release process sins is to think about this stuff only as you reach the end of a project, when you finally need to perform a public software release.

In the software world, it’s an increasingly popular belief that you should defer any task or decision until the last responsible moment;footnote::[This is originally from Mary and Tom Poppendieck’s Lean Software Development: An Agile Toolkit (Boston: Addison-Wesley, 2003), where they describe it as: the moment at which failing to make a decision eliminates an important alternative.] that is, until the point you know most about the exact requirements and have minimised the opportunity cost of what you could be doing instead. This is a sound viewpoint; however, the last responsible minute to construct a release process is a lot sooner than most developers expect.

Key

Do not defer the planning and construction of a software release process until the last minute. Build it early, iterate through builds rapidly and frequently. Debug the build like you’d debug any other software.

We’ve seen that the ideal release process is entirely automated. The automated build and release plumbing should be established very early on in the development process. It should then be used often (daily, if not more frequently) to prove that it works, and that it is robust. This will also help to highlight and eliminate any nefarious presumptions in the code about the installation environment (hardcoded paths, assumptions about the computer’s installed libraries, capabilities, etc.).

Starting the software release process early in the development effort gives you plenty of time to iron out wrinkles and flaws so that when you are in the run-up to a real public release, you can focus on the important task of making your software work, rather than the tedious mechanics of how to ship it. Indeed, some people set up their release process as the very first thing on a new software project.