Last active
August 25, 2016 05:40
-
-
Save allex/83957b884c8d9566f4ad to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
# 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