Contents

The poor man's continuous deployment

Here’s a confession: I’m lazy. And it’s actually one of the traits I am most proud of. Being lazy as a software engineer helps you solve problems by automating them. And my problem is: using ssh and doing 3 commands.

The horror of deployment

I like building things but I dislike actively putting it somewhere on a server by hand. As it turns out, most of the industry has acknowledged this as an actual business problem and now calls it continuous deployment.

And there’s tons of good tools for that around. In my day-to-day business, we use the Gitlab CI tools for that and it works great. But for my personal projects I just want the minimum amount of effort to quickly put it somewhere.

So what’s the least amount of things you need to put, let’s say, a static site on a server?

  • The server itself
    • A running SSH agent
    • Something to serve the site (Nginx, Apache, etc.)
  • A git repository with your static site
  • Magic deployment juice

The easy way

The actual easiest way is to write a script that builds the content locally and copies it to the server. Something along the lines of:

1
2
# build_thing to build/
scp build/ user@foo.com:/var/www/foo.com

Which is completely fine to do and dead simple, but has some downsides:

  • You need SSH access to the server, likely even root access. Which means you can’t trigger a redeploy when not on your main rig.
  • You need the build tools on your local machine.
  • And most importantly, it’s not fun. I want things to be fun.

The poor man’s continuous deployment way

So what’s a more elegant solution without resorting to a full blown CI/CD pipeline? My requirements are easy - I just want to use git, push a commit to master, and have it magically appear on a website.

The magic juice that fuels these ambitions is called - Webhooks!

It’s actually far from a new concept and has been around for over a decade, but it’s simple and effective for many things, like getting notified that a git commit has occured.

GitHub, GitLab and Bitbucket all support Webhooks and it’s remarkably easy, as it basically just calls any URL you provide to it with a POST request as soon as a new commit arrives.

/media/github-webhooks.png

So the next thing you need is a tool that consumes these hooks. You can build something yourself for this, but personally, I like using webhook by adnanh. It just requires a small config file that references the script you want to launch:

1
2
3
4
5
6
7
[
  {
    "id": "redeploy-foo-com",
    "execute-command": "/home/foo/bar/deploy.sh",
    "command-working-directory": "/home/foo/bar"
  }
]

An this is the script of mine that compiles and deploys the site:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# Trap all stdout and stderr to a log file, source: https://serverfault.com/questions/103501/how-can-i-fully-log-all-bash-scripts-actions
exec 3>&1 4>&2
trap 'exec 2>&4 1>&3' 0 1 2 3
exec 1>deploy.log 2>&1

# Check whether new commits are available
git fetch
STATUS=$(git status --porcelain --branch)

if [[ $STATUS == *"behind"* ]]; then
    echo "Pulling current state and deploying to server"
    git pull
    # build_thing to build/
    rm -rf /var/www/foo.com/
    mkdir -p /var/www/foo.com/
    cp -r build/ /var/www/foo.com/
    echo "Deployed without errors"
else
    echo "Repository is up to date. Nothing to do!"
fi

And voilĂ , this is it. Whenever you do a commit, it will automagically get deployed. In fact, you are reading a site deployed by this very technique right now.