Skip to content

Instantly share code, notes, and snippets.

@miraculixx
Created March 8, 2019 16:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save miraculixx/f70e5f91e96f8ceba98a85dd75530663 to your computer and use it in GitHub Desktop.
Save miraculixx/f70e5f91e96f8ceba98a85dd75530663 to your computer and use it in GitHub Desktop.
gitdeploy
#!/usr/bin/env bash
# adopted from https://raw.githubusercontent.com/X1011/git-directory-deploy/master/deploy.sh
#
# changes
# * deploy from current directory is possible
# * set options from either .deploy file or parameters
set -o errexit #abort if any command fails
PREFIX=.
CONFIG=.deploy
# getting the last argument as the appname
appname=${@: -1}
appname=${appname:=default}
function show_help {
echo " $0 [options] [DEPLOYDIRECTORY] [APPNAME]"
echo ""
echo " APPNAME the application name as in $CONFIG"
echo " -v, --verbose print details"
echo " -s, --setup setup and deploy"
echo " -r, --repo the remote repository"
echo " -M, --remote-branch the remote branch"
echo " -B, --branch the local branch"
echo " -D, --directory the directory, from git root"
echo " -C, --config use a different config file (default $CONFIG)"
echo " -R, --reset BRANCH reset a failed deployment to BRANCH"
echo " -X, --resetup delete git setup and reset"
echo " -h this help"
echo " "
echo " All options can be specified in the .deploy file in the"
echo " respective deploy directory."
echo " "
}
function config_init {
cat << EOF > $CONFIG
[default]
# path to deploy from gitroot
deploy_directory=path/to/deploy;
# local git branch to deploy from (make this different from any other branch)
# convention is hk-deploy-appname
deploy_branch=deploy-branch;
# remote git branch to deploy to
deploy_branch_remote=master;
# git remote to deploy to, must be readable and writable.
repo=deploy;
# url of remote repo.
repourl=git@heroku.com:hkpcpsbbstage.git;
# Site environment to be used, this is what the packages are built for
# using fab build:siteenv
siteenv=default;
# Deploy environment
deploy_env=EnvSettings_site;
# if no user identity is already set in the current git environment, use this
# username to be used to login to deployment servers
default_username=ubuntu;
# heroku app instance type examples are ( matser, ipython, schedule, collector, etc)
apptype=master;
# app whose services are to be used in this app
master=default;
EOF
echo "Created $CONFIG"
}
# function to parse the ini style configuration file
function config_parser () {
local iniFile="$1";
local tmpFile=$( mktemp /tmp/`basename $iniFile`.XXXXXX );
local intLines;
local binSED=$( which sed );
# copy the ini file to the temporary location
cp $iniFile $tmpFile;
# remove tabs or spaces around the =
$binSED -i -e 's/[ \t]*=[ \t]*/=/g' $tmpFile;
# transform section labels into function declaration
$binSED -i -e 's/\[\([A-Za-z0-9_-]*\)\]/config.section.\1() \{/g' $tmpFile;
$binSED -i -e 's/config\.section\./\}\'$'\nconfig\.section\./g' $tmpFile;
# remove first line
$binSED -i -e '1d' $tmpFile;
# add the last brace
echo -e "\n}" >> $tmpFile;
# now load the file
source $tmpFile;
# clean up
rm -f $tmpFile;
}
function reset_branch() {
RESET_BRANCH=$1
echo resetting to $RESET_BRANCH
git symbolic-ref HEAD refs/heads/$RESET_BRANCH && git reset --mixed >&2
}
if [[ "$1" == "-R" || "$1" == "--reset" ]]; then
reset_branch $2
exit 0
fi
# Parse arg flags
while : ; do
if [[ $1 == "-v" || $1 == "--verbose" ]]; then
verbose=true
shift
elif [[ $1 == "-s" || $1 == "--setup" ]]; then
setup=true
shift
elif [[ $1 == "-r" || $1 == "--repo" ]]; then
repo=$2
shift 2
elif [[ $1 == "-M" || $1 == "--remote-branch" ]]; then
deploy_branch_remote=master=$2
shift 2
elif [[ $1 == "-B" || $1 == "--branch" ]]; then
deploy_branch=$2
shift 2
elif [[ $1 == "-D" || $1 == "--directory" ]]; then
deploy_directory=$2
shift 2
elif [[ $1 == "-C" || $1 == "--config" ]]; then
CONFIG=$2
shift 2
elif [[ $1 == "-h" ]]; then
show_help
exit 0
elif [[ $1 == "-X" || $1 == "--resetup" ]]; then
resetup=true
shift
else
break
fi
done
if [[ ! -f "$CONFIG" ]]; then
echo "$CONFIG not found. Create?"
select result in Yes No; do
if [[ "$result" == "Yes" ]]; then
config_init
fi
exit 0
done
fi
# load config
config_parser "$CONFIG"
function go_gitroot {
GIT_TOPLEVEL="$(git rev-parse --show-toplevel)"
PREFIX=${PWD#"$GIT_TOPLEVEL/"}
pushd $GIT_TOPLEVEL
}
#echo expanded commands as they are executed (for debugging)
function enable_expanded_output {
if [ $verbose ]; then
set -o xtrace
set +o verbose
fi
}
#this is used to avoid outputting the repo URL, which may contain a secret token
function disable_expanded_output {
if [ $verbose ]; then
set +o xtrace
set -o verbose
fi
}
enable_expanded_output
function set_user_id {
if [[ -z `git config user.name` ]]; then
git config user.name "$default_username"
fi
if [[ -z `git config user.email` ]]; then
git config user.email "$default_email"
fi
}
function restore_head {
if [[ $previous_branch = "HEAD" ]]; then
#we weren't on any branch before, so just set HEAD back to the commit it was on
git update-ref --no-deref HEAD $commit_hash $deploy_branch
else
git symbolic-ref HEAD refs/heads/$previous_branch
fi
git reset --mixed
popd
}
if [[ `type -t config.section.$appname` == 'function' ]]; then
config.section.$appname
else
echo "FATAL!! No config for the app $appname in $CONFIG"
exit 0
fi
commit_title=`git log -n 1 --format="%s" HEAD`
commit_hash=`git log -n 1 --format="%H" HEAD`
previous_branch=`git rev-parse --abbrev-ref HEAD`
go_gitroot
if [ $resetup ]; then
echo Deleting setup
git remote remove $repo
git branch -D $deploy_branch
setup=true
fi
if [ $setup ]; then
echo Setting up
mkdir -p $deploy_directory
git remote add $repo $repourl
git --work-tree $deploy_directory checkout --orphan $deploy_branch
git --work-tree $deploy_directory rm --cached "*"
git --work-tree $deploy_directory add --all
git --work-tree $deploy_directory commit -m "initial publish"$'\n\n'"generated from commit $commit_hash"
git push --force $repo $deploy_branch:$deploy_branch_remote
restore_head
exit
fi
if ! git diff --exit-code --quiet --cached; then
echo Aborting due to uncommitted changes in the index >&2
exit 1
fi
disable_expanded_output
git fetch --force $repo $deploy_branch_remote:$deploy_branch
enable_expanded_output
#make deploy_branch the current branch
git symbolic-ref HEAD refs/heads/$deploy_branch
#put the previously committed contents of deploy_branch branch into the index
git --work-tree "$deploy_directory" reset --mixed --quiet
git --work-tree "$deploy_directory" add --all
set +o errexit
diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD)$?
set -o errexit
case $diff in
0) echo No changes to files in $deploy_directory. Skipping commit.;;
1)
set_user_id
git --work-tree "$deploy_directory" commit -m \
"publish: $commit_title"$'\n\n'"generated from commit $commit_hash"
disable_expanded_output
#--quiet is important here to avoid outputting the repo URL, which may contain a secret token
git push --force $repo $deploy_branch:$deploy_branch_remote
enable_expanded_output
;;
*)
echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to master, use: git symbolic-ref HEAD refs/heads/master && git reset --mixed >&2
exit $diff
;;
esac
restore_head
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment