There are many different ways to handle deployments, but I have become very fond of using Bitbucket’s service hooks. In this case we’re going to be using the POST service hook, which is basically a git post-receive hook that sends a POST request to a given url every time you push to your repository.
Note: This is a really simple and effecient way to handle deployments for smaller projects (e.g. Static websites, Wordpress, etc.), but if your project is any bigger than those you should really be using a CI server to push out deployments.
Work flow
- Commit changes and push them up to your Bitbucket repository
- Bitbucket sends a
POSTrequest to a deployment script on your server - The deployment script pulls changes into it’s local repository (which is in the web-root) which updates the website
- Repeat
Setting up the Server
To get started you’ll need to create a clone of your projects git repository that’s hosted on Bitbucket.
Note: If your repository is private you’ll need to create a public/private key pair on your server and add it to your Bitbucket account. If you don’t do this your server won’t be able to connect with Bitbucket.
1 2 | |
Creating the Deployment Script
Create a php file named deploy.php and add the following code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
Most of the code is self-explanatory, but I’ll go ahead and explain a few key pieces.
1
| |
If you set the date.timezone value in your php.ini file then you can safely remove this line, otherwise you should set it to your local timezone.
1
| |
This tells git to remove any changes to files in the working-tree since the last git pull. If we don’t do this and the working-tree is dirty then the deploy will fail.
1
| |
This just pulls in all new code from the remote and branch specified (defaults to origin remote and master branch).
1
| |
Since the git repository is in the web root users could potentially view it’s contents. This command modifies the permissions of all files in the .git directory so that only the file owner (you) can access them.
Configuring the Script
Most of the script defaults should work fine for the majority of users, but you will need to pass in the path to your web-root as the first parameter when creating the Deploy object. All of the other options can be configured by passing an array of values as the second parameter when creating the Deploy object.
Option Defaults
1 2 3 4 5 6 7 8 | |
Post Deploy
If you need to do something after a deployment you can do so by adding a callback to the Deploy object before executing. By attaching the callback to the Deploy object you ensure the code only gets run if the deployment is successful.
Example
1 2 3 4 5 6 7 | |
*Note: This example will only work on PHP 5.3+ because it uses a closure. If your not on PHP 5.3 you will have to use a traditional callback.
Setting Up the Service Hook
Once you’ve finished configuring your deploy script, go ahead and upload it to your servers web-root.
The next step is pretty straightforward, so I’m just going to point you directly to the documentation.
Now test it out and enjoy your painless automated deployments!
Taking it a Step Further
The script I’ve written updates the server’s repository regardless of whether or not the changes were made to the master branch (or whatever branch is your production branch). This works fine because it will only pull in changes from that branch anyway, but it would be nice if it would check what branch the changes are from and act accordingly.
Well, the good news is Bitbucket is kind enough to send along a bunch of data with the POST request which includes a list of all commits and their branch. It should be fairly easy to modify the script to check this data and only pull in changes if they are on your production branch.
What About Github?
Although I wrote the script for Bitbucket it should work with any git hosting providers as long as the have some sort of service hooks (which Github does, yay!).