#!/usr/bin/env bash export LC_ALL="C" ## default config PAUSE_SECONDS=$((15*60)) BIN_PATH=`dirname $0` HTML_OUTPUT=0 SEND_MAIL=0 PUSH_NIGHTLIES=0 NICE= OWNER= GNUDATE=0 TINDERNAME= BANDWIDTH= LOCK= SMTPPORT=25 SMTPHOST= SMTPUSER= SMTPPW= ## Determine if we have GNU date(1) or not date --version 2> /dev/null | grep -q Free\ Software\ Foundation if [ $? -eq 0 ]; then GNUDATE=1 fi ## Determine how GNU make(1) is called on the system for _g in make gmake gnumake; do $_g --version 2> /dev/null | grep -q GNU if test $? -eq 0; then MAKE=$_g break fi done # Do we have flock? If yes, synchronize - if there are more tinbuilds running # at the same time, just one of them builds / installs / whatever at the given # time if which flock > /dev/null 2>&1 ; then LOCK=1 fi # Do we have timeout? If yes, guard git pull with that - which has a # tendency to hang forever, when connection is flaky if which timeout > /dev/null 2>&1 ; then # std coreutils - timeout is two hours timeout="`which timeout` 2h" elif which gtimeout > /dev/null 2>&1 ; then # Mac - timeout is two hours timeout="`which gtimeout` 2h" fi ## subroutines usage () { echo "Usage: $0 [options]" echo "Options:" echo "-d name of the distro-config to use" echo "-e don't synchronize (when running >1 tindbuilds at the same time)" echo "-h this help" echo "-i run with ionice -c3, can be combined with -n" echo "-l write html build log" echo "-m mail errors to the committer, general errors to the " echo "-n run with nice, can be combined with -i" echo "-r rsync build to nightlies archive, using KBytes/sec bandwidth" echo "-s SMTP server" echo "-c SMTP crypt to use - either none, tls or ssl" echo "-u SMTP user name for auth login" echo "-p SMTP password for auth login" echo "-t send tinderbox mails, identify self as " echo "-w specify timeout in secs between subsequent pull requests" } # echo the message to the screen including a timestamp echots () { echo "[`date -u '+%Y-%m-%d %H:%M:%S'` $TINDER_BRANCH]" "$@" } getCommitters () { from_date="$1" ./g -s log '--pretty=tformat:%ce' --after="$from_date" | sort | uniq | tr '\n' ',' } sendMailMsg () { TO="$1" SUBJECT="$2" HEADERS="$3" BCC="$4" LOG="$5" CMD='$BIN_PATH/sendEmail -q -f "$OWNER" -s "$SMTPHOST" -xu "$SMTPUSER" -xp "$SMTPPW" -t "$TO" -bcc "$BCC" -u "$SUBJECT" -o "message-header=$HEADERS"' if test -n "$LOG" && test -f "$LOG"; then CMD="$CMD -a $LOG" fi eval $CMD echots "Sent a mail to \"$TO\" with subject \"$SUBJECT\"." } reportError () { error_kind="$1" shift rough_time="$1" shift to_mail= if test "$SEND_MAIL" -eq 1; then case "$error_kind" in owner) to_mail="$OWNER" message="box broken" ;; *) if test -z "$last_success" ; then # we need at least one successful build to # be reliable to_mail="$OWNER" else to_mail=`getCommitters "$last_success"` fi message="last success: $rough_time" ;; esac fi echo "$*" 1>&2 echo "Last success: $rough_time" 1>&2 if test -n "$to_mail" ; then TINDER1= TINDER2= if test "$SEND_MAIL" -eq 1 -a -n "$TINDERNAME" ; then TINDER1="`echo \"Full log available at http://tinderbox.libreoffice.org/$TINDER_BRANCH/status.html\"`" TINDER2="`echo \"Box name: $TINDERNAME\"`" fi cat <&2 if test "$error_kind" = "owner" ; then exit 1 fi fi } gitHeads () { ./g rev-parse --verify HEAD } sendTinderboxLog () { if test "$SEND_MAIL" -ne 1 -o -z "$TINDERNAME" ; then return 0 fi STARTTIME="$1" STATUS="$2" LOG="$3" if [ $GNUDATE -eq 0 ] ; then if [ X"`uname`" == X"OpenBSD" ]; then STARTTIME=`echo $STARTTIME | sed "s/-//g;s/ //g;s/://1;s/:/\./g"` STARTLINE="tinderbox: starttime: `date -j \"$STARTTIME\" '+%s'`" else STARTLINE="tinderbox: starttime: `date -juf '%Y-%m-%d %H:%M:%S' \"$STARTTIME\" '+%s'`" fi else STARTLINE="tinderbox: starttime: `date '+%s' -d \"$STARTTIME UTC\"`" fi XTINDER="X-Tinder: cookie" SUBJECT="tinderbox build start notification" GZLOG= MESSAGE=" tinderbox: administrator: $OWNER tinderbox: buildname: $TINDERNAME tinderbox: tree: $TINDER_BRANCH $STARTLINE tinderbox: timenow: `date '+%s'` tinderbox: errorparser: unix tinderbox: status: $STATUS tinderbox: END " if [ "$LOG" = "yes" ] ; then GZLOG="tinder.log.gz" ( echo "$MESSAGE" ; cat autogen.log clean.log build.log smoketest.log install.log 2>/dev/null ) | gzip -c > "$GZLOG" XTINDER="X-Tinder: gzookie" SUBJECT="tinderbox gzipped logfile" fi echo "$MESSAGE" | sendMailMsg "tinderbox@gimli.documentfoundation.org" "$SUBJECT" "$XTINDER" "" "$GZLOG" } ## code while getopts d:ehilm:ns:r:u:p:t:w: opt ; do case "$opt" in d) DISTRO_CONFIG="$OPTARG" ;; e) LOCK= ;; h) usage; exit ;; i) NICE="$NICE ionice -c3" ;; r) PUSH_NIGHTLIES=1 ; BANDWIDTH="$OPTARG" ;; l) HTML_OUTPUT=1 ;; m) SEND_MAIL=1 ; OWNER="$OPTARG" ;; n) NICE="$NICE nice" ;; s) SMTPHOST="$OPTARG" ;; u) SMTPUSER="$OPTARG" ;; p) SMTPPW="$OPTARG" ;; t) TINDERNAME="$OPTARG" ;; w) PAUSE_SECONDS="$OPTARG" ;; ?) usage; exit ;; esac done # sanity checks which git > /dev/null 2>&1 || { echo "You need git for this!" exit 1 } if test "$SEND_MAIL" -eq 1 ; then if test -z "$OWNER" ; then echo "Owner not set." exit 1 fi if test -z "$SMTPHOST" ; then echo "SMTP server not set." exit 1 fi if test "$OWNER" = `echo ${OWNER} | sed 's/\@/_/g'` ; then echo "The owner address '$OWNER' does not look like an email address." exit 1 fi fi # for build.pl test $HTML_OUTPUT -eq 1 && export BUILD_HTML_OUTPUT=true # where to report current_branch=`git branch | grep '^\*' | sed 's/^..//'` TINDER_BRANCH= case "$current_branch" in master) TINDER_BRANCH='MASTER' ;; libreoffice-3-4) TINDER_BRANCH=$current_branch ;; libreoffice-3-5) TINDER_BRANCH=$current_branch ;; libreoffice-3-6) TINDER_BRANCH=$current_branch ;; *) echo "Unknown, non-registered branch, please update tinbuild, and tinderbox.libreoffice.org." ; exit 1 ;; esac # main echots "Starting tinderbox for branch '$TINDER_BRANCH'." prev_success="" last_success="" day_last_upload=0 while true; do err_msg="" # FIXME we need a more exact way to determine a 'good' date; this is not accurate rough_checkout_date="`date -u '+%Y-%m-%d %H:%M:%S'`" # try to build build_status="build_failed" ( if [ "$LOCK" = "1" ] ; then flock -x 200 fi sendTinderboxLog "$rough_checkout_date" "building" retval=0 if ! $NICE ./autogen.sh ${DISTRO_CONFIG:+ --with-distro=${DISTRO_CONFIG}} >autogen.log 2>&1 ; then reportError committer "$rough_checkout_date" `printf "autogen.sh / configure failed - error is:\n\n"` "$(cat autogen.log)" retval=1 elif ! $NICE $MAKE clean >clean.log 2>&1 ; then reportError committer "$rough_checkout_date" `printf "cleaning up failed - error is:\n\n"` "$(tail -n100 clean.log)" retval=1 elif ! $NICE $MAKE >build.log 2>&1 ; then ( . ./*Env.Set.sh && cd instsetoo_native && build.pl ) >> build.log 2>&1 reportError committer "$rough_checkout_date" `printf "building failed - error is:\n\n"` "$(tail -n100 build.log)" retval=1 # elif ! $NICE make smoketest > smoketest.log 2>&1 ; then # reportError committer "$rough_checkout_date" `printf "smoketest failed - error is:\n\n"` "$(tail -n100 smoketest.log)" # retval=1 elif ( test "`uname | cut -c 1-6`" != "CYGWIN" ) && ! $NICE $MAKE dev-install >install.log 2>&1 ; then reportError committer "$rough_checkout_date" `printf "dev installation failed - error is:\n\n"` "$(tail -n100 install.log)" retval=1 fi exit $retval ) 200>/tmp/tinbuild-lockfile if [ "$?" = "0" ] ; then echots "Build done - checkout from $rough_checkout_date successful." gitHeads > prev-git-heads.txt prev_success=$last_success last_success=$rough_checkout_date build_status="success" # upload new daily build? curr_day=`date -u '+%j'` if [ $day_last_upload -lt $curr_day ]; then if test "$PUSH_NIGHTLIES" -eq 1; then $BIN_PATH/push_nightlies.sh -t "$rough_checkout_date" -n "$TINDERNAME" -l "$BANDWIDTH" if [ "$?" == "0" ] ; then day_last_upload=$curr_day fi fi fi fi # send tinderbox mail sendTinderboxLog "$rough_checkout_date" "$build_status" "yes" # save the old logs for I in autogen.log clean.log build.log smoketest.log install.log ; do mv $I prev-$I 2>/dev/null done echots "Waiting $PAUSE_SECONDS seconds." sleep $PAUSE_SECONDS # new commits? show_once=1 while true; do old_head=$(gitHeads) && err_msg="$( $timeout ./g pull -r 2>&1 )" || { reportError owner "$rough_checkout_date" `printf "git repo broken - error is:\n\n$err_msg"` } new_head=$(gitHeads) if test "$old_head" != "$new_head"; then echots "Repo updated, going to build." break fi if [ "$show_once" = "1" ] ; then echots "Waiting until there are changes in the repo..." show_once=0 fi sleep 60 done done