Part 1, Part 2 is available here.
In January of this year, we successfully launched continuous integration for one of our clients on Bamboo Cloud (I will refer to it as Bamboo). Bamboo is a very capable work-automation tool that handles scheduling and running software-compilation tasks. In a nutshell, it runs commands to produce a result (artifact). Some commands are more automated than others, but in the end that’s what Bamboo primarily does.
Since we used Jira, Bamboo was a natural fit for us. It was the same family and had a similar interface. Bamboo and Jira somewhat worked together. When a build ran, Bamboo updated the associated Jira tickets. When you deployed a build, Bamboo showed what tickets would be going live. Bamboo's interface was also quite decent, compared to other entries in the industry. Bamboo was such a good product that I made a talk about it and presented it at our local Atlassian User Group. So far, so good.
You will also notice that I am using the past tense as I write about Bamboo. About a week (or less) after I gave the talk about Bamboo, I received an e-mail stating that Bamboo Cloud is sunsetting out in favor of BitBucket Pipes. We don't use BitBucket, and I never plan to. We hands-down prefer GitHub over BitBucket. Additionally, the basic features we needed in BitBucket Pipeline did not exist.
Before I continue my story, I need to share about our build/deploy process. From the beginning, we wanted a build system that would:
- Allow all compilation to happen at the time of build. In other words, SASS and Node.js (for running
grunt) do not need to be installed on the production environment. This keeps the production servers with as minimal software dependencies as possible.
- Include all dependencies in the build artifact. When the build completes, we have a .tar.gz file that contains every line of code necessary for the store to run. It does not contain
app/etc/local.xmlor the media or var folders. Those are symlinked in at deployment.
- Create one build artifact that is used on staging and then to production. This ensures that what was QA’d on staging is exactly what is deployed to production: no changes or modifications. If QA fails on staging, the developer fixes it, and the build process runs again.
- Automatically build the code from our GitHub repository when a feature branch is merged into the master branch.
- Automatically deploy the build to staging and then provide the ability to manually deploy the code to production.
Bamboo fulfilled each of these items for us. It wasn't perfect, but it sure did a good job.
The next step
With these requirements and without Bamboo, I embarked on a "what's the next best thing.” I looked at the industry leaders: Travis CI, Circle CI, and Snap.io. None of them handle deployment very well. None of them are designed to create a build artifact. That said, Snap.io had the most promise. However, it seems they are still in an intense development phase and their feature-set is not quite “there."
I was stuck. It would have been very nice to have a cloud-based system that handles updates for me. Isn't it ironic that in the world that is exploding with software growth, we still can't always have what we want or need?
I called a good friend who has been down this road before and his suggestion was Jenkins. They use it at their agency, and it works really well for them. Upon researching Jenkins and discussing it with the team here at SwiftOtter, we agreed that Jenkins was our answer.
My next blog post will be how we made this happen. The issue with Jenkins is that it is an installed piece of software. We typically think of booting up a server and letting it run for many years (until version 1 is 10 versions behind the latest release). As a result, the upgrade process is a total mess, feeling like you are starting over again. Using CloudFormation templates, we now have a system that regenerates itself, every day, always with the latest OS and Jenkins releases.