Created
June 9, 2012 07:49
-
-
Save michaelaguiar/2900031 to your computer and use it in GitHub Desktop.
Deploy
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
README HERE |
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
#!/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