Skip to content
jaredgaut edited this page May 3, 2018 · 4 revisions

About

This document describes a way to fake continuous integration through a pre-push hook. You can brush up on git hooks here for a better understanding, but everything relevant should be explained in this document. Basically a pre-push hook is a git hook that exists in .git/hooks and run before every git push and if the return code is 0 continue with the push, if anything else do not push.

Setup Your Keychain

Before you can use the included pre-push hook you must setup your keychain, this way we don't need to store credentials in the project or in plaintext on disk. The username and password should change, but the git2jss-dev and -prod strings should stay the same.

Create the Keychain for Dev

security add-generic-password -l git2jss-dev -a <username> -s <jssdev_url> -w <password>

Create the Keychain for Prod

security add-generic-password -l git2jss-prod -a <username> -s <jssprod_url> -w <password>

Setup pre-push Symlink

cd to the project root directory and run the following command: ln -s ../../hooks/pre-push .git/hooks/ to create the symlink for the pre-hook. This will allow you to modify the hook and keep it in version control. Run git push to test run the pre-push which will push to dev only if you copied it directly from the master branch, the pre-push will run even if there are no changes to be pushed.

Below is an example that will push to dev and if successful continue pushing to prod then push the actual repo to your remote.

#!/bin/sh

# A hook script to verify what is about to be pushed.  Called by "git
# push" after it has checked the remote status, but before anything has been
# pushed. This hook checks the keychain for jss-dev and jss-prod instances
# and if they exist attempts to run the sync.py script against your dev
# instance. If successful, the script will then attempt to upload to prod.
# This script can and probably should be modified to suit your specific needs.
# NOTE: If you are using some CI platform or there is more than 1 person
# working on this repo the script should probably not be used and you should
# use whatever tool your CI server provides.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If pushing without using a named remote those arguments will be equal.
#
# Information about the commits which are being pushed is supplied as lines to
# the standard input in the form:
#
#   <local ref> <local sha1> <remote ref> <remote sha1>

remote="$1"
url="$2"


DEV_URL=`security find-generic-password -l "git2jss-dev" -g 2>&1 | grep 'svce' | cut -d \" -f 4`
DEV_ACCT=`security find-generic-password -l "git2jss-dev" -g 2>&1 | grep 'acct' | cut -d \" -f 4`
DEV_PASS=`security find-generic-password -l "git2jss-dev" -w`

PROD_URL=`security find-generic-password -l "git2jss-prod" -g 2>&1 | grep 'svce' | cut -d \" -f 4`
PROD_ACCT=`security find-generic-password -l "git2jss-prod" -g 2>&1 | grep 'acct' | cut -d \" -f 4`
PROD_PASS=`security find-generic-password -l "git2jss-prod" -w`

branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')


# Attempt the push to dev
./sync.py --url "$DEV_URL" --username "$DEV_ACCT" --password "$DEV_PASS"
err=$?

if [[ $err -eq 0 ]]; then
    echo "Push to dev successful, attempting push to prod."
    ./sync.py --url "$PROD_URL" --username "$PROD_ACCT" --password "$PROD_PASS"
    exit $?
else
    echo "Push to dev returned an error, canceling push."
    echo "Remote not updated, please correct the errors before continuing"
    exit 1
fi