Git + Hooks = LOVE

Tutorial – Create a POST hook on BitBucket

A powerful tool offered by both GitHub (GH) and BitBucket (BB) are so-called “Hooks” which allow certain actions in your repository to trigger other actions. BitBucket’s definition:

Hooks allow you to extend what Bitbucket does when the repository changes (for example, new code is pushed or a pull request is merged).

There are many different kinds of Hooks and I invite you to check out GitHub and Bitbucket‘s documentations for a full list of possible options and how to implement them.

In this tutorial, I’m going to set up a BitBucket “POST” hook. My goal is to force all of my front-end machines to update their local clones of the main repository when a git push is done on the Master branch.

NB: This is for a small side project and my personal rule is that all code development is done on one dev machine and a “deployment” consists of the production machines doing a git pull. Though this method works for me (one-member team, 3 servers, 1 repo containing the entire app), it is certainly not the best way to update your fronts and completely skips the “staging” phase.

Server-Side

SSH Keys (optional)

If you want to be able to interact with BitBucket (or GitHub) without using passwords, you’ll have to provide the public key of each machine you need this for. Follow this tutorial to set that up.

Firewall

In some cases, you may need to allow BitBucket’s IPs to access your server. BB provides a list of IPs they use here. You can allow these IPs to access your server by modifying the iptables:

iptables -A INPUT -s 131.103.20.165 -j ACCEPT
iptables -A INPUT -s 131.103.20.166 -j ACCEPT

Nginx Rules (Apply equivalent idea for Apache)

Personally, I prefer dedicating a folder for 3rd party callbacks. For this tutorial, that folder is /ping and the script I want BB to call back is p.php. We’re going to password protect that folder (obviously). To do so, create a user that BB will use to access this folder. In this example, the username is bucket and I’m using roobar as a password.

If you don’t already have a .htpasswd file, or if you want to use a different one for this purpose, create one (with the -c argument). I’m using /etc/nginx but you can put it where-ever you want.

htpasswd -c /etc/nginx/.htpasswd bucket

If you want to use an existing password file, just add the new user to that file:

htpasswd /etc/nginx/.htpasswd bucket

In both cases, you will be prompted to enter a password for the user.

Once the user is created, we need to tell nginx that folder /ping is protected by passwords located in /etc/nginx/.htpasswd:

location ~ /\. { deny all; }

location ^~ /ping {
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
fastcgi_pass php;
}

NB: I’m using a NGINX+PHP-FPM setup. The first location rule prevents any access to any files that start with a period.

To make sure you have not broken anything, save and then do service nginx configtest. If that goes well, then do service nginx reload so that the new rules are in place.

Test that your folder is password protected by attempting to access p.php from your browser. You should be prompted for a username and password.

auth

Finally, to test that your server is ready to be pinged by BB, you can use curl from machine:

curl -i --user bucket:roobar -H "Content-Type: application/x-www-form-urlencoded" -X POST -d 'payload=%7B%22person%22%3A%7B%22name%22%3A%22bob%22%7D%7D' http://yourdomain.com/ping/p.php

Make your script echo a Hello World or something and you’ll be set.

Important: The content-type is important and BB will actually send you a URL encoded payload.

BitBucket.org

Hooks are created on a per-repository basis. So, enter the repository you want to create a hook for and navigate to the Hooks section:

BitBucket Settings Hooks
Open repository, go to Settings, click on Hooks

In the drop-down menu, select POST and click on “Add Hook.”

You will be prompted to enter the URL which should be of form http://user:password@url_or_ip.com/ping/p.php. For this tutorial, it would translate to http://bucket:roobar@domain.com/ping/p.php.

Repeat this step as many times as necessary (ie/ for every server you wish to ping).

At this point, your hook is set up and should work. Anytime you do anything with this repository, BB will call p.php and in the $_POST[‘payload’] variable, there will be a JSON describing what was done. You can get more details about what is contained in this JSON here.

Once you get pinged, you’re free to to whatever you want!

Have a question? Like what you read? Leave a Reply!