How to use git hooks to automatically deploy site content
It’s pretty common to use git to host your website files. There are a few different ways that you can use git itself to automate the deployment of site updates, depending on the specifics of your git hosting situation. The below methods should cover the vast majority of git-based workflows, at least if you’re self-hosting Publ.
Deployment script
Regardless of your actual git hosting situation, you will need a deployment script, which does a git pull
and performs different tasks depending on what’s been updated. Save this file as deploy.sh
in your website repository, and make sure it’s set executable:
The remainder of the deployment process depends on how you’re actually hosting your git repository.
Self-hosted git repository
Repository on same server as the website
For this example, we will keep the main git repository in $HOME/sitefiles/example.com.git
and the deployment directory in $HOME/example.com
.
On your webserver, create a private bare git repository wherever you want it; for example, on the server, run:
Now you’ll have a bare repository in $HOME/sitefiles/example.com.git
and a live deployment workspace in $HOME/example.com
, and pushing to the bare repository will run the deployment script in the live workspace, if it exists.
On your local repository (i.e. where you’re actually working on your site) add the bare repository as your remote:
This should push all of your content into the bare repository; however, since the live workspace won’t yet have deploy.sh
you’ll need to do one git pull
manually. After this, every push to the bare repository should automatically run your deployment script.
Separate servers using an ssh
key
If you keep your git repository on a separate server from where it’s deployed to, set up an ssh key or other authentication mechanism other than password so that you can do passwordless ssh from the repository server to the deployment server, and then add this as a post-update
hook on the repository:
replacing DEPLOYMENT_SERVER
with the actual server name, and example.com
with the directory that contains the site deployment.
Simple webhook deployment
If you don’t have the ability to run arbitrary post-update
hooks but do have some sort of webhook functionality, you can add a webhook to your Publ site to run deploy.sh
; for example, you can add this to your app.py
:
Then, in whatever mechanism you use to run the website, set the environment variable REDEPLOY_SECRET
to some secret string. For example, if you’re using a systemd
service, add a line like:
Deploy these changes to your website and restart it. Now you can configure a webhook on your git repository that sends a POST request to the /_deploy
route with the secret
parameter set to your REDEPLOY_SECRET
key.
GitHub-style web hooks
If you’re using GitHub (or something GitHub-compatible) to host your site files, there is a more secure way to run a webhook.
First, install the flask-github-webhook package into your environment (with e.g. poetry add flask-github-webhook
).
Next, add the following to your app.py
somewhere after the app
object gets created:
Now, set up your deployment to have an environment variable called GITHUB_SECRET
set to some random, unguessable string. Do a manual redeployment.
Finally, go to your GitHub repository settings, then “Webhooks,” then “Add webhook.” On the new webhook, set your payload URL to your deployment hook (e.g. http://example.com/_gh
), the content type to application/x-www-form-urlencoded
, and the secret to the value of your GITHUB_SECRET
string. It should look something like this:
Anyway, once you have it set up, every time you commit to GitHub, your site should automatically pull and redeploy the latest changes.
An example of this in action can be seen at the files for this site; in particular, see the app.py
and deploy.sh
files.
Troubleshooting
Site doesn’t update, or “updates rejected”
This is usually a sign that something changed on your deployment repository that’s causing a git conflict. ssh
into your live workspace and do a git pull
to see what’s going on. Chances are there was a change on your live repository that’s causing an update conflict, for example you checked in an entry which didn’t yet have an assigned Entry-ID
or the like.
Generally you can fix this by going into your live repository and doing git status
to see what’s changed, and a command like git checkout . && git pull
or git reset --hard origin/master
will sort everything out (but be sure not to lose any changes you meant to make directly on the server).
Webhook is timing out
If your packages change, the webhook will likely time out while poetry install
runs. This should be okay, but try ssh
ing into your live workspace and running ./deploy.sh
manually.