Skip to content

Instantly share code, notes, and snippets.

@michaelaguiar
Created June 9, 2012 07:49
Show Gist options
  • Save michaelaguiar/2900031 to your computer and use it in GitHub Desktop.
Save michaelaguiar/2900031 to your computer and use it in GitHub Desktop.
Deploy
README HERE
#!/usr/bin/env bash
VERSION="0.7.0"
CONFIG=./deploy.conf
LOG=/tmp/deploy.log
TEST=1
REF=
ENV=
#
# Output usage information.
#
usage() {
cat <<-EOF
Usage: deploy [options] <env> [command]
Options:
-C, --chdir <path> change the working directory to <path>
-c, --config <path> set config path. defaults to ./deploy.conf
-T, --no-tests ignore test hook
-V, --version output program version
-h, --help output help information
Commands:
setup run remote setup commands
update update deploy to the latest release
revert [n] revert to [n]th last deployment or 1
config [key] output config file or [key]
curr[ent] output current release commit
prev[ious] output previous release commit
exec|run <cmd> execute the given <cmd>
console open an ssh session to the host
list list previous deploy commits
[ref] deploy to [ref], the 'ref' setting, or latest tag
EOF
}
#
# Output version.
#
version() {
echo $VERSION
}
#
# Log <msg>.
#
log() {
echo " > $@"
}
#
# Abort with <msg>
#
abort() {
echo " > $@" 1>&2
exit 1
}
#
# Set configuration file <path>.
#
set_config_path() {
test -f $1 || abort invalid --config path
CONFIG=$1
}
#
# Check if config <section> exists.
#
config_section() {
grep "^\[$1" $CONFIG &> /dev/null
}
#
# Get config value by <key>.
#
config_get() {
local key=$1
test -n "$key" \
&& grep "^\[$ENV" -A 20 $CONFIG \
| grep "^$key" \
| head -n 1 \
| cut -d ' ' -f 2-999
}
#
# Return the ssh command to run.
#
ssh_command() {
local url="`config_get user`@`config_get host`"
local key="`config_get key`"
local forward_agent="`config_get forward-agent`"
test -n "$forward_agent" && local agent="-A"
test -n "$key" && local identity="-i $key"
echo "ssh $agent $identity $url"
}
#
# Run the given remote <cmd>.
#
run() {
local shell="`ssh_command`"
echo $shell "\"$@\"" >> $LOG
$shell $@
}
#
# Launch an interactive ssh console session.
#
console() {
local shell="`ssh_command`"
echo $shell
exec $shell
}
#
# Output config or [key].
#
config() {
if test $# -eq 0; then
cat $CONFIG
else
config_get $1
fi
}
#
# Run setup.
#
setup() {
local path=`config_get path`
local repo=`config_get repo`
log Setting up remote server
run "if [ ! -d $path/.git ]; \
then git clone $repo $path; \
fi;" 2>/dev/null
test $? -eq 0 || abort Setup Failed
log Setup Complete
}
#
# Deploy
#
deploy() {
local ref=$1
local path=`config_get path`
log Deploying $ref
# Update
log Fetching Updates
run "cd $path; git fetch origin; git reset --hard $ref"
test $? -eq 0 || abort Fetch failed
# Update log
log Updating Log
run "cd $path && \
echo \`git rev-parse --short HEAD\` \
>> $path/.deploys"
test $? -eq 0 || abort Update log failed
if test $TEST -eq 1; then
if test $? -ne 0; then
log Tests failed, reverting
quickly_revert_to 1 && log "Revert complete" && exit
fi
else
log Ignoring tests
fi
log Successfully deployed $ref
}
#
# Get current commit.
#
current_commit() {
local path=`config_get path`
run "cd $path; git rev-parse --short HEAD"
}
#
# Get <n>th deploy commit.
#
nth_deploy_commit() {
local n=$1
local path=`config_get path`
run "cat $path/.deploys | tail -n $n | head -n 1 | cut -d ' ' -f 1"
}
#
# List deploys.
#
list_deploys() {
local path=`config_get path`
run "cat $path/.deploys"
}
#
# Revert to the <n>th last deployment, ignoring tests.
#
quickly_revert_to() {
local n=$1
log "quickly reverting $n deploy(s)"
local commit=`nth_deploy_commit $((n + 1))`
TEST=0 deploy "$commit"
}
#
# Revert to the <n>th last deployment.
#
revert_to() {
local n=$1
log "reverting $n deploy(s)"
local commit=`nth_deploy_commit $((n + 1))`
deploy "$commit"
}
#
# Require environment arg.
#
require_env() {
config_section $ENV || abort "[$ENV] config section not defined"
test -z "$ENV" && abort "<env> required"
}
#
# Ensure all changes are committed and pushed before deploying.
#
check_for_local_changes() {
git --no-pager diff --exit-code --quiet || abort "Commit or stash your changes before deploying"
git --no-pager diff --exit-code --quiet --cached || abort "Commit your staged changes before deploying"
[ -z "`git rev-list origin.. -n 1`" ] || abort "Push your changes before deploying"
}
#
# Update deploy.
#
update() {
log Updating deploy
rm -fr /tmp/deploy
git clone git://github.com/michaelaguiar/deploy.git \
--depth 0 \
/tmp/deploy \
&> /tmp/deploy.log \
&& cd /tmp/deploy \
&& make install \
&& log "Updated $VERSION -> `./bin/deploy --version`"
}
# parse argv
while test $# -ne 0; do
arg=$1; shift
case $arg in
-h|--help) usage; exit ;;
-V|--version) version; exit ;;
-c|--config) set_config_path $1; shift ;;
-C|--chdir) log cd $1; cd $1; shift ;;
-T|--no-tests) TEST=0 ;;
run|exec) require_env; run "cd `config_get path` && $@"; exit ;;
console) require_env; console; exit ;;
curr|current) require_env; current_commit; exit ;;
prev|previous) require_env; nth_deploy_commit 2; exit ;;
revert) require_env; revert_to ${1-1}; exit ;;
setup) require_env; setup $@; exit ;;
list) require_env; list_deploys; exit ;;
update) update; exit ;;
config) config $@; exit ;;
*)
if test -z "$ENV"; then
ENV=$arg;
else
REF="$REF $arg";
fi
;;
esac
done
require_env
check_for_local_changes
# deploy
deploy "${REF:-`config_get ref`}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment