Automating Deployment Using Git
Written by Simon Bailey
How many developers out there are still manually deploying project files to their remote server?
In my experience, automated deployment is typically declared as a nice to have but not usually a task where time actually gets set aside to complete. This post is focusing on what I would term as the simplest essence of automated deployment. The sequence of steps:
- Compile e.g. generating project files using rake or compiling a swf.
- Commit i.e. pushing to a git repository.
- Transfer e.g. copying local files to a remote server.
Heads Up
This is not covering the full CI setup, versioning, etc, this is simply a small (time saving) step for those developers who are still pushing projects manually. Further fun stuff like CI and automated builds comes in another post ;)
On the surface (for a simple project), all we are doing using the automated logic within this blog post is avoiding the transfer of local files to a remote server. However, for a project which starts to get slightly more complex for example deploying to different server directories e.g development, staging and production this approach starts to really shine. And in my experience it is the FTP’ing of files that I found swiftly became the mundane pain in the proverbial!
The project could be of any type you choose, whether a rails project, wordpress blog or flash app it’s all good. What you do need is the project in version control and this blog post focuses on using git.
Here’s what we are going to cover
- Setup the (remote) server-side web directories.
- Create a remote git repository (our hub) for the project.
- Write a post-update git hook to deploy our project files to defined serverside directories.
- Setup our initial local project setup.
- Add our local project to git.
- Test deployment to dev.
- Test deployment to production.
The scenario involves having two branches in your git repository, a master and a develop branch. Similary on your remote server you would have two directories under your wwwroot, I have called mine example (mapped to the domain example.com) and example_dev (mapped to the domain dev.example.com). Also on the server I have installed git and setup a user account named git. Here I presume you have ssh access to your remote server i.e. using your git account i.e. ssh git@mydomain.com.
Remote server web configuration
Navigate to your webroot directory and create two new directories as detailed above. Create your publically accessible directories under each site and ensure they have appropriate permissions (I simply open up access of these example public folders, you can restrict as you see fit):
cd /srv/www/
mkdir -p example/public_html
mkdir -p example_dev/public_html
chgrp -R users example
chgrp -R users example_dev
chmod 777 example/public_html
chmod 777 example_dev/public_html
Remote server git configuration
Login to your server under your git user account (or once on your server sudo su - git) and enter the following (replacing example with the project name of your choice) to create our project hub repository:
mkdir example.git && cd example.git
git init --bare
Configure git hooks
Still under the git user account:
vim hooks/post-update
Within this post-update file enter the following ensuring you change the root files to your defined directory names:
#!/bin/sh
echo $1
echo "*UPDATE*"
case " $1 " in
*'refs/heads/develop'*)
GIT_WORK_TREE=/srv/www/example_dev git checkout develop public_html
echo
echo "Dev was pulled"
echo
;;
esac
case " $1 " in
*'refs/heads/master'*)
GIT_WORK_TREE=/srv/www/example git checkout master public_html
echo
echo "Master was pulled"
echo
;;
esac
When there is a push from our local repository to the remote hub repository, this logic will determine which branch we pushed to i.e. develop or master and checkout the files from the public_html directory into the appropriate web root. There is a little visual feedback in the console to highlight what branch has been checked out.
Lastly we must ensure this post-update file is executable:
chmod +x hooks/post-update
Local project configuration
Create a new project directory and navigate on in:
mkdir newtriks.com && cd newtriks.com
Local project git configuration
Initialise a new git repository and commit a newly created test file. Finally add your remote hub url as the local respository remote alias and push to the master branch.
git init
echo 'Hello master!' > index.html
git add index.html
git commit -q -m'Initial pimp hit'
git remote add web git@[your ip]:example.git
git push web +master:refs/heads/master
Testing deployment to production
If you navigate in your browser to the production domain i.e. example.com, you should see Hello master!
Local develop branch configuration
Create and checkout a new branch within your project named develop. Update the index.html file and commit then push to the hubs develop branch.
git checkout -b develop
echo 'Hello, develop!' > index.html
git add index.html
git commit -m'Test dev pimp hit'
git push web develop
Testing deployment to development
If you navigate in your browser to the development domain i.e. dev.example.com, you should see Hello develop!!
Hopefully all works for you and your now comfortable with this initial start in automated deployment using git.
Resources
Thanks to these links and their authors for getting me started with this approach: