Gitobots, Roll Out
We use Git for our version control and, with Heroku's push to deploy in mind, I looked further into the possibilities of using Git for our deployment process. Abhijit Menon-Sen's article details the process very well. With a few slight variations, these are the steps I follow to deploy changes via Git.
Prime RemoteOn the remote server for your application (e.g. production, staging or test), create a new, bare Git repository for your codebase:
cd /cygdrive/c/repo mkdir project.git cd project.git git --bare init
As this bare repository does not contain a working tree (the actual source), a Git hook is used to checkout the code to a specific location. Git hooks allow custom scripts to be executed when certain important actions occur.
- Create the directory from which your application is accessed/executed - e.g. /cygdrive/c/webroot/project
- Create the file post-receive in the project/hooks directory.
- Edit the file to include the following:
#!/bin/sh GIT_WORK_TREE=/cygdrive/c/webroot/project git checkout -f staging rm -rf /cygdrive/c/webroot/project/twig_cache/*
- Set the file to be executable - e.g.:
chmod +x post-receive
The main point of this hook is in the configuration of a working directory and the checkout of a specific branch (staging in this case) to this location. I also utilise the hook to clear out a cache directory for a templating engine (Twig) used in the application.
Push ItWithin your local development repository, add the bare repository as a remote:
git remote add staging-web ssh://email@example.com/cygdrive/c/repo/project.git
Once you have committed your local changes and are ready to deploy to your server, the server code base can be updated by pushing to the remote repository:
git push staging-web staging
The remote repository should update and also note that it is already on that particular branch. The updated files should now be present in the working directory.
Note: it may be necessary to manually execute the post-receive hook for the first push.
Branching EnvironmentThe above process can be replicated for various environments so that changes can be pushed to these environments as needed (e.g. test, staging, production). Following a similar model as described by Vincent Driessen, I utilise different branches for each environment (e.g. the staging branch is pushed to the remote repo staging-web, the master branch is pushed to the remote repo production-web). However, this generally implies that each environment will require unique configuration settings.
In order to address this issue, I created a new local configuration file to supplement a more generic configuration file.
- config.local.php contains configuration settings that are unique to that environment - e.g. database connection details, email settings, etc. Note: This file is not under Git control, as you do not want to commit any changes from this file across all your environments. Changes need to be made to each environment individually - these changes are normally relatively infrequent.
- config.php contains generic environment settings that apply across all environments - e.g. global constants, LDAP server connection details, etc. This file is under Git control.
It is necessary to ensure that all environment specific variables are extracted into appropriate configuration files (e.g. REST access points for your Backbone frontend, database connection, etc.)
While not optimal, this solution addressed the problem at hand.