| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376 | 
							- #!/usr/bin/env bash
 
- #
 
- # deploy(1) - Minimalistic shell script to deploy Git repositories.
 
- # Released under the MIT License.
 
- #
 
- # https://github.com/visionmedia/deploy
 
- #
 
- VERSION="0.6.0"
 
- CONFIG=./deploy.conf
 
- LOG=/tmp/pm2-deploy-${USER:-default}.log
 
- FORCE=0
 
- REF=
 
- ENV=
 
- #
 
- # Read PIPED JSON
 
- #
 
- read conf
 
- #
 
- # 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
 
-     -V, --version        output program version
 
-     -h, --help           output help information
 
-     -f, --force          skip local change checking
 
-   Commands:
 
-     setup                run remote setup commands
 
-     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>
 
-     list                 list previous deploy commits
 
-     ref [ref]            deploy [ref]
 
- EOF
 
- }
 
- #
 
- # Abort with <msg>
 
- #
 
- abort() {
 
-   echo
 
-   echo "  $@" 1>&2
 
-   echo
 
-   exit 1
 
- }
 
- #
 
- # Log <msg>.
 
- #
 
- log() {
 
-   echo "  ○ $@"
 
- }
 
- #
 
- # Get config value by <key>.
 
- #
 
- config_get() {
 
-     local key=$1
 
-     echo $(expr "$conf" : '.*"'$key'":"\([^"]*\)"')
 
- }
 
- #
 
- # Output version.
 
- #
 
- version() {
 
-   echo $VERSION
 
- }
 
- #
 
- # Return the ssh command to run.
 
- #
 
- ssh_command() {
 
-   local user="`config_get user`"
 
-   if test -n "$user"; then
 
-       local url="$user@`config_get host`"
 
-   else
 
-       local url="`config_get host`"
 
-   fi
 
-   local unexpanded_key="`config_get key`"
 
-   local key="${unexpanded_key/#\~/$HOME}"
 
-   local forward_agent="`config_get forward-agent`"
 
-   local port="`config_get port`"
 
-   local needs_tty="`config_get needs_tty`"
 
-   local ssh_options="`config_get ssh_options`"
 
-   test -n "$forward_agent" && local agent="-A"
 
-   test -n "$key" && local identity="-i $key"
 
-   test -n "$port" && local port="-p $port"
 
-   test -n "$needs_tty" && local tty="-t"
 
-   test -n "ssh_options" && local ssh_opts="$ssh_options"
 
-   echo "ssh $ssh_opts $tty $agent $port $identity $url"
 
- }
 
- #
 
- # Run the given remote <cmd>.
 
- #
 
- runRemote() {
 
-   local shell="`ssh_command`"
 
-   echo $shell "\"$@\"" >> $LOG
 
-   $shell $@
 
- }
 
- #
 
- # Run the given local <cmd>.
 
- #
 
- runLocal() {
 
-   echo "\"$@\"" >> $LOG
 
-   /usr/bin/env bash -c "$*"
 
- }
 
- #
 
- # Run the given <cmd> either locally or remotely
 
- #
 
- run() {
 
-   local host="`config_get host`"
 
-   if [[ $host == localhost ]]
 
-   then
 
-     runLocal $@
 
-   else
 
-     runRemote $@
 
-   fi
 
- }
 
- #
 
- # Output config or [key].
 
- #
 
- config() {
 
-     echo $(expr "$conf" : '.*"$key":"\([^"]*\)"')
 
- }
 
- #
 
- # Execute hook <name> relative to the path configured.
 
- #
 
- hook() {
 
-   test -n "$1" || abort hook name required
 
-   local hook=$1
 
-   local path=`config_get path`
 
-   local cmd=`config_get $hook`
 
-   if test -n "$cmd"; then
 
-     log "executing $hook \`$cmd\`"
 
-     run "cd $path/current; \
 
-       SHARED=\"$path/shared\" \
 
-       $cmd 2>&1 | tee -a $LOG; \
 
-       exit \${PIPESTATUS[0]}"
 
-     test $? -eq 0
 
-   else
 
-     log hook $hook
 
-   fi
 
- }
 
- #
 
- # Pre Setup hook runs on the host before the actual setup runs
 
- # multiple commands or a script
 
- #
 
- hook_pre_setup() {
 
-   local cmd=`config_get pre-setup`
 
-   if test -n "$cmd"; then
 
-     local is_script=($cmd)
 
-     if [ -f "${is_script[0]}" ]; then
 
-       log "executing pre-setup script \`$cmd\`"
 
-       local shell="`ssh_command`"
 
-       runLocal "$shell 'bash -s' -- < $cmd"
 
-     else
 
-       log "executing pre-setup \`$cmd\`"
 
-       run "$cmd"
 
-     fi
 
-     test $? -eq 0
 
-   else
 
-     log hook pre-setup
 
-   fi
 
- }
 
- #
 
- # Run setup.
 
- #
 
- setup() {
 
-   local path=`config_get path`
 
-   local repo=`config_get repo`
 
-   local ref=`config_get ref`
 
-   local fetch=`config_get fetch`
 
-   local branch=${ref#*/}
 
-   hook_pre_setup || abort pre-setup hook failed
 
-   run "mkdir -p $path/{shared/{logs,pids},source}"
 
-   test $? -eq 0 || abort setup paths failed
 
-   log running setup
 
-   log cloning $repo
 
-   if test "$fetch" != "fast"; then
 
-     log "full fetch"
 
-     run "git clone --branch $branch $repo $path/source"
 
-   else
 
-     log "fast fetch"
 
-     run "git clone --depth=5 --branch $branch $repo $path/source"
 
-   fi
 
-   test $? -eq 0 || abort failed to clone
 
-   run "ln -sfn $path/source $path/current"
 
-   test $? -eq 0 || abort symlink failed
 
-   hook post-setup || abort post-setup hook failed
 
-   log setup complete
 
- }
 
- #
 
- # Deploy [ref].
 
- #
 
- deploy() {
 
-   local ref=$1
 
-   local branch=$2
 
-   if test -z "$branch"; then
 
-     branch=${ref#*/}
 
-   fi
 
-   local path=`config_get path`
 
-   local fetch=`config_get fetch`
 
-   log "deploying ${ref}"
 
-   # 1- Execute local commands
 
-   log executing pre-deploy-local
 
-   local pdl=`config_get pre-deploy-local`
 
-   runLocal $pdl || abort pre-deploy-local hook failed
 
-   # 2- Execute pre deploy commands on remote server
 
-   hook pre-deploy || abort pre-deploy hook failed
 
-   # 3- Fetch updates
 
-   log fetching updates
 
-   if test "$fetch" != "fast"; then
 
-       log "full fetch"
 
-       run "cd $path/source && git fetch --all --tags"
 
-   else
 
-       log "fast fetch"
 
-       run "cd $path/source && git fetch --depth=5 --all --tags"
 
-   fi
 
-   test $? -eq 0 || abort fetch failed
 
-   # 4- If no reference retrieve shorthand name for the remote repo
 
-   if test -z "$ref"; then
 
-     log fetching latest tag
 
-     ref=`run "cd $path/source && git for-each-ref \
 
-       --sort=-*authordate \
 
-       --format='%(refname)' \
 
-       --count=1 | cut -d '/' -f 3"`
 
-     test $? -eq 0 || abort failed to determine latest tag
 
-   fi
 
-   # 5- Reset to ref
 
-   log resetting HEAD to $ref
 
-   run "cd $path/source && git reset --hard $ref"
 
-   test $? -eq 0 || abort git reset failed
 
-   # 6- Link current
 
-   run "ln -sfn $path/source $path/current"
 
-   test $? -eq 0 || abort symlink failed
 
-   # deploy log
 
-   run "cd $path/source && \
 
-       echo \`git rev-parse HEAD\` \
 
-       >> $path/.deploys"
 
-   test $? -eq 0 || abort deploy log append failed
 
-   hook post-deploy || abort post-deploy hook failed
 
-   # done
 
-   log successfully deployed $ref
 
- }
 
- #
 
- # Get current commit.
 
- #
 
- current_commit() {
 
-   local path=`config_get path`
 
-   run "cd $path/source && \
 
-       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 "tac $path/.deploys | awk '{printf \"%d\t%s\n\", NR-1, \$0}'"
 
- }
 
- #
 
- # 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"
 
- }
 
- #
 
- # Ensure all changes are committed and pushed before deploying.
 
- #
 
- check_for_local_changes() {
 
-   local path=`config_get path`
 
-   if [ $FORCE -eq 1 ]
 
-   then
 
-       return
 
-   fi
 
-   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 @{upstream}.. -n 1`" ]       || abort "push your changes before deploying"
 
- }
 
- # parse argv
 
- while test $# -ne 0; do
 
-   arg=$1; shift
 
-   case $arg in
 
-     -h|--help) usage; exit ;;
 
-     -V|--version) version; exit ;;
 
-     -C|--chdir) log cd $1; cd $1; shift ;;
 
-     -F|--force) FORCE=1 ;;
 
-     run|exec)  run "cd `config_get path`/current && $@"; exit ;;
 
-     console)  console; exit ;;
 
-     curr|current)  current_commit; exit ;;
 
-     prev|previous)  nth_deploy_commit 2; exit ;;
 
-     revert)  revert_to ${1-1}; exit ;;
 
-     setup)  setup $@; exit ;;
 
-     list)  list_deploys; exit ;;
 
-     config) config $@; exit ;;
 
-     ref) REF=$1; BRANCH=$2 ;;
 
-   esac
 
- done
 
- check_for_local_changes
 
- echo
 
- # deploy
 
- deploy "${REF:-`config_get ref`}" "${BRANCH}"
 
 
  |