Skip to content

Instantly share code, notes, and snippets.

@fprochazka
Created February 20, 2012 15:59
Show Gist options
  • Save fprochazka/1869831 to your computer and use it in GitHub Desktop.
Save fprochazka/1869831 to your computer and use it in GitHub Desktop.
Useful git hooks for Gitolite

Git push deploy

Requires installed gitolite in /home/git and following directory structure

/var
    /www
        /apps
        /hosts
        /libs
        /pre-deploy

/var/www/apps

Contains applications, each one in separated folder named by it's git repository

/var/www/hosts

when created folder in here (for example kdyby.l), nginx will try to direct all the trafic from kdyby.l and *.kdyby.l to /var/www/hosts/kdyby.l/index.php.

By the rule, only symlinks are in this directory, targeting folders from projects in /var/www/apps

/var/www/libs

Contains libraries, that are automatically deployed to directories %git-repo-name%/%refname%.

So if I push to kdyby-framework to branch master, directory /var/www/libs/kdyby-framework/master will be containing latest version of master. Works the same way for tags.

When pushed as $ git push origin :branch, the branch will be deleted as usual and the directory containing deleted branch (or tag) will be deleted too.

/var/www/pre-deploy

Is used for deploying to apps

Deployment process

  • Bare repository is git-archive'd to corresponding directory in pre-deploy.
  • Script will build filters for rsync, using existing .gitignore files in project.
  • If this isn't the first deploy, and there is file app/console in the project, it will be called as app/console deploy:begin (yes it's symfony console in Kdyby sandbox based project)
  • Directories /var/www/pre-deploy/project and /var/www/apps/project will be rsynched using defined filters
  • Deploy script will fix permissions
  • If there is file app/console in the project, it will be called as app/console deploy:finalize
  • Directory /var/www/pre-deploy will be cleaned up
#!/bin/bash
#
# The "post-receive" script is run after receive-pack has accepted a pack
# and the repository has been updated. It is passed arguments in through
# stdin in the form
# <oldrev> <newrev> <refname>
# arguments
read oldrev newrev refname
# dirs
SOURCE_DIR="$GL_REPO_BASE_ABS/$GL_REPO.git"
PRE_DEPLOY_DIR="/var/www/pre-deploy/$GL_REPO"
APP_DIR="/var/www/apps/$GL_REPO"
# fix_permissions [dir]
fix_permissions () {
find $1 -type d -exec chmod -f 770 {} \;
find $1 -type f -exec chmod -f 660 {} \;
chown -f -R git:www-data $1
}
# export_ref [ref] [source] [target]
copy_ref () {
unset GIT_DIR
echo "Preparing directory $3"
rm -rf $3
mkdir -p $3
echo "Copying $1 to $3"
cd $2 && git archive $1 | (cd $3 && tar xf -)
}
# file=$(gitignore [source])
gitignore () {
TMP="/tmp/$(basename $0).$$.tmp"
for file in `find "$1/" -name .gitignore -type f`; do
echo "$(cat $file)" | sed -e '/^#/d' | sed -e 's/\s*#.*$//g' | while read -r line; do
if [ -z "$line" ]; then
continue
fi
if [ "${line:0:1}" == "!" ]; then
echo "+ $(dirname $file |sed "s@$1\/@@g")/${line:1}"
else
echo "- $(dirname $file |sed "s@$1\/@@g")/$line"
fi
done
done > $TMP
echo $TMP
}
# deploy [source] [target]
deploy () {
if [ -d "$2/app/console" ]; then
echo "Notifying application about deploy"
. $2/app/console deploy:begin
fi
echo "Synchronizing changes to $2"
rules=$(gitignore $1)
rsync --exclude='.git*' --filter="merge $rules" \
-r -c --no-implied-dirs --size-only \
--delete-after $1/ $2/ 2>/dev/null
fix_permissions $2/
rm $rules; rm -rf $1/
if [ -d "$2/app/console" ]; then
echo "Requesting application to finish deploy"
. $2/app/console deploy:finalize
fi
}
# decide whether and what to deploy or delete
case $refname in
refs/heads/* )
BRANCH="${refname:11}"
# choose target
case $BRANCH in
devel )
echo "Executing deploy to $BRANCH of application $GL_REPO"
copy_ref $BRANCH $SOURCE_DIR $PRE_DEPLOY_DIR
deploy $PRE_DEPLOY_DIR $APP_DIR
echo "Deploy finished"
;;
* )
;;
esac
;;
* )
;;
esac
exit 0
#!/bin/bash
#
# The "post-receive" script is run after receive-pack has accepted a pack
# and the repository has been updated. It is passed arguments in through
# stdin in the form
# <oldrev> <newrev> <refname>
# arguments
read oldrev newrev refname
# dirs
SOURCE_DIR="$GL_REPO_BASE_ABS/$GL_REPO.git"
TARGET_DIR="/var/www/libs/$GL_REPO"
# fix_permissions [dir]
fix_permissions () {
find $1 -type d -exec chmod 750 {} \;
find $1 -type f -exec chmod 640 {} \;
chown -R git:www-data $1
}
# export_ref [ref] [source] [target]
copy_ref () {
unset GIT_DIR
echo "Deleting directory $3"
rm -rf $3
mkdir -p $3
echo "Copying $1 to $3"
cd $2 && git archive $1 | (cd $3 && tar xf -)
}
# decide whether and what to deploy or delete
if [ "$newrev" = "0000000000000000000000000000000000000000" ]; then
case $refname in
refs/heads/* )
BRANCH="${refname:11}"
echo "Removing published branch $BRANCH of library $GL_REPO"
rm -rf $TARGET_DIR/$BRANCH/
;;
refs/tags/* )
TAG="${refname:10}"
echo "Removing published tag $TAG of library $GL_REPO"
rm -rf $TARGET_DIR/$TAG/
;;
* )
;;
esac
find $TARGET_DIR/ -type d -empty -delete
else
case $refname in
refs/heads/* )
BRANCH="${refname:11}"
TARGET="$TARGET_DIR/$BRANCH/"
echo "Executing deploy of library $GL_REPO, brach $BRANCH"
copy_ref $BRANCH $SOURCE_DIR $TARGET
;;
refs/tags/* )
TAG="${refname:10}"
TARGET="$TARGET_DIR/$TAG/"
echo "Executing deploy of library $GL_REPO, tag $TAG"
copy_ref $TAG $SOURCE_DIR $TARGET
;;
* )
;;
esac
fix_permissions $TARGET_DIR
fi
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment