Last active
February 8, 2018 15:01
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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