As I run a couple of harp based web sites with a manual rollout process
I thought it is time to change this. The rollout process itself is pretty
straightforward, but it still requires you to log into the remote server,
update the git repo, execute harp compile
and copy over the data.
Automation always wins, even if it is simple.
There are several approaches to this problem
- Have a process on the remote system, that regularly pulls for updates. If
an update is found, execute
harp
and copy over the data. The biggest pro is a decoupled process from the push. The biggest con is, that this is a batch job, so updates are not immediately visible. Also you do not get to know, if the rollout has failed. For this sort of task I do not want to setup an emailing job. - Push to two repositories. The regular one, and one that is on the remote server and then executes the deployment steps. Pros: Simple, immediate feedback and immediate rollout. Cons: Does not scale, two pushes at the same time might be a problem, only one person gets to see the error. So the cons make it ideal for small scale project and I really like the immediate feedback.
The nice part about this, is that it only takes three minutes to set up.
Create a bare repository on your webserver
The first step is to create another repository on your destination host. The important
part is to initialize this repository as a bare
one, meaning it will not contain a
working copy, but allows us to push into
mkdir /my/repo.git
cd /my/repo.git
git init --bare
Create a post-update
hook
After initializing the repo the next step is to create a hook. Hooks allow you to fire custom scripts. Hooks can happen on the client side or the server side. A common client side hook might be running a linter or ensuring that you cannot push untested code. A common server side hook is an action executed after a push, which will be used as well here. You can read more about git hook here.
You can put the following hook into your freshly created bare repository at
/my/repo.git/hooks/post-update
.
#!/bin/sh
# Make sure that we abort on error
set -xe
unset GIT_DIR
BAREREPO="/my/mydomain.org.git"
WORKREPO="/home/user/mydomain"
WWWDATA="/var/www/www.mydomain.org"
if [ ! -d $WORKREPO ] ; then
git clone $BAREREPO $WORKREPO
fi
cd $WORKREPO
git checkout -f master
git pull origin master
npm install
./node_modules/harp/bin/harp compile
cp -rv www/* $WWWDATA
You can see, the script is no magic. You have to to unset the GIT_DIR
as this is configured
to the current repository. Apart from that configuring the bash to abort on errors is important
via set -e
. The rest is pretty straightforward. After optionally cloning and then updating the
repository, you can simply run the needed commands to create your static page content.
Push two both repositories
The most important step is, that whenever you push, you need to push into both repositories. The one for version control (and possibly shared with other developers) and the one on the web server used for rolling out.
git remote add rollout ssh://user@your-remote-server/my/repo.git
As you can see, there is no need to setup a public git server, when you can use SSH and just have a local, non-hosted repository. Now whenever you want to push, simply execute two pushes to both your remotes, one to update the repo and one to trigger the update on your webserver.
git push origin master
git push rollout master
Other options
One other option, which was already mentioned above, is to constantly pull the content and using a read-only deployment key to pull the data from the official git repo. That would more likely be the way to go with bigger setups, especially with a bigger team doing rollouts.
One last option would be to create the content on your local system, which means in this case doing the static compilation locally and then just push the data to the remote system. One thing to ensure in that setup is an atomic update, so you dont get states where you are updating your live data step by step.
I switched to this for all of my static hosted sites to save some SSH hassle. As usual, ping me on twitter or drop me an email for your thoughts.