# !/bin/bash # # cvs-make.sh: # # This bash-script checks out the last SECONDO sources # and runs make to compile them. # # 03/02/28 M. Spiekermann: initial version # 04/01/27 M. Spiekermann: port from csh to bash # 05/01/27 M. Spiekermann: major revision, automatic test runs # July 2005 M. Spiekermann: cvsDir was not set correctly. # # July-August 2005, M. Spiekermann: The script will now only # compile SECONDO if there are changes in the CVS repository. # Moreover, the CVS history will be shown and the users who made # changes are extracted and their email addresses are retrieved. # # August 2005, M. Spiekermann: A new function makeSecondo was introduced. Now # SECONDO will be compiled twice: first with all algebra modules activated # and second with the algebras as defined in makefile.alsgebras.sample. # Moreover, if the script is successful, a new tag LAST_STABLE will be set # for the file's revision numbers. # # January 2006, M. Spiekermann: A backup dir for mails and test outputs # was implemented. # # October 2006, M. Spiekermann: Support for multiple SDKs and cvs modules added. # # March 2007, M. Spiekermann: Support for tar files and module options implemented. # Configuration Options export OSTYPE=linux # root for created local directories and files opt_rootDir="/tmp" # default gcc version str opt_gccVersion=".undefined" # cvs configuration cvsDir=/home/spieker/tmp-cvs opt_coTag="HEAD" opt_cvsServer="zeppelin" #opt_logRoot="/home/secondo/testrun-errors" opt_logRoot="/var/tmp/cvs-make" opt_waitMax=1800 opt_tarFile="none" opt_tarMail="Thomas.Behr@Fernuni-Hagen.de Fabio.Valdes@fernuni-hagen.de" opt_runTests="yes" opt_mkStable="yes" opt_earlyExit="no" # options for automatic mails LU_SENDMAIL="true" LU_SENDMAIL_FROM="fabio.valdes@fernuni-hagen.de" failedBuild_DefaultRecipients="Thomas.Behr@Fernuni-Hagen.de Fabio.Valdes@Fernuni-Hagen.de Christian.Duentgen@Fernuni-Hagen.de" newTarFile_MailRecipients="fabio.valdes@fernuni-Hagen.de" LU_LOG_SCREEN="true" # define mail bodys mailHeader=" This message was generated by $0! " mailFooter=" Please contact the involved people in order to find out who should fix the problem! A history of the old error log files is stored in $opt_logRoot on server $opt_cvsServer." mailBody1=" $mailHeader You will find the output of make in the attached file. $mailFooter " mailBody2=" $mailHeader You will find the log files of the failed tests in the attached file. $mailFooter" mailBody3=" $mailHeader You will find the log file of make realclean in the attached file. List of unremoved files: " mailBody4=" $mailHeader A new public version was created as tar file in " ############################################################# # IMPLEMENTATION PART # ############################################################# opt_sdkRootDir="$HOME" opt_sdkDir="secondo-sdk" opt_coModule="secondo" opt_coModuleOpt="std" # Include function definitions of libutil.sh. It must be in the same direcory # as this script file or in the search path. baseDir=$HOME/${0%/*} if [ -s $baseDir/libutil.sh ]; then if ! source $baseDir/libutil.sh; then exit 1; fi else if ! source libutil.sh; then exit 1; fi fi ## ## Function Definitions ## # checkOpt # function checkOpt() { local optName=$1 local val="$2" shift shift for opt in $*; do if [ "$val" == "$opt" ]; then return 0 fi done echo "Error: Option \"$optName = $val\" is invalid. I must be one of [$*]." exit 1 } # cvsChanges # # $1 file last date # $2 cvs module function cvsChanges() { # retrieve date of last run and store it in the first # line. This is more secure since time stamps of the file # may be modified by backup-script etc. local file=$1 local module=$2 lastDate="1-day-ago" if [ -e $file ]; then lastDate=$(tail -n1 $file) fi showValue lastDate # Note: The -p"prefix" option of the history commands selects files starting with the # given prefix. Since we have other repositories starting with "secondo" we need to filter # the output using grep. local cvsHistCmd="cvs history -xMAR -a -D\"$lastDate\" -p\"$module\" | sed -nre \"/$module[/ ]|No records/p\"" showValue cvsHistCmd cvsHistory=$(eval $cvsHistCmd) #showValue cvsHistory # store current date in file local currentDate=$(date +"%Y-%m-%d %H:%M") echo $lastDateFileHeader > $file echo $currentDate >> $file cvsChanges=" ----------------------------------------------------------- ${currentDate}: Changes since last run (${lastDate}) ----------------------------------------------------------- $cvsHistory" echo -e "$cvsChanges" >> $cvsHistFile # extract the 1st line of cvs history local cvsHist_1st=$(echo $cvsHistory | head -n1) #showValue cvsHist_1st if [ "$cvsHist_1st" == "No records selected." ]; then return 1 else return 0 fi } # mkMailStr # $1 body function mkMailStr { MAIL_STR="SECONDO_SDK=<"$SECONDO_SDK"> SECONDO_BUILD_DIR=<"$SECONDO_BUILD_DIR"> $cvsChanges $1" } # mkMailStr2 # $1 body # $2 variable text function mkMailStr2 { MAIL_STR="SECONDO_SDK=<"$SECONDO_SDK"> SECONDO_BUILD_DIR=<"$SECONDO_BUILD_DIR"> $1 $2" } # makeModule $1 $2 # # $1 file name for make's output # $2 subject for email function makeModule() { local msgFile=$1 local subject=$2 cd $cbuildDir CM-Scripts/catvar.sh > $msgFile 2>&1 if isCmdPresent "nice"; then local niceOpt="nice -n 19" fi checkCmd "$niceOpt make" >> $msgFile 2>&1 local rc=$? # proceed if last command was successful if [ $rc -ne 0 ]; then printf "%s\n" "Problems during build, sending a mail." mkMailStr "$mailBody1" sendMail "$subject $gccMailSubject" "$mailRecipients $failedBuild_DefaultRecipients" "$MAIL_STR" "$cvsHistMailBackupDir" "$msgFile" return $rc fi } function cleanModule { if [ "$opt_tarFile" != "none" ]; then return 0 fi printSep "Cleaning $opt_coModule" local logFile=$tmpDir/make-realclean.log checkCmd "make realclean" > $logFile 2>&1 mk_rc=$? printf "\n%s\n" "files unkown to CVS:" grepCmd='cvs -nQ update | grep "^? "' local leftFiles=$($grepCmd) if [ "$leftFiles" != "" ]; then mkMailStr "$mailBody3 $leftFiles" sendMail "make realclean has left some files! $gccMailSubject" "$mailRecipients" "$MAIL_STR" "$cvsHistMailBackupDir" "$logFile" else echo "The command $grepCmd returned no files!" fi return $mk_rc } ### ### MAIN PART ### tmpDir=/tmp/cvs-make-$USER mkdir -p $tmpDir declare -i numOfArgs=$# let numOfArgs++ while [ $# -eq 0 -o $numOfArgs -ne $OPTIND ]; do getopts "behnm:r:w:c:s:t:d:g:f:o:" optKey if [ "$optKey" == "?" ]; then optKey="h" fi case $optKey in h) showGPL printf "\n%s\n" "Usage of ${0##*/}:" printf "%s\n" "Global-Options:" printf "%s\n" " -h print this message and exit." printf "%s\n" " -n send no mails. Just print the message to stdout." printf "%s\n" " -e exit before compile (for testing only)." printf "%s\n" " -b build only, don't run tests." printf "%s\n" "SDK-Settings:" printf "%s\n" " -s => \"${opt_sdkRootDir}\" " printf "%s\n" " -d => \"${opt_sdkDir}\" " printf "%s\n" " -g => \"${opt_gccVersion}\" " printf "%s\n" " -t => \"${opt_coTag}\" " printf "%s\n" "Source-Definitions:" printf "%s\n" " -m => \"${opt_coModule}\" " printf "%s\n" " -o => \"${opt_coModuleOpt}\" " printf "%s\n" " -f => \"${opt_tarFile}\" " printf "%s\n" " -r => \"${opt_rootDir}\" " printf "%s\n" " -c => \"tmp_secondo_\"" printf "%s\n" "Test-Run Options:" printf "%s\n" " -w (timeout for tests!) => \"${opt_waitMax}\" " printf "%s\n" " -l => \"${opt_logRoot}\" " printf "%s\n" " -x => \"${opt_logRoot}\" " printf "%s\n\n" "The script checks out a local copy of into the directoy" printf "%s\n" "into / and runs make, various tests, etc." printf "%s\n\n" "In case of a failure an email will be sent to the CVS users." exit 0;; b) opt_runTests="no";; r) opt_rootDir=$OPTARG;; s) opt_sdkRootDir=$OPTARG;; d) opt_sdkDir=$OPTARG;; e) opt_earlyExit="true";; t) opt_coTag=$OPTARG;; g) opt_gccVersion=$OPTARG;; c) opt_coDir=$OPTARG;; o) opt_coModuleOpt=$OPTARG;; m) opt_coModule=$OPTARG;; f) opt_tarFile=$OPTARG;; w) opt_waitMax=$OPTARG;; n) LU_SENDMAIL="false";; esac done checkOpt "-o" "$opt_coModuleOpt" "all" "std" printSep "Variable values" opt_coDir=${opt_coModule}_${date_ymd}_${date_HMS}.gcc${opt_gccVersion} showValue opt_rootDir showValue opt_sdkRootDir showValue opt_sdkDir showValue opt_gccVersion showValue opt_coTag showValue opt_coDir showValue opt_coModule showValue opt_coModuleOpt showValue opt_tarFile showValue opt_tarMail if [ "$opt_tarFile" != "none" ]; then opt_mkStable="no" fi showValue opt_mkStable showValue opt_earlyExit showValue opt_runTests showValue opt_waitMax showValue LU_SENDMAIL showValue LU_SENDMAIL_FROM showValue cvsDir showValue tmpDir if [ "$opt_coModule" == "" ]; then echo -e "Error: a module needs to be specified!" exit 1; fi if [ "$opt_gccVersion" != "" ]; then gccMailSubject="(using gcc $opt_gccVersion)" fi # set up environment for secondo source ~/.bashrc # this is needed when started by cron # overwrite SECONDO_SDK and set up # the compiler and other tools needed by secondo if [ "$opt_sdkRootDir" == "" ]; then echo -e "Error: The SDK root needs to be specified!" exit 1; fi if [ "$opt_sdkDir" == "" ]; then echo -e "Error: The SDK dir needs to be specified!" exit 1; fi export SECONDO_SDK=$opt_sdkRootDir/$opt_sdkDir showValue SECONDO_SDK echo "OSTYPE <$OSTYPE>" if ! source $SECONDO_SDK/secondorc; then exit 1; fi # derive some other important directories cbuildDir=${opt_rootDir}/${opt_coDir} if [ "$opt_tarFile" != "none" ]; then cbuildDir=${opt_rootDir}/${opt_coDir}/$opt_coModule createDir $cbuildDir fi scriptDir=${cbuildDir}/CM-Scripts startDate=$(date) scriptFile="${PWD}/$0" showValue startDate showValue scriptFile showValue scriptDir showValue cbuildDir ## check if files in the module secondo were changed ## since the last run if [ "$opt_tarFile" == "none" ]; then opt_logRoot="$opt_logRoot/$opt_sdkDir/$opt_coModule" else opt_logRoot="$opt_logRoot/$opt_sdkDir/tarfile" fi lastDateFile="$opt_logRoot/lastrun" lastDateFileHeader="#This file was generated by $0! It stores the date of the last run." createDir $opt_logRoot cvsHistFile="$opt_logRoot/cvs-make-history" cvsHistMailBackupDir=$opt_logRoot/${date_ymd}_${date_HMS} showValue opt_cvsServer showValue opt_logRoot showValue lastDateFile showValue cvsHistFile showValue cvsHistMailBackupDir if [ "$opt_tarFile" == "none" ]; then cvsChanges "$lastDateFile" "$opt_coModule" cvsChanges_rc=$? showValue cvsChanges_rc if [ $cvsChanges_rc -ne 0 ]; then printf "\nNo changes since ${lastDate}! \n\n" exit 0; else echo -e "\n$cvsChanges" cvsUsers=$( echo -e "$cvsHistory" | awk '/./ { print $5 }' | sort | uniq | tr "\n" " " ) mailRecipients="" for userName in $cvsUsers; do mapStr "${cvsDir}/CVSROOT/users" "$userName" ":" mailRecipients="$LU_MAPSTR $mailRecipients" done printf "\n%s\n" "CVS user(s) : $cvsUsers" printf "%s\n" "Mail address(es): $mailRecipients" fi else mailRecipients=$opt_tarMail cvsChanges="Testing $opt_tarFile" fi ## report host status printSep "host status" printf "%s\n" "uptime" uptime printf "\n%s\n" "disk free" df -k printf "\n%s\n" "memory usage" free -m ## checkout work copy printSep "Checking out source files" setvar $cbuildDir printSep "Environment settings" catvar printSep "Alias definitions" alias if [ "$opt_tarFile" == "none" ]; then cd $opt_rootDir checkCmd "cvs -Q checkout -d $opt_coDir -P $opt_coModule" else cd $opt_rootDir/$opt_coDir checkCmd "tar -xzf $opt_tarFile" checkCmd "rm $opt_tarFile" fi if [ "$opt_earlyExit" == "yes" ]; then exit 0 fi ## ## Build the specified module ## declare -i errors=0 cd $cbuildDir printf "\n%s\n" "Changed to directory $PWD" printSep "Compile $opt_coModule with option $opt_coModuleOpt" moduleOptInit="false" if [ "$opt_coModuleOpt" == "all" ]; then echo "Setting Options for $opt_coModuleOpt ..." export SECONDO_ACTIVATE_ALL_ALGEBRAS="true" #export SECONDO_YACC="/usr/bin/bison" logFile=$tmpDir/make-all-algebras.log subject="Building $opt_coModule with all algebras failed!" opt_runTests="no" opt_mkStable="no" moduleOptInit="true" fi if [ "$opt_coModuleOpt" == "std" ]; then echo "Setting Options for $opt_coModuleOpt ..." unset SECONDO_ACTIVATE_ALL_ALGEBRAS logFile=$tmpDir/make-default-algebras.log subject="Building $opt_coModule failed!" moduleOptInit="true" fi if [ "$moduleOptInit" == "false" ]; then echo "Error: Options are not initialized." exit 1 fi showValue logFile showValue subject makeModule "$logFile" "$subject" mk_rc=$? if [ $mk_rc -ne 0 ]; then echo "*** Error during build! ***" cleanModule exit $mk_rc fi ## run tests if [[ ($mk_rc -eq 0) && ($opt_runTests == "yes") ]]; then printSep "Running automatic tests" cd $scriptDir checkCmd "run-tests.sh -tty $opt_logRoot $opt_waitMax" if [ $? -ne 0 ]; then printf "%s\n" "Problems during test, sending a mail" attachment2="$cbuildDir/failedTests.tar.gz" subject2="Automatic tests failed! $gccMailSubject" failedHist=" List of failed tests: --------------------- $(find $opt_logRoot -name "_failed_*" -exec cat {} \;) " mkMailStr "$mailBody2 $failedHist" sendMail "$subject2" "$mailRecipients" "$MAIL_STR" "$cvsHistMailBackupDir" "$attachment2" let errors++ fi cleanModule if [[ ($[errors] == 0) && ("$opt_runTests" == "yes") && ("$opt_mkStable" == "yes") ]]; then # Move label for stable version cd $cbuildDir tagSym="LAST_STABLE" tagMsg="Moving CVS tag $tagSym" printSep $tagMsg echo -e "Automatic regression test was successful. ${tagMsg}!" >> $cvsHistFile cvs -Q tag -d $tagSym cvs -Q tag $tagSym make tag=$tagSym src-archives #Backup to /www switched of since the server has problems #cp /tmp/make-$USER/secondo-$tagSym* $HOME/Backup # send a notification archive="/tmp/make-$USER/secondo-$tagSym.tar.gz" mkMailStr2 "$mailBody4" $archive sendMail "New public version source archives created" "$newTarFile_MailRecipients" "$MAIL_STR" # clean up rm -rf $cbuildDir rm -rf $tmpDir # rm -rf /tmp/make-$USER fi echo "*** The regression test finished with $errors errors ***" exit $errors fi