Skip to content

Instantly share code, notes, and snippets.

@Eihen
Last active February 8, 2018 15:01
Show Gist options
  • Save Eihen/05b3c63393ae0c8a2a47b96894085e7a to your computer and use it in GitHub Desktop.
Save Eihen/05b3c63393ae0c8a2a47b96894085e7a to your computer and use it in GitHub Desktop.
Git post-receive hook to deploy changes to a server using "git push" and execute needed commands when successful
#!/bin/bash
# REQUIREMENTS:
# 1) SSH Access to the remote server
# 2) Reading the whole script and understanding what it does before using it
# If you can't understand something, let me know and I'll be happy to help
# 3) Understanding that this script is provided as-is and I have no responsibility for whatever damage occurs
# That said, if the script was strictly tested and no problems should arise if you use it without any modifications
# of areas which not states that can be modified
# Also if you find any problems let me know to see if I can help you (and/or fix the script)
# INSTRUCTIONS:
# 1) Create a git repository in your remote server user home directory with "git init --bare"
# 2) Create another directory to where the files will be deployed
# This second directory can be anywhere on the server as long as you have read and write access to it
# I recommend that you create it on the same place as the first directory and symlink it with "ln -sf $SOURCE_DIR $DEST_DIR"
# if you need it to be anywhere else
# $SOURCE_DIR = The path in which the directory actually is
# $DEST_DIR = The path in which you also need it to be (like "/srv/http/" or something)
# 3) Add a remote to your local repository with "git add remote $REMOTE_NAME $SERVER_USER@$SERVER_ADDRESS:$BARE_REPOSITORY_DIR" (no quotes)
# $REMOTE_NAME = Name to which you will refer to this remote in your git commands
# $SERVER_USER = The name of the user you use on the remote server (the same you use to start SSH sessions)
# $SERVER_ADDRESS = The IP or HostName of the remote server (the same you use to start SSH sessions)
# $BARE_REPOSITORY_DIR = The directory you created the bare git repository (Step 1)
# This directory uses the user home directory as base, so if you created the directory in "/home/$SERVER_USER/git-bare-repository"
# you should use "git-bare-repository" (no quotes)
# 4) Push to your server using "git push $REMOTE_NAME" (no quotes)
# You can also pull from it using "git pull $REMOTE_NAME" (no quotes)
# Actually, any git command that you use a remote will work as long as you suply the $REMOTE_NAME in the correct argument
# 6) Configure the script variables TARGET, SOURCE, BRANCH
# 7) Modify the SUCCESS and POST_SUCCESS arrays to suit your needs
# 8) Modify or remove the example block of iterating over modified files
# 5) Be happy without all the hassle of connection to your remote server via SSH and doing a manual deploy
# NOTES:
# 1) This is all done over SSH so it has the same security as your SSH sessions
# 2) Make sure your SSH Agent is running at the time you're issuing a git command using the remote server
# 3) If you use SSH Keys make sure they were added to your running SSH Agent
# 4) I also made a script to partially automate the SSH Agent and Keys management: https://gist.github.com/Eihen/7fececcfe9abfb55bddfcc8bf99e37c1
# That script was tested and works on both Linux Bash and Git Bash for Windows (If you find any problems, please, let me know)
# It's very simple for compatibility with Git Bash for Windows, so if you use Linux there are better ways of doing this, take a look at:
# https://wiki.archlinux.org/index.php/SSH_keys
# https://wiki.archlinux.org/index.php/KDE_Wallet#Using_the_KDE_Wallet_to_store_ssh_key_passhprases
# https://wiki.archlinux.org/index.php/GnuPG#SSH_agent
# Even tough they are from the ArchLinux wiki it WILL work on other distros with small modifications (like file locations or package names)
# 5) Take care with the commands you set to be executed on this scripts, test then severely before using in production
# 6) I really recommend the first command on the SUCCESS array to be a backup of your database (if you use one)
# this can save your life if something goes wrong
# 7) Just reminding you that the responsibility for whatever damage this script causes is solely yours
# But if something goes wrong let me know to see if I can help you (and/or fix the script)
# A LAST TIME: If you need ANY KIND OF HELP related to this script, be it a problem understanding the instructions, the script itself,
# if you find a problem, if anything went wrong (with the script or EVEN WITH YOUR COMMANDS) or help to write your commands
# LET ME KNOW and I'll be happy to help you in whichever way I can
# TODO: MODIFY THE CONFIGURATION VARIABLES
TARGET=/woktree/directory
SOURCE=/bare/git/repository/directory
BRANCH=name-of-the-branch-that-can-be-deplyed-to-this-server
# TODO: MODIFY THE COMMANDS ARRAYS TO SUIT YOUR NEED OR LEAVE THEM EMPTY IF YOU DON'T NEED THEM
# The commands on the arrays are executed on the definition order
# Comands to be executed right after the checkout
SUCCESS=(
"command1"
"command2"
)
# Commands to be executed after everything else has been done
POST_SUCCESS=(
"command3"
"command4"
)
while read oldrev newrev ref
do
# Check if pushed branch is allowed to be deployed
if [[ $ref =~ .*/"$BRANCH"$ ]]; then
echo "$BRANCH ref received. Deploying to testing environment..."
# Checkout deployed branch on the defined workdir
git --work-tree="$TARGET" --git-dir="$SOURCE" checkout -f "$BRANCH"
# Execute the commands defined on the SUCCESS array
for cmd in "${SUCCESS[@]}"
do
$cmd
done
# TODO: MODIFY THIS BLOCK TO YOUR NEEDs OR REMOTE IT IF YOU DON'T NEED IT, it's just here as an example
# Execute commands when files (or a single file) matching a regex were modified between this and the last deploy
git --work-tree="$TARGET" --git-dir="$SOURCE" diff --name-only $oldrev $newrev | grep "regex.for.file.names$" | while read file
do
command5
command6-UsingFileAsArgument $file
done
# TODO: IF YOU NEED ANY CUSTOM BEHAVIOR INSERT IT UNDER THIS (between SUCCESS and POST_SUCCESS execution)
# Execute the commands defined on the POST_SUCCESS array
for cmd in "${POST_SUCCESS[@]}"
do
$cmd
done
else
# Notify user that the pushed branch can't be deployed on this server
echo "$ref ref received. Doing nothing because only the $BRANCH ref may be deplyed to this server."
fi
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment