Is your release process causing you problems? Are you looking to set up continuous delivery?
If you’re struggling to setup a reliable, repeatable release process you’re not alone. The good news is that most of the problems you’ll encounter have been solved before.
There are many smart strategies you can use to create a fast, smooth release process that will give your entire team a competitive edge.
#1: Version everything
Source control for application code is a given.
Have a single source of truth that the whole team can use. You get auditability, repeatability and security in knowing your changes aren’t just on your laptop. There’s also that feeling of closure when you commit or push your finished work. (Until it comes back to you from testing.)
But to be ahead of the game you should be versioning more than application code:
- Content. The above points apply for other content too. The document containing your EULA, the images for the website, the deployment scripts. Put them all in source control, unless they’re huge.
- Databases. They are no exception! Without appropriate use of source control, it’s hard to know what you should be releasing to customers, or which changes caused the problems in the last release.
- Configuration. Companies are even going as far as source controlling the configuration of entire servers, making it trivial to apply changes as needed.
It’s not hard to do many of these, and the tools needed are widely available.
#2: Use branches
Branching can be hard but is unavoidable for teams doing continuous delivery.
You need to be in a position where you can release all of the time. Where anyone can deliver a fix to your customers easily. You’re going to have features that aren’t fully baked in a single commit that would cause pain if accidentally released.
Here’s how you make branching and merging manageable:
- Pick the right branching strategy for your project. You’ll need one branch that is always releasable and other branches for development work.
- Merge little and often. There’s nothing worse than a whole day spent merging code.
- Talk to your team mates. They don’t bite. Usually. Seriously, the best way to avoid unnecessary conflicts is to understand what each other are trying to achieve, and where that impacts.
#3: Write enough tests
Yes, you really should have done a full release test, but you were in a hurry. Now the customer is on the phone about it. It does take longer to write tests than to manually test the app once and writing tests quickly and with good coverage is a hard-earned skill. However, writing automated tests will definitely make your life less painful.
Write enough tests by:
- Starting with the most critical parts of your application. This will make you feel much more comfortable when releasing because you know that part of the app works.
- Not worrying whether you’re writing unit tests or integration tests. The main things to keep in mind are having good coverage and that the tests don’t take too long to run.
Test driven development is great. It makes for more robust, maintainable code. Arguably it speeds up development too, as you’re reducing the feedback loop to a minimum.
#4: Create and use packages
A lot of great libraries are available as NuGet packages. There are currently over 16,000 on the NuGet gallery. Sure, you can just keep the assemblies, or even source code in your source control system, but you’d be missing out.
NuGet packages are integrated into Visual Studio, and are really easy to add or update in your project. You don’t have to commit the binaries. NuGet can download packages using just the name and version number.
But packages are useful for more than just third party libraries:
- Create your own libraries as NuGet packages and publish them to private package repositories. This will improve build times as you’re depending on binaries rather than source. It also helps separate concerns and reduce variability. You will be more confident in a release if you know it was only the web app component that was even recompiled.
- Deployment benefits from packages. If you create a package for each component of your application, it’s easier to know what you’re deploying. You can easily deploy an earlier version, check for drift, etc.
#5: Automate everything
Not everything can be automated. I’m not able to automate deploying my iPhone app to the AppStore for instance. But automating nothing is asking for trouble.
- Build and test runs can be automated easily using one of many build/CI systems. The output of a build should be an artefact ready for use by its consumer, whether that is another build, a system or a real person.
- Running a build isn’t just for applications. Anything that needs to be consumed somewhere else should be built; libraries and databases too.
- Automate deployments and releases using a release management system, such as Octopus Deploy. Writing scripts and running them from your build system is fine for simple projects. But in most cases a release management system will be a much better fit to your environments, team and processes.
Putting continuous delivery into practice
None of the tips above are particularly difficult to implement. But in practice, it’s often hard to find the time to try out new approaches. Getting them adopted more widely in your organization is harder still.
Here’s my suggestion.
Identify just one improvement to your process that you’d like to try, and tell others your plan. There’s nothing like getting a plan out in the open to make it happen! Try it on something small, prove that it helps, then work on convincing others to follow.
What do you think? What ONE piece of advice would you give a friend trying to achieve continuous delivery? Tweet me @JustinCaldicott.