Hey, I'm Luke Siedle maker of things technical and creative. I'm a full stack developer by day. Musician and writer by night.

← Home

A faster deployment workflow with git and your dev server

Like everybody, I'm pretty tired of deploying websites via FTP. In many cases, the client doesn't have root access to their server since they're on a shared host, so your hands are tied anyway, and the best you can do is upload a zip file. You can however stage the site on your own servers until you're ready for production. If you've got root access to your stage, you can create a git deployment method that will allow you to focus on the work only, and worry about deployment only at the very end of your project.

Create a webhook

The first thing you need is a web hook, an endpoint that Bitbucket or Github can request when they receive a git push. Bitbucket recently changed how their web hooks work and the payload that gets sent along with them.

You need an event on repository push, which is a default they provide in the webhooks section of your repo settings.

https://confluence.atlassian.com/display/BITBUCKET/Manage+Webhooks

Your webhook will be hosted on your stage, so you need a link like, www.mydevserver.com/webhook.php. This PHP file will be reading in the payload sent along by Bitbucket, and perform the necessary actions to get pull your latest repository.

Now each time you push, this request will be sent to that URL. Right now, there's nothing there. So you need to create the file and the script that will handle the workflow.

Create a PHP (or other) script for the webhook

You need to read in PHP input and decode from JSON: $payload = json_decode( file_get_contents('php://input'));. Inspect the object for the information you need. Basically you're just looking for the repo URL/name and the commit message. The reason we want the commit message is, it's useful to be able to send commands inside the message. These are already used inside Bitbucket for certain actions, for example, "Fixes #2", would resolve the issue numbered #2.

You will probably access the repo name and message from the object as follows:

$payload->repository->name;
$payload->push->changes[0]->new->target->message;

Create a binary wrapper

Once you've got this info, I found it easiest to pass this into a binary wrapper script that can execute as root. I just came up against a lot of permissions issues, so this was the quickest way to get things working. In PHP you would run shell_exec("./wrapper arg1 arg2 arg3 etc"). You can learn how to create this script here:

http://stackoverflow.com/a/8532448/558287

So you can pass a set of arguments to your wrapper, which will in turn execute a shell script as root. This gives your shell script unlimited power, so be careful about what the script does. You can interface with any software you've got installed on your server. Right now my deployment script does this, (which is all I really need for now):

  1. Pull the latest changes from Bitbucket
  2. Copy these changes to the working directory (staging)
  3. Automatically create a MySQL DB equal to the name of the repo
  4. If you find the words "UPDATE_DB" in the commit msg, automatically update the database if you can find a file called "latest.sql" in the root.

Now every time I want the site to be updated 100% (for example, a Wordpress site I'm staging), I just have to run the following (after dumping to latest.sql)git add . && git commit -m "Latest changes UPDATE_DB". In a few seconds, the stage is synced, and I can now show the client my progress. Good times.

There's a bit more to all this than I've shared, for example, you need to have git installed on your server, and ensure you have SSH keys installed to your root user that allow you to access your Bitbucket/Github repo. You should also try and SSH to Bitbucket at least once from your server. I'll let you Google all that.

What else is possible?

You could do some awesome stuff with git, for example, automatically run integration tests each deploy to ensure your build is functional, or you could link to your project management tool to report each deployment/build success, along with the commit message. You could also stage all the branches of your project separately, if for example, different team members are working on different areas of the project. So it's really worth spending the time setting this up. It'll save you countless hours in the future.

Want to work with me and the team? Check us out http://lab19digital.com.