Reputation: 6062
I'm trying to follow the last part of this tutorial here to create a post-receive Git hook (really just an example, the instructions everywhere else are basically identical).
As well as my local repository, I have a GitHub repo set up as a remote called central, and a production server set up as a remote called live. I have everything in place such that I'm able to easily push from the local repository to GitHub, and SSH into the production server to pull from GitHub.
I want to do away with the latter step entirely, so that all I need to do is push to the central repository, from where the production server will pull those changes automatically - and everything I've seen tells me a post-receive hook is the way to do this.
For some reason, everything I've tried so far to get the post-receive hook to work has failed.
My post-receive
file exists on my production server in .git/hooks/
, it's been made executable with chmod ug+x
, and yes, "post-receive" is spelt right. The post-receive
file contains the following Bash code:
#!/bin/sh
cd ~/www.example.com/public_html || exit
unset GIT_DIR
git pull central master
exec git update-server-info
I can even SSH into the production server and execute the post-receive
hook manually, and yet for some reason it isn't triggered when I push to the central repository, despite the fact that all the guides specify this is the way it should work.
The single way that I've diverged from these guides is that the repository on my server is a non-bare one, but from what I've learnt of the differences between the two this shouldn't make a difference where it's already been established that I can push and pull as normal.
So why exactly is my post-receive hook not working?
Changing the cd
line to:
cd ~/www.example.com/public_html && touch ./cd_ran_successfully || exit
...and then doing the push command locally results in no cd_ran_successfully
file being created on the server. However, manually executing the file when logged into the server, does create the file. This indicates some sort of problem with the user/process that the shared server is using to execute the file, but other than that I have no idea.
Upvotes: 0
Views: 1643
Reputation: 6062
As pointed out by jpsalm, Git hooks can only be run on a Git server, which generally isn't common practice to set up when hosting websites and CMSes like Wordpress, especially on shared servers where root access is less likely. Instead of Git's hooks, Github implements its own version of a technology known as webhooks.
N.B. Everything I've learnt below is the result of my research in the last few hours or so, and this answer is primarily for the purpose of consolidating this knowledge and making me feel like that time wasn't entirely wasted.
Webhooks are a very similar technology to APIs - where an API functions to provide data that is requested by a user, webhooks seem to work in the inverse way: they listen for specified changes on the server and notify the user of those changes.
As commonly applied to Git and Github, a webhook listens to Github for an event, such as git push
, and then sends a POST request containing all the details of that event to an endpoint. This endpoint is a script on the server written to parse the JSON from the POST request, check for authentication, and then execute another script on the server that actually does something - most commonly, pulling from the GitHub repo.
Github takes some of the pain of Webhooks out of the way by providing a web interface to create the request, but that still leaves the endpoint itself (what Github confusingly calls the payload, which I still don't get) to be programmed, in addition to the script that the endpoint will runs.
Unfortunately, I don't have the skill nr the time to write an endpoint for parsing JSON with Bash, or any other language for that matter, so until someone comes along and does just that, it looks like I'll have to settle for doing one extra push
command. :)
Upvotes: 0
Reputation: 328
A post-receive hook is a server-side hook, it needs to be on your git server.
Generally, to run custom hooks you will need to host your own git server. From what it sounds like what you want, you need to setup your production server to also host a git server that you can set up as a different git remote that you can push to.
Then you can setup your post-receive to deploy the files as needed.
Alternatively, you can setup a pre-push script to let your prod server know an update is available, albeit it is pretty hacky.
pre-push:
#!/usr/bin/env bash
ssh user@prod "/home/user/my_script.sh &"
my_script.sh
#!/usr/bin/env bash
# Wait for push to go through
sleep(25)
cd git_dir && git pull
# Deploy
cp git_dir/binary /usr/bin/
Upvotes: 1