Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • Jenkinsfile

    reda8175 r27474a7  
    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//===========================================================================================================
     87// Helper classes/variables/routines
     88//===========================================================================================================
     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]
     104}
     105
     106def prepare_build() {
     107        properties ([                                                                                                   \
     108                [$class: 'ParametersDefinitionProperty',                                                                \
     109                        parameterDefinitions: [                                                                         \
     110                                [$class: 'ChoiceParameterDefinition',                                           \
     111                                        description: 'Which compiler to use',                                   \
     112                                        name: 'pCompiler',                                                              \
     113                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
     114                                        defaultValue: 'gcc-6',                                                          \
     115                                ],                                                                                              \
     116                                [$class: 'ChoiceParameterDefinition',                                           \
     117                                        description: 'The target architecture',                                 \
     118                                        name: 'pArchitecture',                                                          \
     119                                        choices: 'x64\nx86',                                                            \
     120                                        defaultValue: 'x64',                                                            \
     121                                ],                                                                                              \
     122                                [$class: 'BooleanParameterDefinition',                                                  \
     123                                        description: 'If false, only the quick test suite is ran',              \
     124                                        name: 'pRunAllTests',                                                           \
     125                                        defaultValue: false,                                                            \
     126                                ],                                                                                              \
     127                                [$class: 'BooleanParameterDefinition',                                                  \
     128                                        description: 'If true, jenkins also runs benchmarks',           \
     129                                        name: 'pRunBenchmark',                                                          \
     130                                        defaultValue: true,                                                             \
     131                                ],                                                                                              \
     132                                [$class: 'BooleanParameterDefinition',                                                  \
     133                                        description: 'If true, jenkins also builds documentation',              \
     134                                        name: 'pBuildDocumentation',                                                    \
     135                                        defaultValue: true,                                                             \
     136                                ],                                                                                              \
     137                                [$class: 'BooleanParameterDefinition',                                                  \
     138                                        description: 'If true, jenkins also publishes results',                 \
     139                                        name: 'pPublish',                                                               \
     140                                        defaultValue: false,                                                            \
     141                                ],                                                                                              \
     142                                [$class: 'BooleanParameterDefinition',                                                  \
     143                                        description: 'If true, jenkins will not send emails',           \
     144                                        name: 'pSilent',                                                                        \
     145                                        defaultValue: false,                                                            \
     146                                ],                                                                                              \
     147                        ],
     148                ]])
     149
     150        compiler                = compiler_from_params( pCompiler )
     151        arch_name               = pArchitecture
     152        architecture    = architecture_from_params( arch_name )
     153
     154        do_alltests             = (pRunAllTests == 'true')
     155        do_benchmark    = (pRunBenchmark == 'true')
     156        do_doc          = (pBuildDocumentation == 'true')
     157        do_publish              = (pPublish == 'true')
     158        do_sendemail    = ! (pSilent == '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           : ${ pRunAllTests.toString() }
     169Run Benchmark           : ${ pRunBenchmark.toString() }
     170Build Documentation     : ${ pBuildDocumentation.toString() }
     171Publish                 : ${ pPublish.toString() }
     172Silent                  : ${ pSilent.toString() }
     173"""
     174}
     175
     176def build_stage(String name, Closure block ) {
     177        stage_name = name
     178        stage(name, block)
     179}
     180
     181def notify_server(int wait) {
     182        sh """curl --silent --show-error --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
     183        return
     184}
     185
     186def make_doc() {
     187        def err = null
     188        try {
     189                sh 'make clean > /dev/null'
     190                sh 'make > /dev/null 2>&1'
     191        }
     192        catch (Exception caughtError) {
     193                err = caughtError //rethrow error later
     194                sh 'cat *.log'
     195        }
     196        finally {
     197                if (err) throw err // Must re-throw exception to propagate error
     198        }
     199}
     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//===========================================================================================================
    79247// Main compilation routines
    80248//===========================================================================================================
     
    82250        build_stage('Cleanup') {
    83251                // clean the build by wipping the build directory
    84                 dir(BuildDir) {
     252                dir(builddir) {
    85253                        deleteDir()
    86254                }
     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'
    87261        }
    88262}
     
    92266        build_stage('Checkout') {
    93267                //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()
     268                checkout scm
    99269        }
    100270}
     
    103273        build_stage('Build') {
    104274                // Build outside of the src tree to ease cleaning
    105                 dir (BuildDir) {
     275                dir (builddir) {
    106276                        //Configure the conpilation (Output is not relevant)
    107277                        //Use the current directory as the installation target so nothing escapes the sandbox
    108278                        //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"
     279                        sh "${srcdir}/configure CXX=${compiler.cpp_cc} ${architecture} --with-backend-compiler=${compiler.cfa_cc} --enable-silent-rules --quiet"
    117280
    118281                        //Compile the project
     
    125288        build_stage('Test') {
    126289
    127                 dir (BuildDir) {
     290                dir (builddir) {
    128291                        //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 '
     292                        if ( do_alltests ) {
     293                                sh 'make --no-print-directory -C src/tests all-tests debug=yes'
     294                                sh 'make --no-print-directory -C src/tests all-tests debug=no '
    132295                        }
    133296                        else {
    134                                 sh 'make --no-print-directory -C tests'
     297                                sh 'make --no-print-directory -C src/tests'
    135298                        }
    136299                }
     
    141304        build_stage('Benchmark') {
    142305
    143                 if( !Settings.RunBenchmark ) return
    144 
    145                 dir (BuildDir) {
     306                if( !do_benchmark ) return
     307
     308                dir (builddir) {
    146309                        //Append bench results
    147                         sh "make --no-print-directory -C benchmark jenkins githash=${Settings.GitNewRef} arch=${Settings.Architecture} | tee ${SrcDir}/bench.json"
     310                        sh "make --no-print-directory -C src/benchmark jenkins githash=${gitRefNewValue} arch=${arch_name} | tee ${srcdir}/bench.json"
    148311                }
    149312        }
     
    153316        build_stage('Documentation') {
    154317
    155                 if( !Settings.BuildDocumentation ) return
     318                if( !do_doc ) return
    156319
    157320                dir ('doc/user') {
     
    168331        build_stage('Publish') {
    169332
    170                 if( !Settings.Publish ) return
     333                if( !do_publish ) return
    171334
    172335                //Then publish the results
     
    178341//Routine responsible of sending the email notification once the build is completed
    179342//===========================================================================================================
    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 """
     343//Standard build email notification
     344def email(String status, boolean log, boolean bIsSandbox) {
     345        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
     346        //Configurations for email format
     347        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
     348
     349        def gitLog = 'Error retrieving git logs'
     350        def gitDiff = 'Error retrieving git diff'
     351
     352        try {
     353
     354                sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG"
     355                gitLog = readFile('GIT_LOG')
     356
     357                sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF"
     358                gitDiff = readFile('GIT_DIFF')
     359        }
     360        catch (Exception error) {}
     361
     362        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
     363        def email_body = """This is an automated email from the Jenkins build machine. It was
     364generated because of a git hooks/post-receive script following
     365a ref change was pushed to the repository containing
     366the project "UNNAMED PROJECT".
     367
    190368The branch ${env.BRANCH_NAME} has been updated.
    191 ${gitUpdate}
     369   via  ${gitRefOldValue} (commit)
     370  from  ${gitRefNewValue} (commit)
    192371
    193372Check console output at ${env.BUILD_URL} to view the results.
     
    195374- Status --------------------------------------------------------------
    196375
    197 BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}
     376BUILD# ${env.BUILD_NUMBER} - ${status}
    198377
    199378- Log -----------------------------------------------------------------
     
    203382${gitDiff}
    204383"""
    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()
    219384
    220385        def email_to = "cforall@lists.uwaterloo.ca"
    221386
    222         if( Settings && !Settings.IsSandbox ) {
     387        if( !bIsSandbox ) {
    223388                //send email notification
    224389                emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
     
    229394        }
    230395}
    231 
    232 //===========================================================================================================
    233 // Helper classes/variables/routines
    234 //===========================================================================================================
    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         }
    326 }
    327 
    328 def prepare_build() {
    329         // prepare the properties
    330         properties ([                                                                                                   \
    331                 [$class: 'ParametersDefinitionProperty',                                                                \
    332                         parameterDefinitions: [                                                                         \
    333                                 [$class: 'ChoiceParameterDefinition',                                           \
    334                                         description: 'Which compiler to use',                                   \
    335                                         name: 'Compiler',                                                                       \
    336                                         choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
    337                                         defaultValue: 'gcc-6',                                                          \
    338                                 ],                                                                                              \
    339                                 [$class: 'ChoiceParameterDefinition',                                           \
    340                                         description: 'The target architecture',                                 \
    341                                         name: 'Architecture',                                                           \
    342                                         choices: 'x64\nx86',                                                            \
    343                                         defaultValue: 'x64',                                                            \
    344                                 ],                                                                                              \
    345                                 [$class: 'BooleanParameterDefinition',                                                  \
    346                                         description: 'If false, only the quick test suite is ran',              \
    347                                         name: 'RunAllTests',                                                            \
    348                                         defaultValue: false,                                                            \
    349                                 ],                                                                                              \
    350                                 [$class: 'BooleanParameterDefinition',                                                  \
    351                                         description: 'If true, jenkins also runs benchmarks',           \
    352                                         name: 'RunBenchmark',                                                           \
    353                                         defaultValue: false,                                                            \
    354                                 ],                                                                                              \
    355                                 [$class: 'BooleanParameterDefinition',                                                  \
    356                                         description: 'If true, jenkins also builds documentation',              \
    357                                         name: 'BuildDocumentation',                                                     \
    358                                         defaultValue: true,                                                             \
    359                                 ],                                                                                              \
    360                                 [$class: 'BooleanParameterDefinition',                                                  \
    361                                         description: 'If true, jenkins also publishes results',                 \
    362                                         name: 'Publish',                                                                        \
    363                                         defaultValue: false,                                                            \
    364                                 ],                                                                                              \
    365                                 [$class: 'BooleanParameterDefinition',                                                  \
    366                                         description: 'If true, jenkins will not send emails',           \
    367                                         name: 'Silent',                                                                         \
    368                                         defaultValue: false,                                                            \
    369                                 ],                                                                                              \
    370                         ],
    371                 ]])
    372 
    373         final settings = new BuildSettings(params, env.BRANCH_NAME)
    374 
    375         currentBuild.description = settings.DescShort
    376         echo                       settings.DescLong
    377 
    378         return settings
    379 }
    380 
    381 def build_stage(String name, Closure block ) {
    382         StageName = name
    383         echo " -------- ${StageName} -------- "
    384         stage(name, block)
    385 }
    386 
    387 def notify_server(int wait) {
    388         sh """curl --silent --show-error --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
    389         return
    390 }
    391 
    392 def make_doc() {
    393         def err = null
    394         try {
    395                 sh 'make clean > /dev/null'
    396                 sh 'make > /dev/null 2>&1'
    397         }
    398         catch (Exception caughtError) {
    399                 err = caughtError //rethrow error later
    400                 sh 'cat *.log'
    401         }
    402         finally {
    403                 if (err) throw err // Must re-throw exception to propagate error
    404         }
    405 }
Note: See TracChangeset for help on using the changeset viewer.