Skip to content

Instantly share code, notes, and snippets.

@allex
Last active August 29, 2015 14:19
Show Gist options
  • Save allex/fbe05460d1f4005047ad to your computer and use it in GitHub Desktop.
Save allex/fbe05460d1f4005047ad to your computer and use it in GitHub Desktop.
#!/bin/sh
# Toolkit script for git repos build and distribute release.
# Author: Allex Wang ([email protected])
# GistID: fbe05460d1f4005047ad
dir=`cd $(dirname $0); pwd -P`
source=$dir/source
[ -d $source ] || { echo >&2 "source dir not exists." && exit 404; }
out=$dir/out
lockfile=$out/.lock
verfile=$out/.version
rebuild=1
force=0
publish=0
exclude=( ".svn" ".git" )
while getopts ":u:b:m:d:e:fi" opt
do
case $opt in
u) repo_url=$OPTARG ;;
b) branch=$OPTARG ;;
m) IFS="," read -ra mods <<< "$OPTARG"
has_topic=0
for i in "${mods[@]}"; do
[ "$i" == "topic" ] && { has_topic=1; break; }
done
[ $has_topic -eq 1 ] || exclude+=("*topic/*")
;;
d) IFS="," read -ra server <<< "$OPTARG" ;;
f) force=1 ;;
i) rebuild=0 ;;
e) [ "$OPTARG" == "pro" ] && publish=1 ;;
:) echo >&2 "Option -$OPTARG requires an argument."
exit 500
;;
esac
done
if [ -z "$mods" ]; then
echo ""
echo "$(basename $0) [-f] [-m module_list] [-e environment]"
echo ""
echo " -m <module_name> A comma-separated module list to build, eg. public,admin"
echo ""
exit 1;
fi
if [ -f $lockfile ]
then
if [ $force -eq 1 ]; then
kill -9 `cat $lockfile`
rm -f $lockfile;
else
pid=`cat $lockfile`
if ps -p $pid > /dev/null
then
user=`ps aux|awk -v PID=$pid '$2 == PID { print $1 }'`
echo >&2 "[$user] build is running... (exit 1)" && exit 406;
fi
fi
fi
if [ -d $source/.git ]
then
if [ -z "$branch" ]; then
branch=$(cd $source && git rev-parse --abbrev-ref HEAD);
fi
echo "Current branch: $branch"
if [ $rebuild -eq 1 ]; then
eval "cd $source && git fetch origin && git reset --hard origin/$branch"
fi
rev=`cd $source && git rev-parse --short HEAD`
else
if [ -d $source/.svn ] ; then
svn up $source >/dev/null 2>&1
echo "Update source from remote repository, done"
fi
fi
VERSION=""
ts=${rev}.$(date +%s)
tarball="/tmp/build_${ts}.tgz"
exclude_pattern=""
init()
{
for i in "${exclude[@]}"; do
exclude_pattern+=" --exclude \"$i\""
done
trap eof SIGINT SIGTERM
echo $$ >$lockfile
}
eof()
{
[ -f $tarball ] && rm -rf $tarball
[ -f $lockfile ] && rm -rf $lockfile
exit 1;
}
dist()
{
[ -f $tarball ] || { eval "cd $out && tar czf $tarball $exclude_pattern ./"; }
local list=()
local mode=0
if [ -n "$server" ]; then
list=( ${server[@]} )
mode=1
else
read -t 40 -p "Enter the server name to distribute (q to exit): "
local ex=$?
local ip=$REPLY
# timeout exit.
[ $ex -eq 0 ] || return $ex
[ "$ip" != "q" ] || return 1;
local IFS=","
list=( $ip )
fi
if [ -n "${list}" ]; then
# distribute release
remote_dir="/apps/data/web/working/static5.bubugao.com/"
for i in "${list[@]}"
do
target=${i}:${remote_dir}
echo "Releasing to ${target} ..."
if ssh -q -o StrictHostKeyChecking=no -o BatchMode=yes $i true; then
scp -rpq $tarball "apps@$i:$tarball" && ssh apps@$i "mkdir -p \"$remote_dir\"; tar xzf $tarball -C \"$remote_dir\"; rm -f $tarball" && echo "Done. (build: $ts)"
else
echo >&2 "Host key verification failed."
fi
done
fi
[ $mode -eq 1 ] || dist;
}
cleanup_dist()
{
if [ -d $out/.svn ]; then
svn revert $out -R >/dev/null
svn st $out | grep '^?' | awk '{print $2}' | xargs rm -rf
svn up $out >/dev/null 2>&1
fi
}
commit_dist()
{
if [ -d $out/.svn ]; then
local st="svn status $out"
if [ -n "$st" ]; then
$st |sed -e '/^?/!d' -e 's/^? *//' |xargs -I{} svn add '{}@' >/dev/null 2>&1
$st |sed -e '/^!/!d' -e 's/^! *//' |xargs -I{} svn rm '{}@' >/dev/null 2>&1
fi
svn status $out
fi
echo
}
prompt_version()
{
local ver=""
local git="$1"
# get version by user input
read -t 600 -p "Please enter the version for release (eg: v0.0.1): " ver
local ex=$?
[ $ex -eq 0 ] || return $ex
if [ -z "$ver" ]; then
prompt_version;
else
if ! [[ "$ver" =~ ^v[0-9]+.[0-9]+.[0-9]+ ]]; then
echo "Not a valid version."
prompt_version && return;
fi
VERSION="${ver}"
if $git rev-parse ${VERSION} >/dev/null 2>&1; then
echo "tag exist (${VERSION})."
prompt_version;
fi
fi
}
build()
{
if [ $publish -eq 1 ]; then
cleanup_dist
fi
if [ $rebuild -ne 0 ]; then
args="$@"
if [[ ! "$args" =~ "-f " ]]; then
args="${args} -c $dir/build.json"
fi
if [[ ! "$args" =~ "-o " ]]; then
args="${args} -o $out"
fi
node $dir/bin/build.js $args
echo $ts >$verfile
fi
}
# commit release
release()
{
if [ $publish -eq 1 ]; then
commit_dist
local red=$(tput setaf 1)
local reset=$(tput sgr0)
read -t 180 -p "${red}Commit to release branche? [y|n]${reset} "
if [ "$REPLY" = "y" ]; then
git="git --git-dir=${source}/.git --work-tree=${source}"
$git fetch --tags &>/dev/null
prompt_version "$git"
if [ -n "$VERSION" ]; then
local msg="Release $VERSION"
svn ci $out -m "$msg" --force-log
[ $? -eq 0 ] && $git tag "${VERSION}" -m "Release $msg" && $git push origin --tags
echo "$msg, done"
else
echo "${red}Release build cancelled.${reset}"
fi
fi
fi
}
init
build "$@"
dist
release
eof
# 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