Posted on

Quick rollback via system link in DeployBot

I’ve been using DeployBot (formally known as Dploy) to deploy complex websites which require compiling Sass, minifying and uploading assets to Amazon S3 using Gulp.js, installation of Composer dependancies and a number of other configuration and cache settings to be changed.

DeployBot does quite a good job of managing this infrastructure. Although the build tools are still in beta, you can’t fault them for their support.

As per this blog post they mention:

You could always rollback by triggering a deployment with a previous commit selected. However, when things go wrong you want to react fast. We hope this button will go a long way to help you save time and not make a mistake in a rush.

The problem is, if you have quite a large site (that requires compiling before it even starts uploading the files), rollbacks are painfully slow. There’s nothing worse than a live site in a state that the client (or even yourself) isn’t happy with. Whatever the reason, you’d want rollbacks to be instantaneous.

DeployBot don’t currently support ‘quick’ rollbacks via symlink changes alone (since these can be quite complicated). At the moment, rollbacks are done just as any other deployment – code gets compiled, uploaded to a new release, all the files are uploaded to the release and if it’s successful, the release will switch the $BASE/current symlink. The other issue is if you have code that needs to be executed before/after deployments such as database migrations. This is where things can get a bit tricky, and you may want to stick with DeployBot’s current rollback solution.

I’ll leave that to you work out for your own applications but on a basic level, I’ve come up with a quick shell script that makes this ‘quick’ rollback possible:

if [ 1 -eq "$rollback" ]; then
    for release in $releases/*; do
        revision=$(cat "$release/.revision")
        if [ "$revision" = "$commit" ]; then
            rm -f "$releases/current"
            ln -s "$release" "$releases/current"
            mv -f "$releases/current" "$base/"
            echo "Release found on server, switching symlink."
            exit 0
    echo "Release not found, continuing with deployment."
    echo "Deployment is not a rollback, continuing with deployment."

Be sure to change the $base variable to your correct path.

Please check my GitHub account for the latest version of this code.

This works by first checking to see if the current deployment is a rollback. If it is, we check through all the current releases that are stored on the server and comparing the .revision file with the current commit. If it matches, the symlink is changed.

I’ve put this code in a new server (selecting ‘Shell’ as the type) upon deployment. Adding this code alone will quickly check to see if the rolled back release is available, switch it and ends with an exit code (0). Your application would have reverted back instantly.

Panic over. Go make a cuppa.

Whilst you’re making your tea, since these deployments are running in parallel, the Atomic FTP server is currently deploying the rollback from scratch.

After speaking to DeployBot, one of the concerns they had with this script is you would have two deployments running in parallel, so you couldn’t be sure the shell deployment ran first. Generally speaking, your Atomic FTP deployment will take a good while to deploy, and you’d want it to carry on deploying anyway – this is more as a fallback until the actual deployment is finished.

However, if you would prefer to have your deployments running in series, simply set up a second environment. The first being your shell deployment with the quick rollback and the second being your Atomic FTP deployment. Head over to the ‘overview’ of your deployments which should show your environments. Click the settings button on your shell environment and you should be in the ‘Servers & settings’ section. Scroll down to ‘Triggers’ and you’ll see something like this:


Simply check the ‘Deploy another environment’ box and choose your Atomic FTP environment. Be sure to name your shell environment just the environment you wish to choose. In this case, I’ve named my shell environment ‘Staging’ and my Atomic FTP environment ‘Staging (Atomic FTP)’. This is so the manual commit trigger can be picked up by adding [deploy: staging] to your commit message.

And there we have it, instant rollbacks. Neato.