Automatic deployment on push to GitHub repository

A simple task

Setting up automatic deployments on push to your GitHub repository should be a simple task, and there are many ways to do it.

However, almost all of them require you to waste your precious time and energy doing things you don’t necessarily care about.

First off you start learning what webhooks are, and how do they work. You go through the GitHub API documentation, and dig up the example payloads they send to you.

After that you figure out that you have to write the custom server for consuming the incoming webhooks. That forces you to choose the tech stack for the server. Then you figure out the server should be able to handle and execute multiple shell scripts.

At this point you figure out that perhaps your current tech stack is not a good fit for the new problem. You choose to rewrite the server in a different language.

Questions and problems start popping up left and right.

What if two developers push to the repository only few seconds apart? You start extending your server logic, and the initial architecture for the “simple” solution starts slowing you down.

You drain your creative juices for solving problems totally unrelated to your project. Solutions that won’t make your end users any happier.

What started as a simple task of getting the latest code from GitHub repository to your remote server, slowly turned into a nightmare.

You are now spending your time and energy developing and maintaining a solution to a problem that is totally unrelated to your real work.

Hookdoo to the rescue!

Not everyone wants to go through the described scenario. It should indeed be a simple task that you can perform in under 15 minutes.

This is where Hookdoo steps in.

After logging into my account, I am greeted with the overview page. This page contains history of my hook invocations.

Hook invocation history page.

Adding a Server

First thing I want to do is add my server where I want to be able to update my code.

Simple click to the “Servers” link in the header presents me with a Servers list page.

Servers list page, time to add a new server.

Clicking “Add a new server” button I get to fill out a simple form with SSH credentials that will be used to connect to the server and execute my custom shell scripts.

Adding new server — you can use Password or Private Key auth.

After clicking the “Submit” button, my server is ready to use right away!

Servers list — my server is ready to use right away!

Adding a “Hook”

Now I have to define which shell commands should be run on my server on the incoming webhook.

Upon clicking the “Hooks” link in the header I am presented with the Hooks list page.

Hooks list page, let’s add a new hook!

Click on the “Create a new hook” button leads me to the form where I can set up when and how my hook will be executed, what context values should be available to my shell commands, and the shell commands that I want to execute.

I type in the hook name, assign it to my server it should execute the shell commands on, set the concurrency strategy to ignore all subsequent requests until the script finishes the execution, and then trigger the next execution with the last incoming webhook payload. So if the two developers push the code one after another, we will have their changes deployed in order.

And, I write the shell commands to pull the changes from the remote repository and execute the script that will perform the necessary build & deploy steps. I could have also copied the contents of that script right here, but to me it’s more convenient to have that script in the repository.

Adding my hook

Now, I could have finished here, but I also wanted to ensure that my hook would be executed only on changes that happened to the development branch. Also, I want to ensure that the incoming hook really came from the GitHub itself.

This is what the “Trigger rule” option is for.

I quickly add up the expressions to check if the ref parameter from payload is referring to the development branch, and that the SHA1 signature of the message matches the value in the x-hub-signature header.

ref == ‘refs/heads/development’ && x-hub-signature == sha1(payload, ‘medium’)

Now I’m safe to use the hook! After submitting the form, I am presented with the Hooks list page.

At this point, everything is set up. Hookdoo has assigned an HTTP endpoint to my hook that I can use to trigger the execution of the shell script on my server. I can get that URL by clicking the “Copy endpoint” action.

The GitHub part

The only thing left to do is to add an outgoing webhook on GitHub that will trigger our Hookdoo endpoint.

Go to the GitHub repository Settings page, select the “Webhooks” from the side navigation and click the “Add webhook” button.

Webhook settings page of the GitHub repository

After confirming my identity, I am presented with a form to input my outgoing webhook details. I quickly fill them out.

Upon clicking the “Add webhook” button, I am all done. When pushing to the development branch, my code will be available almost instantly on my remote server.

That was easy, wasn’t it?

Check out more about Hookdoo at https://www.hookdoo.com/