Skip to content

Instantly share code, notes, and snippets.

@ernstki
Last active May 29, 2019 22:23
Show Gist options
  • Save ernstki/5b028575d0de6f28cdee to your computer and use it in GitHub Desktop.
Save ernstki/5b028575d0de6f28cdee to your computer and use it in GitHub Desktop.
A basic Git post-receive hook that will publish a sequence of similarly-named projects to a common web-accessible subfolder
#!/bin/bash
####################################################################
## ##
## post-receive.webhost ##
## ##
## A Git 'post-receive' hook for automating deployment to a ##
## public web directory based on the name of the "bare" repo ##
## that it belongs to. ##
## ##
## Rename to 'post-receive' and 'chmod a+x', then move this ##
## file into <bare-repo-name.git>/hooks. The next 'git push' ##
## to this remote will then check out all files listed in ##
## a file called 'manifest' (configurable below) to the dest- ##
## ination specified in CLONE_DEST, below. ##
## ##
## Author: Kevin Ernst <ernstki -at- mail.uc.edu> ##
## Date: Summer 2014-ish, with a few updates ##
## ##
## https://gist.github.com/ernstki/5b028575d0de6f28cdee ##
## ##
####################################################################
#set -x # uncomment for debugging
# Where to check out a copy of this repository after receiving new commits
CLONE_DEST="$HOME/public_html/projects"
BRANCH='master'
# The 'manifest' file should exist inside the root of your repository. It's a
# a list of file and directory names that you'd like to clone to the
# web-accessible folder. Comments are delimited with a leading '#'. Subfolders
# are supported by adding a trailing '/' (from which Git infers that you want
# to check out the entire folder).
MANIFEST_FILE='manifest'
# Infer the destination folder in $CLONE_DEST from the name of the c.w.d.; that
# is, the name of the directory containing the "bare" Git repo belonging to
# this 'post-receive' hook.
PROJ_DIR=$( pwd | sed 's!.*/!!; s!\..*!!' ) # strip before '/' & after '.'
export GIT_WORK_TREE="$CLONE_DEST/$PROJ_DIR"
if [ ! -d "$GIT_WORK_TREE" ]; then
echo "ACK! The specified working tree ($GIT_WORK_TREE) doesn't exist. Quitting." >&2
exit 39
fi
echo "Checking out the manifest file..."
git checkout -f $BRANCH $MANIFEST_FILE
manifest="$GIT_WORK_TREE/$MANIFEST_FILE"
# Clean up when the script quits or is abnormally terminated. (An 'rm -rf' would
# be pretty inadvisable here because there's a slash in the pathname--what if
# $GIT_WORK_TREE and $MANIFEST somehow both ended up null?)
trap "test -f '$manifest' && rm -f '$manifest'" EXIT
if [ $? -ne 0 -o ! -f "$manifest" ]; then
echo "ACK! Could not check out the manifest file from '$BRANCH'. Quitting." >&2
exit 53
fi
# Otherwise:
echo "Checking out passengers..."
while read passenger; do
# Skip comments
if [ "${file:0:1}" == "#" ]; then
continue
fi
set -x
git checkout -f $BRANCH "$passenger"
set +x
done < "$manifest"
# post-receive
@ernstki
Copy link
Author

ernstki commented Oct 12, 2018

Note that this does not recover gracefully from a failure, although it does notify you about it.

I have a feeling one of the other hooks might be better choice for this, or else this script needs to be a lot more sophisticated when handling problems on the remote end.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment