A whistle-stop tour through the various approaches and services we've used for version control and deployment, finally settling on GitLab and Jenkins...for now.
We’ve blogged before about the benefits of Git and version control so I won’t cover that ground again. But just to provide a little background, our journey with version control started many moons ago with an initial fling with Subversion, that quickly became “official” and it’s safe to say has now grown into a full blown marriage to Git!
Our experiences with Subversion started off with a self-hosted Windows solution using VisualSVN Server and that’s a product I would wholeheartedly recommend, it’s stable, actively maintained and keeping it up-to-date is a breeze. But...it’s Subversion and Git is what all the cool kids are using, right?
Our first foray into Git was using the hosted Beanstalk app and while we’ve been nothing but pleased with Beanstalk we’re quite prolific coders so we quickly smashed through our account repository limits and before we knew it we were paying quite an eye-watering amount to Beanstalk each month. So we started to shift some of our repositories over to BitBucket, a service that allows you to host an unlimited number of private repositories.
One of Beanstalk’s features we really love is their deployments, which easily allowed us to automatically deploy code to staging servers after a commit or trigger manual deployment of code to our production servers. So while we started to move repositories to BitBucket we still needed to replace the deployment functionality we were rather attached to at Beanstalk.
Enter GitLab, I can’t recall how or where I came across it, but I’m very glad I did. Essentially it’s best described as a self-hosted, open source equivalent to GitHub. It’s solved a lot of our problems, we can now move all our repositories under one roof and we can create repositories with no limits. But that’s not all, GitLab offers a really polished web based interface, where we can create issues and close them from commit messages, add GitHub like readmes and wikis, the list goes on. In addition, using the Omnibus package it’s a real breeze to install too.
GitLab also has an optional Continuous Integration server called GitLab CI, this couldn’t be easier to enable and then once a GitLab CI Runner is registered (where the tests are run) it has made it easy for us to run functional tests after each code commit. This is welcome automation that will save us time and improve the quality of our work.
The last piece in the puzzle was a means to replicate and hopefully improve upon the deployments we were reliant on at Beanstalk. In the past, I have dabbled with tools such as Hudson and RunDeck so I knew this shouldn’t be too tricky. For this particular task we looked to Hudson’s sibling, Jenkins. Our deployments at Beanstalk effectively just run a Shell script on our production or staging servers, so aren’t complicated to reproduce elsewhere. We found that we were able to very easily replicate the same functionality with Jenkins along with the potential to add improvements such as querying our auto-scaling groups at Amazon Web Services to then deploy to however many server instances are running at that particular moment. That’s one feature Beanstalk was sorely lacking. Also, by configuring a post-receive hook in GitLab we’ve been able to configure automated deployment to our staging server, again saving us yet more time and making sure our clients are reviewing the very latest iteration of our work.
Jenkins is a really mature tool, so there’s a wealth of plug-ins available allowing us to trigger HipChat notifications when jobs are run and we’ve found ourselves inventing further uses for it such as migrating databases between environments. Even running scheduled Pingdom style uptime and functional tests across all our client sites, something that would be prohibitively expensive to do via Pingdom.