Changeset 90152a4 for Jenkinsfile
- Timestamp:
- Aug 27, 2018, 4:40:34 PM (7 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, cleanup-dtors, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum, stuck-waitfor-destruct
- Children:
- b7c89aa
- Parents:
- f9feab8 (diff), 305581d (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)links above to see all the changes relative to each parent. - File:
-
- 1 edited
-
Jenkinsfile (modified) (13 diffs)
Legend:
- Unmodified
- Added
- Removed
-
Jenkinsfile
rf9feab8 r90152a4 6 6 node ('master'){ 7 7 8 boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox" 8 // Globals 9 BuildDir = pwd tmp: true 10 SrcDir = pwd tmp: false 11 Settings = null 12 StageName = '' 13 14 // Local variables 9 15 def err = null 10 16 def log_needed = false 11 12 stage_name = ''13 14 compiler = null15 arch_name = ''16 architecture = ''17 18 do_alltests = false19 do_benchmark = false20 do_doc = false21 do_publish = false22 do_sendemail = true23 17 24 18 currentBuild.result = "SUCCESS" … … 30 24 notify_server(0) 31 25 32 prepare_build() 26 Settings = prepare_build() 27 28 clean() 33 29 34 30 checkout() … … 41 37 42 38 benchmark() 43 44 clean()45 39 46 40 build_doc() … … 58 52 err = caughtError 59 53 54 echo err.toString() 55 60 56 //An error has occured, the build log is relevent 61 57 log_needed = true 62 58 63 59 //Store the result of the build log 64 currentBuild.result = "${ stage_name} FAILURE".trim()60 currentBuild.result = "${StageName} FAILURE".trim() 65 61 } 66 62 67 63 finally { 68 64 //Send email with final results if this is not a full build 69 if( do_sendemail && !bIsSandbox ) { 70 echo 'Notifying users of result' 71 email(currentBuild.result, log_needed) 65 if( Settings && !Settings.Silent ) { 66 email(log_needed, Settings.IsSandbox) 72 67 } 73 68 … … 82 77 83 78 //=========================================================================================================== 84 // Helper classes/variables/routines85 //===========================================================================================================86 //Helper routine to collect information about the git history87 def collect_git_info() {88 89 checkout scm90 91 //create the temporary output directory in case it doesn't already exist92 def out_dir = pwd tmp: true93 sh "mkdir -p ${out_dir}"94 95 //parse git logs to find what changed96 gitRefName = env.BRANCH_NAME97 sh "git reflog > ${out_dir}/GIT_COMMIT"98 git_reflog = readFile("${out_dir}/GIT_COMMIT")99 gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]100 gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2]101 }102 103 def prepare_build() {104 properties ([ \105 [$class: 'ParametersDefinitionProperty', \106 parameterDefinitions: [ \107 [$class: 'ChoiceParameterDefinition', \108 description: 'Which compiler to use', \109 name: 'pCompiler', \110 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \111 defaultValue: 'gcc-6', \112 ], \113 [$class: 'ChoiceParameterDefinition', \114 description: 'The target architecture', \115 name: 'pArchitecture', \116 choices: 'x64\nx86', \117 defaultValue: 'x64', \118 ], \119 [$class: 'BooleanParameterDefinition', \120 description: 'If false, only the quick test suite is ran', \121 name: 'pRunAllTests', \122 defaultValue: false, \123 ], \124 [$class: 'BooleanParameterDefinition', \125 description: 'If true, jenkins also runs benchmarks', \126 name: 'pRunBenchmark', \127 defaultValue: true, \128 ], \129 [$class: 'BooleanParameterDefinition', \130 description: 'If true, jenkins also builds documentation', \131 name: 'pBuildDocumentation', \132 defaultValue: true, \133 ], \134 [$class: 'BooleanParameterDefinition', \135 description: 'If true, jenkins also publishes results', \136 name: 'pPublish', \137 defaultValue: false, \138 ], \139 [$class: 'BooleanParameterDefinition', \140 description: 'If true, jenkins will not send emails', \141 name: 'pSilent', \142 defaultValue: false, \143 ], \144 ],145 ]])146 147 compiler = compiler_from_params( pCompiler )148 arch_name = pArchitecture149 architecture = architecture_from_params( arch_name )150 151 do_alltests = (pRunAllTests == 'true')152 do_benchmark = (pRunBenchmark == 'true')153 do_doc = (pBuildDocumentation == 'true')154 do_publish = (pPublish == 'true')155 do_sendemail = ! (pSilent == 'true')156 157 echo """Compiler : ${compiler.cc_name} (${compiler.cpp_cc}/${compiler.cfa_cc})158 Architecture : ${arch_name}159 Arc Flags : ${architecture}160 Run All Tests : ${ pRunAllTests.toString() }161 Run Benchmark : ${ pRunBenchmark.toString() }162 Build Documentation : ${ pBuildDocumentation.toString() }163 Publish : ${ pPublish.toString() }164 Silent : ${ pSilent.toString() }165 """166 167 collect_git_info()168 }169 170 def build_stage(String name, Closure block ) {171 stage_name = name172 stage(name, block)173 }174 175 def notify_server(int wait) {176 sh """curl --silent --data "wait=${wait}" -X POST http://plg2:8082/jenkins/notify > /dev/null || true"""177 return178 }179 180 def make_doc() {181 def err = null182 try {183 sh 'make clean > /dev/null'184 sh 'make > /dev/null 2>&1'185 }186 catch (Exception caughtError) {187 err = caughtError //rethrow error later188 sh 'cat *.log'189 }190 finally {191 if (err) throw err // Must re-throw exception to propagate error192 }193 }194 195 //Description of a compiler (Must be serializable since pipelines are persistent)196 class CC_Desc implements Serializable {197 public String cc_name198 public String cpp_cc199 public String cfa_cc200 201 CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {202 this.cc_name = cc_name203 this.cpp_cc = cpp_cc204 this.cfa_cc = cfa_cc205 }206 }207 208 def compiler_from_params(cc) {209 switch( cc ) {210 case 'gcc-6':211 return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')212 break213 case 'gcc-5':214 return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')215 break216 case 'gcc-4.9':217 return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')218 break219 case 'clang':220 return new CC_Desc('clang', 'clang++', 'gcc-6')221 break222 default :223 error "Unhandled compiler : ${cc}"224 }225 }226 227 def architecture_from_params( arch ) {228 switch( arch ) {229 case 'x64':230 return '--host=x86_64'231 break232 case 'x86':233 return '--host=i386'234 break235 default :236 error "Unhandled architecture : ${arch}"237 }238 }239 240 //===========================================================================================================241 79 // Main compilation routines 242 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 243 90 //Compilation script is done here but environnement set-up and error handling is done in main loop 244 91 def checkout() { 245 92 build_stage('Checkout') { 246 93 //checkout the source code and clean the repo 247 checkout scm 248 249 //Clean all temporary files to make sure no artifacts of the previous build remain 250 sh 'git clean -fdqx' 251 252 //Reset the git repo so no local changes persist 253 sh 'git reset --hard' 94 final scmVars = checkout scm 95 Settings.GitNewRef = scmVars.GIT_COMMIT 96 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT 97 98 echo GitLogMessage() 254 99 } 255 100 } … … 257 102 def build() { 258 103 build_stage('Build') { 259 260 def install_dir = pwd tmp: true 261 262 //Configure the conpilation (Output is not relevant) 263 //Use the current directory as the installation target so nothing 264 //escapes the sandbox 265 //Also specify the compiler by hand 266 sh "./configure CXX=${compiler.cpp_cc} ${architecture} --with-backend-compiler=${compiler.cfa_cc} --prefix=${install_dir} --enable-silent-rules --quiet" 267 268 //Compile the project 269 sh 'make -j 8 --no-print-directory V=0 install' 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 } 270 121 } 271 122 } … … 274 125 build_stage('Test') { 275 126 276 //Run the tests from the tests directory 277 if ( do_alltests ) { 278 sh 'make -C src/tests all-tests debug=yes --no-print-directory' 279 sh 'make -C src/tests all-tests debug=no --no-print-directory' 280 } 281 else { 282 sh 'make -C src/tests --no-print-directory' 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 } 283 136 } 284 137 } … … 288 141 build_stage('Benchmark') { 289 142 290 if( !do_benchmark ) return 291 292 //Append bench results 293 sh 'make -C src/benchmark --no-print-directory jenkins githash=' + gitRefNewValue + ' arch=' + arch_name + ' | tee bench.json' 294 } 295 } 296 297 def clean() { 298 build_stage('Cleanup') { 299 300 //do a maintainer-clean to make sure we need to remake from scratch 301 sh 'make maintainer-clean > /dev/null' 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 } 302 149 } 303 150 } … … 306 153 build_stage('Documentation') { 307 154 308 if( ! do_doc) return155 if( !Settings.BuildDocumentation ) return 309 156 310 157 dir ('doc/user') { … … 321 168 build_stage('Publish') { 322 169 323 if( ! do_publish ) return170 if( !Settings.Publish ) return 324 171 325 172 //Then publish the results 326 sh 'curl - H "Content-Type: application/json" --silent --data @bench.json http://plg2:8082/jenkins/publish > /dev/null || true'173 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true' 327 174 } 328 175 } … … 331 178 //Routine responsible of sending the email notification once the build is completed 332 179 //=========================================================================================================== 333 //Standard build email notification 334 def email(String status, boolean log) { 335 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line 336 //Configurations for email format 337 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase() 338 339 def gitLog = 'Error retrieving git logs' 340 def gitDiff = 'Error retrieving git diff' 341 342 try { 343 344 sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG" 345 gitLog = readFile('GIT_LOG') 346 347 sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF" 348 gitDiff = readFile('GIT_DIFF') 349 } 350 catch (Exception error) {} 351 352 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}" 353 def email_body = """This is an automated email from the Jenkins build machine. It was 354 generated because of a git hooks/post-receive script following 355 a ref change was pushed to the repository containing 356 the project "UNNAMED PROJECT". 357 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 """ 358 190 The branch ${env.BRANCH_NAME} has been updated. 359 via ${gitRefOldValue} (commit) 360 from ${gitRefNewValue} (commit) 191 ${gitUpdate} 361 192 362 193 Check console output at ${env.BUILD_URL} to view the results. … … 364 195 - Status -------------------------------------------------------------- 365 196 366 BUILD# ${env.BUILD_NUMBER} - ${ status}197 BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result} 367 198 368 199 - Log ----------------------------------------------------------------- … … 372 203 ${gitDiff} 373 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() 374 219 375 220 def email_to = "cforall@lists.uwaterloo.ca" 376 221 377 //send email notification 378 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log 379 } 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 //=========================================================================================================== 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.