Changes in / [72a5a75:b6830d74]


Ignore:
Files:
1 deleted
1 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    r72a5a75 rb6830d74  
    66node ('master'){
    77
    8         // Globals
    9         BuildDir  = pwd tmp: true
    10         SrcDir    = pwd tmp: false
    11         Settings  = null
    12         StageName = ''
    13 
    14         // Local variables
     8        boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox"
    159        def err = null
    1610        def log_needed = false
     11
     12        stage_name              = ''
     13
     14        compiler                = null
     15        arch_name               = ''
     16        architecture    = ''
     17
     18        do_alltests             = false
     19        do_benchmark    = false
     20        do_doc          = false
     21        do_publish              = false
     22        do_sendemail    = true
     23
     24        builddir = pwd tmp: true
     25        srcdir   = pwd tmp: false
    1726
    1827        currentBuild.result = "SUCCESS"
     
    2433                        notify_server(0)
    2534
    26                         Settings = prepare_build()
     35                        prepare_build()
    2736
    2837                        clean()
     
    5261                err = caughtError
    5362
    54                 echo err.toString()
    55 
    5663                //An error has occured, the build log is relevent
    5764                log_needed = true
    5865
    5966                //Store the result of the build log
    60                 currentBuild.result = "${StageName} FAILURE".trim()
     67                currentBuild.result = "${stage_name} FAILURE".trim()
    6168        }
    6269
    6370        finally {
    6471                //Send email with final results if this is not a full build
    65                 if( Settings && !Settings.Silent ) {
    66                         email(log_needed, Settings.IsSandbox)
     72                if( do_sendemail ) {
     73                        echo 'Notifying users of result'
     74                        email(currentBuild.result, log_needed, bIsSandbox)
    6775                }
    6876
     
    7785
    7886//===========================================================================================================
    79 // Main compilation routines
    80 //===========================================================================================================
    81 def clean() {
    82         build_stage('Cleanup') {
    83                 // clean the build by wipping the build directory
    84                 dir(BuildDir) {
    85                         deleteDir()
    86                 }
    87         }
    88 }
    89 
    90 //Compilation script is done here but environnement set-up and error handling is done in main loop
    91 def checkout() {
    92         build_stage('Checkout') {
    93                 //checkout the source code and clean the repo
    94                 final scmVars = checkout scm
    95                 Settings.GitNewRef = scmVars.GIT_COMMIT
    96                 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
    97 
    98                 echo GitLogMessage()
    99         }
    100 }
    101 
    102 def build() {
    103         build_stage('Build') {
    104                 // Build outside of the src tree to ease cleaning
    105                 dir (BuildDir) {
    106                         //Configure the conpilation (Output is not relevant)
    107                         //Use the current directory as the installation target so nothing escapes the sandbox
    108                         //Also specify the compiler by hand
    109                         targets=""
    110                         if( Settings.RunAllTests ) {
    111                                 targets="--with-target-hosts='host:debug,host:nodebug'"
    112                         } else {
    113                                 targets="--with-target-hosts='host:debug'"
    114                         }
    115 
    116                         sh "${SrcDir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"
    117 
    118                         //Compile the project
    119                         sh 'make -j 8 --no-print-directory'
    120                 }
    121         }
    122 }
    123 
    124 def test() {
    125         build_stage('Test') {
    126 
    127                 dir (BuildDir) {
    128                         //Run the tests from the tests directory
    129                         if ( Settings.RunAllTests ) {
    130                                 sh 'make --no-print-directory -C tests all-tests debug=yes'
    131                                 sh 'make --no-print-directory -C tests all-tests debug=no '
    132                         }
    133                         else {
    134                                 sh 'make --no-print-directory -C tests'
    135                         }
    136                 }
    137         }
    138 }
    139 
    140 def benchmark() {
    141         build_stage('Benchmark') {
    142 
    143                 if( !Settings.RunBenchmark ) return
    144 
    145                 dir (BuildDir) {
    146                         //Append bench results
    147                         sh "make --no-print-directory -C benchmark jenkins githash=${Settings.GitNewRef} arch=${Settings.Architecture} | tee ${SrcDir}/bench.json"
    148                 }
    149         }
    150 }
    151 
    152 def build_doc() {
    153         build_stage('Documentation') {
    154 
    155                 if( !Settings.BuildDocumentation ) return
    156 
    157                 dir ('doc/user') {
    158                         make_doc()
    159                 }
    160 
    161                 dir ('doc/refrat') {
    162                         make_doc()
    163                 }
    164         }
    165 }
    166 
    167 def publish() {
    168         build_stage('Publish') {
    169 
    170                 if( !Settings.Publish ) return
    171 
    172                 //Then publish the results
    173                 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
    174         }
    175 }
    176 
    177 //===========================================================================================================
    178 //Routine responsible of sending the email notification once the build is completed
    179 //===========================================================================================================
    180 def GitLogMessage() {
    181         if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
    182 
    183         sh "${SrcDir}/tools/PrettyGitLogs.sh ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
    184 
    185         def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
    186         def gitLog    = readFile("${BuildDir}/GIT_LOG")
    187         def gitDiff   = readFile("${BuildDir}/GIT_DIFF")
    188 
    189         return """
    190 The branch ${env.BRANCH_NAME} has been updated.
    191 ${gitUpdate}
    192 
    193 Check console output at ${env.BUILD_URL} to view the results.
    194 
    195 - Status --------------------------------------------------------------
    196 
    197 BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}
    198 
    199 - Log -----------------------------------------------------------------
    200 ${gitLog}
    201 -----------------------------------------------------------------------
    202 Summary of changes:
    203 ${gitDiff}
    204 """
    205 }
    206 
    207 //Standard build email notification
    208 def email(boolean log, boolean bIsSandbox) {
    209         //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
    210         //Configurations for email format
    211         echo 'Notifying users of result'
    212 
    213         def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
    214         def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
    215         def email_body = """This is an automated email from the Jenkins build machine. It was
    216 generated because of a git hooks/post-receive script following
    217 a ref change which was pushed to the Cforall repository.
    218 """ + GitLogMessage()
    219 
    220         def email_to = "cforall@lists.uwaterloo.ca"
    221 
    222         if( Settings && !Settings.IsSandbox ) {
    223                 //send email notification
    224                 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
    225         } else {
    226                 echo "Would send email to: ${email_to}"
    227                 echo "With title: ${email_subject}"
    228                 echo "Content: \n${email_body}"
    229         }
    230 }
    231 
    232 //===========================================================================================================
    23387// Helper classes/variables/routines
    23488//===========================================================================================================
    235 //Description of a compiler (Must be serializable since pipelines are persistent)
    236 class CC_Desc implements Serializable {
    237         public String cc_name
    238         public String cpp_cc
    239         public String cfa_cc
    240 
    241         CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
    242                 this.cc_name = cc_name
    243                 this.cpp_cc = cpp_cc
    244                 this.cfa_cc = cfa_cc
    245         }
    246 }
    247 
    248 //Description of an architecture (Must be serializable since pipelines are persistent)
    249 class Arch_Desc implements Serializable {
    250         public String name
    251         public String flags
    252 
    253         Arch_Desc(String name, String flags) {
    254                 this.name  = name
    255                 this.flags = flags
    256         }
    257 }
    258 
    259 class BuildSettings implements Serializable {
    260         public final CC_Desc Compiler
    261         public final Arch_Desc Architecture
    262         public final Boolean RunAllTests
    263         public final Boolean RunBenchmark
    264         public final Boolean BuildDocumentation
    265         public final Boolean Publish
    266         public final Boolean Silent
    267         public final Boolean IsSandbox
    268         public final String DescLong
    269         public final String DescShort
    270 
    271         public String GitNewRef
    272         public String GitOldRef
    273 
    274         BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
    275                 switch( param.Compiler ) {
    276                         case 'gcc-6':
    277                                 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
    278                         break
    279                         case 'gcc-5':
    280                                 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
    281                         break
    282                         case 'gcc-4.9':
    283                                 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
    284                         break
    285                         case 'clang':
    286                                 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
    287                         break
    288                         default :
    289                                 error "Unhandled compiler : ${cc}"
    290                 }
    291 
    292                 switch( param.Architecture ) {
    293                         case 'x64':
    294                                 this.Architecture = new Arch_Desc('x64', '--host=x86_64')
    295                         break
    296                         case 'x86':
    297                                 this.Architecture = new Arch_Desc('x86', '--host=i386')
    298                         break
    299                         default :
    300                                 error "Unhandled architecture : ${arch}"
    301                 }
    302 
    303                 this.RunAllTests        = param.RunAllTests
    304                 this.RunBenchmark       = param.RunBenchmark
    305                 this.BuildDocumentation = param.BuildDocumentation
    306                 this.Publish            = param.Publish
    307                 this.Silent             = param.Silent
    308                 this.IsSandbox          = (branch == "jenkins-sandbox")
    309 
    310                 def full = param.RunAllTests ? " (Full)" : ""
    311                 this.DescShort = "${ this.Compiler.cc_name }:${ this.Architecture.name }${full}"
    312 
    313                 this.DescLong = """Compiler              : ${ this.Compiler.cc_name } (${ this.Compiler.cpp_cc }/${ this.Compiler.cfa_cc })
    314 Architecture            : ${ this.Architecture.name }
    315 Arc Flags               : ${ this.Architecture.flags }
    316 Run All Tests           : ${ this.RunAllTests.toString() }
    317 Run Benchmark           : ${ this.RunBenchmark.toString() }
    318 Build Documentation     : ${ this.BuildDocumentation.toString() }
    319 Publish                 : ${ this.Publish.toString() }
    320 Silent                  : ${ this.Silent.toString() }
    321 """
    322 
    323                 this.GitNewRef = ''
    324                 this.GitOldRef = ''
    325         }
     89//Helper routine to collect information about the git history
     90def collect_git_info() {
     91
     92        checkout scm
     93
     94        //create the temporary output directory in case it doesn't already exist
     95        def out_dir = pwd tmp: true
     96        sh "mkdir -p ${out_dir}"
     97
     98        //parse git logs to find what changed
     99        gitRefName = env.BRANCH_NAME
     100        sh "git reflog > ${out_dir}/GIT_COMMIT"
     101        git_reflog = readFile("${out_dir}/GIT_COMMIT")
     102        gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]
     103        gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2]
    326104}
    327105
    328106def prepare_build() {
    329         // prepare the properties
    330107        properties ([                                                                                                   \
    331108                [$class: 'ParametersDefinitionProperty',                                                                \
     
    371148                ]])
    372149
    373         final settings = new BuildSettings(params, env.BRANCH_NAME)
    374 
    375         currentBuild.description = settings.DescShort
    376         echo                       settings.DescLong
    377 
    378         return settings
     150        compiler                = compiler_from_params( params.Compiler )
     151        arch_name               = params.Architecture
     152        architecture    = architecture_from_params( arch_name )
     153
     154        do_alltests             = (params.RunAllTests == 'true')
     155        do_benchmark    = (params.RunBenchmark == 'true')
     156        do_doc          = (params.BuildDocumentation == 'true')
     157        do_publish              = (params.Publish == 'true')
     158        do_sendemail    = ! (params.Silent == 'true')
     159
     160        collect_git_info()
     161
     162        def full = do_alltests ? " (Full)" : ""
     163        currentBuild.description = "${compiler.cc_name}:${arch_name}${full}"
     164
     165        echo """Compiler                 : ${ compiler.cc_name } (${ compiler.cpp_cc }/${ compiler.cfa_cc })
     166Architecture            : ${ arch_name }
     167Arc Flags               : ${ architecture }
     168Run All Tests           : ${ params.RunAllTests.toString() }
     169Run Benchmark           : ${ params.RunBenchmark.toString() }
     170Build Documentation     : ${ params.BuildDocumentation.toString() }
     171Publish                 : ${ params.Publish.toString() }
     172Silent                  : ${ params.Silent.toString() }
     173"""
    379174}
    380175
    381176def build_stage(String name, Closure block ) {
    382         StageName = name
    383         echo " -------- ${StageName} -------- "
     177        stage_name = name
    384178        stage(name, block)
    385179}
     
    404198        }
    405199}
     200
     201//Description of a compiler (Must be serializable since pipelines are persistent)
     202class CC_Desc implements Serializable {
     203        public String cc_name
     204        public String cpp_cc
     205        public String cfa_cc
     206
     207        CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
     208                this.cc_name = cc_name
     209                this.cpp_cc = cpp_cc
     210                this.cfa_cc = cfa_cc
     211        }
     212}
     213
     214def compiler_from_params(cc) {
     215        switch( cc ) {
     216                case 'gcc-6':
     217                        return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
     218                break
     219                case 'gcc-5':
     220                        return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
     221                break
     222                case 'gcc-4.9':
     223                        return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
     224                break
     225                case 'clang':
     226                        return new CC_Desc('clang', 'clang++', 'gcc-6')
     227                break
     228                default :
     229                        error "Unhandled compiler : ${cc}"
     230        }
     231}
     232
     233def architecture_from_params( arch ) {
     234        switch( arch ) {
     235                case 'x64':
     236                        return '--host=x86_64'
     237                break
     238                case 'x86':
     239                        return '--host=i386'
     240                break
     241                default :
     242                        error "Unhandled architecture : ${arch}"
     243        }
     244}
     245
     246//===========================================================================================================
     247// Main compilation routines
     248//===========================================================================================================
     249def clean() {
     250        build_stage('Cleanup') {
     251                // clean the build by wipping the build directory
     252                dir(builddir) {
     253                        deleteDir()
     254                }
     255
     256                //Clean all temporary files to make sure no artifacts of the previous build remain
     257                sh 'git clean -fdqx'
     258
     259                //Reset the git repo so no local changes persist
     260                sh 'git reset --hard'
     261        }
     262}
     263
     264//Compilation script is done here but environnement set-up and error handling is done in main loop
     265def checkout() {
     266        build_stage('Checkout') {
     267                //checkout the source code and clean the repo
     268                checkout scm
     269        }
     270}
     271
     272def build() {
     273        build_stage('Build') {
     274                // Build outside of the src tree to ease cleaning
     275                dir (builddir) {
     276                        //Configure the conpilation (Output is not relevant)
     277                        //Use the current directory as the installation target so nothing escapes the sandbox
     278                        //Also specify the compiler by hand
     279                        targets=""
     280                        if(do_alltests) {
     281                                targets="--with-target-hosts='host:debug,host:nodebug'"
     282                        } else {
     283                                targets="--with-target-hosts='host:debug'"
     284                        }
     285
     286                        sh "${srcdir}/configure CXX=${compiler.cpp_cc} ${architecture} ${targets} --with-backend-compiler=${compiler.cfa_cc} --quiet"
     287
     288                        //Compile the project
     289                        sh 'make -j 8 --no-print-directory'
     290                }
     291        }
     292}
     293
     294def test() {
     295        build_stage('Test') {
     296
     297                dir (builddir) {
     298                        //Run the tests from the tests directory
     299                        if ( do_alltests ) {
     300                                sh 'make --no-print-directory -C tests all-tests debug=yes'
     301                                sh 'make --no-print-directory -C tests all-tests debug=no '
     302                        }
     303                        else {
     304                                sh 'make --no-print-directory -C tests'
     305                        }
     306                }
     307        }
     308}
     309
     310def benchmark() {
     311        build_stage('Benchmark') {
     312
     313                if( !do_benchmark ) return
     314
     315                dir (builddir) {
     316                        //Append bench results
     317                        sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${arch_name} | tee ${srcdir}/bench.json"
     318                }
     319        }
     320}
     321
     322def build_doc() {
     323        build_stage('Documentation') {
     324
     325                if( !do_doc ) return
     326
     327                dir ('doc/user') {
     328                        make_doc()
     329                }
     330
     331                dir ('doc/refrat') {
     332                        make_doc()
     333                }
     334        }
     335}
     336
     337def publish() {
     338        build_stage('Publish') {
     339
     340                if( !do_publish ) return
     341
     342                //Then publish the results
     343                sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
     344        }
     345}
     346
     347//===========================================================================================================
     348//Routine responsible of sending the email notification once the build is completed
     349//===========================================================================================================
     350def gitBranchUpdate(String gitRefOldValue, String gitRefNewValue) {
     351        def update = ""
     352        sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG";
     353        readFile('GIT_LOG').eachLine { rev ->
     354                sh "git cat-file -t ${rev} > GIT_TYPE"
     355                def type = readFile('GIT_TYPE')
     356
     357                update += "       via  ${rev} (${type})\n"
     358        }
     359        def rev = gitRefOldValue
     360        sh "git cat-file -t ${rev} > GIT_TYPE"
     361        def type = readFile('GIT_TYPE')
     362
     363        update += "      from  ${rev} (${type})\n"
     364        return update
     365
     366def output=readFile('result').trim()
     367echo "output=$output";
     368}
     369
     370//Standard build email notification
     371def email(String status, boolean log, boolean bIsSandbox) {
     372        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
     373        //Configurations for email format
     374        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
     375
     376        def gitLog = 'Error retrieving git logs'
     377        def gitDiff = 'Error retrieving git diff'
     378        def gitUpdate = 'Error retrieving update'
     379
     380        try {
     381                gitUpdate = gitBranchUpdate(gitRefOldValue, gitRefNewValue)
     382
     383                sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG"
     384                gitLog = readFile('GIT_LOG')
     385
     386                sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF"
     387                gitDiff = readFile('GIT_DIFF')
     388        }
     389        catch (Exception error) {
     390                echo error.toString()
     391                echo error.getMessage()
     392        }
     393
     394        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
     395        def email_body = """This is an automated email from the Jenkins build machine. It was
     396generated because of a git hooks/post-receive script following
     397a ref change was pushed to the repository containing
     398the project "UNNAMED PROJECT".
     399
     400The branch ${env.BRANCH_NAME} has been updated.
     401${gitUpdate}
     402
     403Check console output at ${env.BUILD_URL} to view the results.
     404
     405- Status --------------------------------------------------------------
     406
     407BUILD# ${env.BUILD_NUMBER} - ${status}
     408
     409- Log -----------------------------------------------------------------
     410${gitLog}
     411-----------------------------------------------------------------------
     412Summary of changes:
     413${gitDiff}
     414"""
     415
     416        def email_to = "cforall@lists.uwaterloo.ca"
     417
     418        if( !bIsSandbox ) {
     419                //send email notification
     420                emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
     421        } else {
     422                echo "Would send email to: ${email_to}"
     423                echo "With title: ${email_subject}"
     424                echo "Content: \n${email_body}"
     425        }
     426}
Note: See TracChangeset for help on using the changeset viewer.