When evaluating solutions to automate and streamline your application lifecycle management process, your goal should be to build a mesh, not a monolith. By this we mean, rather than implementing a large, monolithic, enterprise workflow automation type of solution, your solution should focus on smaller, loosely coupled system components that don’t require each other to function, yet build on each other to create a streamlined workflow in the end. Even though our site’s focus is on Windows, this may sound oddly familiar – it’s basically the Unix philosophy applied to your application lifecycle management process.
You need a process for getting your applications from source code to deployable artifacts. The process needs to be frictionless enough to not get in your development team’s way, but it needs to ensure operational requirements are met like audit trails and build reproducibility.
We hope you’ll notice as we step through this process that none of the components necessarily require one another. Each component can function without the others, and the loss or outage of one component does not prevent software releases from reaching production.
This may sound obvious, but first and foremost, anything created by your developers and operations teams must be in source control. Centralized source control of course gives you backups and version history, and it serves as your source of truth about all software changes (who, when, what).
Many developers use an IDE like Visual Studio for interactive builds, but to automate your build process, including automation of compilation, version stamping, testing, code coverage/analysis, etc. you need a build system. Having a solid build system makes it easy to standardize build automation for most, if not all of your projects.
Next, whenever there’s more than one developer on a project (or even with just one…) you’ll need a continuous integration (CI) process. There are many products available, but this process polls your source control repository for changes to source code for a particular project, and then executes your build system (the exact same way your developers would!) and produces build artifacts including code analysis reports and binaries.
The build binaries should be dropped in an accessible location (i.e. a file share) that is only writeable by the account that runs the CI system. This ensures that binaries produced by the CI system are consistent with the source code that produced them. Of course limiting access to your build servers is important as well.
Given adequate build server capacity and an easy enough process for adding new projects to your CI system, your operations team can then use it as a way to enforce process: applications bound for production machines must be produced by the continuous integration system.
Release Branching Service
Once you’re following a branch-per-release branching scheme with standard branch naming conventions and practices, you can build additional automation to glue together your branching policy and your continuous integration system. This depends a lot on your choice of a continuous integration system, as some systems are more friendly to customization and automation than others.
You can create integrations and automation that allow developers to easily create a release branch from a given build (i.e. source control revision number) and have that release branch created as a new build project in your CI system so it begins “being watched” and gets built as changes are committed.
Finally, your development team needs to communicate the desire to release a particular application and version to the operations team. There’s a lot of information that needs to be noted (application name, version number, location of binaries, etc.). Of course as you advance towards continuous deployment, this process itself may be automated away, but in the meantime…
Using a lightweight release tracking tool, you can give developers a means of notifying the operations team of their intent to release, including all the relevant details, and you have an opportunity to automate the staging of binaries from the location the continuous integration system drops them to a production staging area or to your deployment system. This production staging area can be another file share that is only writeable by the process running your staging process.
Depending on the amount of customization possible with your continuous integration system you can even build integrations with your release management tool, since your continuous integration system knows most of the information needed in the release request already.
Hopefully you see how each of these pieces build on each other, but don’t necessarily require each other, nor does the end goal – a production application release – require them. You don’t need a build system to compile software, nor do you need a continuous integration system to package your software, nor do you need a release branching system to create your release branches & release builds, and you certainly don’t need a release management tool to keep track of your releases and stage them for deployment. You can start from a completely manual process and slowly build up simple components to automate stages of the process, making life a little bit simpler as you go, while retaining the know-how to plug the gaps manually in the event that one of the components becomes unavailable in the future.
By integrating these automation components components together, building a mesh instead of a monolith, you can create a fairly automated and streamlined application lifecycle management process that is frictionless enough for developers to get things done, but gives operations the information they need to perform the deployment, and you have auditing and reliability every step of the way.