Skip to content

Instantly share code, notes, and snippets.

@allex
Last active August 25, 2016 05:40
Show Gist options
  • Save allex/83957b884c8d9566f4ad to your computer and use it in GitHub Desktop.
Save allex/83957b884c8d9566f4ad to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Distribute git project to remote server by SSH
# Author: Allex Wang ([email protected])
# GistID: 83957b884c8d9566f4ad
# GistURL: https://gist.github.com/83957b884c8d9566f4ad
branch=release
commit=
server_list=
publish=
source=
use_scp=
user=apps
deploy_key="${GIT_DEPLOY_KEY:-$HOME/.ssh/id_rsa}"
ssh_opt="-o ConnectTimeout=5 -o StrictHostKeyChecking=no -o GSSAPIAuthentication=no -i ${deploy_key}"
ssh="ssh -T ${ssh_opt}"
usage() {
local prog=`basename $0`
cat <<-HELP
Usage: $prog [options]
-u <repository_url>
-b <branch>
-r <commit_sha1>
-d <server_list>
-s <surce_dir>
-t <remote_dir>
-p Publish project meta info
-x Turn on xtrace
-h Show this help info
HELP
}
get_abs_path() {
local p="$1"
local f=
if [ -f "$p" ]; then
f="`basename $p`"
p="`dirname $p`"
fi
p=`cd -P -- "$p" 2>/dev/null && pwd -P`
printf "$p/$f"
}
while getopts ":u:b:r:d:s:t:pxh" opt
do
case $opt in
u) REPO_URL=$OPTARG ;;
b) branch=$OPTARG ;;
r) commit=$OPTARG ;;
d) server_list=$(echo $OPTARG|tr , ' ') ;;
s) source=$OPTARG ;;
t) remote_dir=$OPTARG ;;
x) debug=1; set -x ;;
h)
usage
exit
;;
p)
git release publish
;;
:)
echo >&2 "Option -$OPTARG requires an argument."
exit 500
;;
esac
done
if [ "x$source" = "x" ]; then
# distribute by git
[ -n "$remote_dir" ] || remote_dir=`git rev-parse --show-toplevel`
[ $? -eq 0 ] || { exit $?; }
[ -n "$remote_dir" ] || { echo "GIT top-level directory not valid, Exit."; exit 1; }
source="$remote_dir"
REPO_URL=$(git config --get remote.origin.url)
if [[ $REPO_URL == git@* ]]; then
REPO_URL="http://$(echo ${REPO_URL}|sed -e "s/git@//g"|tr ':' '/')"
fi
git ls-remote -h --exit-code ${REPO_URL} $branch &>/dev/null || branch=`git rev-parse --abbrev-ref HEAD`
else
[ "$source" ] && source=$(get_abs_path "$source")
# fix remote_dir by source path
if [ "x$remote_dir" = "x" ]; then
[ "$source" ] || { echo >&2 "Not a valid source dir"; exit 1; }
if [ -f "$source" ]; then
remote_dir="`dirname $source`"
else
remote_dir="$source"
fi
fi
use_scp=1
fi
if [ -d "${source}/.git" ]; then
pushd $source >/dev/null
git fetch origin +$branch:refs/remotes/origin/$branch -ufv
if [ "x$commit" = "x" ]; then
commit=`git rev-parse --short origin/$branch`
else
commit=`git rev-parse --short $commit`
fi
popd >/dev/null
fi
SEED="$(date "+%Y%m%d%H%M%S").$$"
LOG_FILE="/tmp/git-deploy.$SEED.log"
DEPLOY_TARBALL="/tmp/${SEED}.tgz"
exec 4<> "$LOG_FILE"
cleanup() {
[ -f "$DEPLOY_TARBALL" ] && rm -f "$DEPLOY_TARBALL"
}
trap cleanup 0 1 2 3 13 15 9
dist()
{
local list=()
local mode=0
if [ -n "${server_list}" ]; then
list=( ${server_list} )
mode=1
else
echo "Enter the server name to distribute. (q to exit)"
read -t 90 -p ">>> "
local ex=$?
local ip=$REPLY
# timeout exit.
[ $ex -eq 0 ] || return $ex
[ "$ip" != "q" ] || return 1;
list=( $ip )
fi
# verify commit by grep pattern
if [ -n "$commit" ]; then
(c=$(git log -1 --pretty="%h" --grep "$grepstr" "$commit")
if [ "$c" != "$commit" ]; then
echo >&2 "fatal: The target refspec not a valid commit. Aborting."
exit 1
fi) \
|| exit $?
fi
if [ "$use_scp" ] ; then
if git rev-parse --git-dir >/dev/null 2>&1; then
# archive git release package
[ "x$commit" != "x" ] && [ ! -r "$DEPLOY_TARBALL" ] \
&& echo "git archive $commit ..." \
&& git archive $commit -o $DEPLOY_TARBALL
else
[ -r "$source" ] \
&& echo "build release package ..." \
&& (if [ -f "$source" ]; then
dir=`dirname $source`
dest=${source##*/}
else
dir="$source"
dest=./
fi
cd "$dir" && tar -czf "$DEPLOY_TARBALL" "$dest") \
|| (exit 1)
fi
[ $? -eq 0 ] || { echo "Build distribute package failed. Exiting."; exit 1; }
fi
if [ -n "${list}" ]; then
echo '-----'
# distribute release
for i in "${list[@]}"; do (
echo "-> ${i}:${remote_dir} ..."
if $ssh -q $user@$i true; then
if [ $use_scp ]
then
# scp deploy
if [ -r "$DEPLOY_TARBALL" ]; then
scp ${ssh_opt} -qrp -C "$DEPLOY_TARBALL" "$user@$i:/tmp/" \
&& $ssh $user@$i <<ENDSSH
set -e
[ "$debug" ] && set -x || true
trap "rm -f "$DEPLOY_TARBALL"; exit" 0 1 2 3 13 15 9;
[ -r /etc/profile ] && source /etc/profile
mkdir -p "$remote_dir" \
&& tar -C "$remote_dir" -xzf "$DEPLOY_TARBALL" \
&& echo $commit >"$remote_dir/.VERSION" \
&& echo done. \
&& (if [ -f "$remote_dir/.dist.json" ]; then
PATH=/usr/local/nodejs/bin:/apps/svr/nodejs/bin/:/apps/data/web/working/fe.bubugao-inc.com/deploy/node_modules/.bin:\$PATH
if which build-client &>/dev/null; then
cd "$remote_dir" \
&& name=\$(node -p "require('./.dist.json').name") \
&& build-client --registry http://127.0.0.1:7894/deploy/ . -e test \
&& curl -s http://127.0.0.1:7894/deploy/update/\$name
else
echo "$i: deploy service not running." >&2
fi
fi)
ENDSSH
fi
else
# git deploy
$ssh $user@$i <<ENDSSH
set -e
[ "$debug" ] && set -x || true
mkdir -p "${remote_dir}"
cd "${remote_dir}"
if [ -d "${remote_dir}/.git" ]; then
if [ "$(git config --get remote.origin.url)" != "${REPO_URL}" ]; then
git remote rm origin && git remote add origin "${REPO_URL}"
fi
git fetch -upfvq origin +$branch:$branch \
&& git reset --hard $branch -- &>/dev/null \
&& git clean -dfx
else
git clone -b $branch "${REPO_URL}" "${remote_dir}"
fi
[ $? -eq 0 ] \
&& (if [ -n "$commit" ]; then git reset --hard $commit -- &>/dev/null; fi) \
&& git log -1 --pretty=format:'[%h] => %s (%ai)' \
&& echo done. \
&& echo $commit >"$remote_dir/.VERSION" \
&& (if [ -f "$remote_dir/.dist.json" ]; then
PATH=/usr/local/nodejs/bin:/apps/svr/nodejs/bin/:/apps/data/web/working/fe.bubugao-inc.com/deploy/node_modules/.bin:\$PATH
if which build-client &>/dev/null; then
cd "$remote_dir" \
&& name=\$(node -p "require('./.dist.json').name") \
&& build-client --registry http://127.0.0.1:7894/deploy/ . -e test \
&& curl -s http://127.0.0.1:7894/deploy/update/\$name
else
echo "$i: deploy service not running." >&2
fi
fi)
ENDSSH
fi
else
echo "ERR: Host key verification failed."
fi
echo '-----'
) 2>&4; done
fi
[ $mode -eq 1 ] || { echo; dist; }
}
dist
# vim: set fdm=manual ts=2 sw=2 sts=2 tw=85 et :
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment