source: Jenkinsfile@ 249091f

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 249091f was 249091f, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Some cleanup in Jenkinsfile

  • Property mode set to 100644
File size: 15.6 KB
RevLine 
[a63ad80]1#!groovy
2
[7a230fd]3import groovy.transform.Field
4
[8ecb590]5// For skipping stages
6import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
7
[29f4fe62]8//===========================================================================================================
[9beae23]9// Main loop of the compilation
[29f4fe62]10//===========================================================================================================
[56a9ce6]11
[5307c33]12node('master') {
[5b8413b4]13 // Globals
[4c55047]14 BuildDir = pwd tmp: true
15 SrcDir = pwd tmp: false
[5b8413b4]16 Settings = null
17 StageName = ''
18
19 // Local variables
[9beae23]20 def err = null
21 def log_needed = false
[0ef06b6]22
23 currentBuild.result = "SUCCESS"
24
[9beae23]25 try {
[95fdb0a]26 //Wrap build to add timestamp to command line
27 wrap([$class: 'TimestamperBuildWrapper']) {
[23a14d86]28
[c431138]29 Settings = prepare_build()
[7aebc62]30
[5307c33]31 node(Settings.Architecture.node) {
[bf9d323]32 BuildDir = pwd tmp: true
33 SrcDir = pwd tmp: false
34
[5307c33]35 clean()
[0dc3ac3]36
[5307c33]37 checkout()
[fde808df]38
[5307c33]39 build()
[95fdb0a]40
[5307c33]41 test()
[95fdb0a]42
[5307c33]43 benchmark()
[95fdb0a]44
[5307c33]45 build_doc()
[7359098]46
[5307c33]47 publish()
48 }
[9beae23]49
[4c55047]50 // Update the build directories when exiting the node
51 BuildDir = pwd tmp: true
52 SrcDir = pwd tmp: false
[9beae23]53 }
[738cf8f]54 }
55
[9beae23]56 //If an exception is caught we need to change the status and remember to
57 //attach the build log to the email
[738cf8f]58 catch (Exception caughtError) {
59 //rethrow error later
60 err = caughtError
61
[e966ec0]62 echo err.toString()
63
[9beae23]64 //An error has occured, the build log is relevent
65 log_needed = true
66
67 //Store the result of the build log
[5b8413b4]68 currentBuild.result = "${StageName} FAILURE".trim()
[738cf8f]69 }
70
71 finally {
[9beae23]72 //Send email with final results if this is not a full build
[13c98a4]73 email(log_needed)
[9beae23]74
[734891d]75 echo 'Build Completed'
76
[738cf8f]77 /* Must re-throw exception to propagate error */
78 if (err) {
79 throw err
80 }
81 }
82}
[29f4fe62]83//===========================================================================================================
[9beae23]84// Main compilation routines
[29f4fe62]85//===========================================================================================================
[0dc3ac3]86def clean() {
[6c55a3d]87 build_stage('Cleanup', true) {
[0dc3ac3]88 // clean the build by wipping the build directory
[5b8413b4]89 dir(BuildDir) {
[d4cd491]90 deleteDir()
[ece8a80]91 }
[620dd2b]92 }
[95fdb0a]93}
[29f4fe62]94
[0dc3ac3]95//Compilation script is done here but environnement set-up and error handling is done in main loop
96def checkout() {
[6c55a3d]97 build_stage('Checkout', true) {
[0dc3ac3]98 //checkout the source code and clean the repo
[a336d46]99 final scmVars = checkout scm
100 Settings.GitNewRef = scmVars.GIT_COMMIT
101 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
[d3a4564a]102
[a336d46]103 echo GitLogMessage()
[0dc3ac3]104 }
105}
106
[95fdb0a]107def build() {
[e507c11]108 debug = true
109 release = Settings.RunAllTests || Settings.RunBenchmark
110 build_stage('Build : configure', true) {
[50f2cfc]111 // Build outside of the src tree to ease cleaning
[5b8413b4]112 dir (BuildDir) {
[50f2cfc]113 //Configure the conpilation (Output is not relevant)
114 //Use the current directory as the installation target so nothing escapes the sandbox
115 //Also specify the compiler by hand
[3fc5f010]116 targets=""
[d4510ea]117 if( Settings.RunAllTests || Settings.RunBenchmark ) {
[6bde81d]118 targets="--with-target-hosts='host:debug,host:nodebug'"
[3fc5f010]119 } else {
[6bde81d]120 targets="--with-target-hosts='host:debug'"
[3fc5f010]121 }
122
[93fe3154]123 sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
[f253e4a]124
125 // Configure libcfa
[e70e54e]126 sh 'make -j 8 --no-print-directory configure-libcfa'
[e507c11]127 }
128 }
129
130 build_stage('Build : cfa-cpp', true) {
131 // Build outside of the src tree to ease cleaning
132 dir (BuildDir) {
133 // Build driver
134 sh 'make -j 8 --no-print-directory -C driver'
135
136 // Build translator
137 sh 'make -j 8 --no-print-directory -C src'
138 }
139 }
[1752d0e]140
[e507c11]141 build_stage('Build : libcfa(debug)', debug) {
142 // Build outside of the src tree to ease cleaning
143 dir (BuildDir) {
144 sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
145 }
146 }
147
148 build_stage('Build : libcfa(nodebug)', release) {
149 // Build outside of the src tree to ease cleaning
150 dir (BuildDir) {
151 sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
[50f2cfc]152 }
[620dd2b]153 }
[95fdb0a]154}
[24eecab]155
[95fdb0a]156def test() {
[4c1b9ea8]157 try {
158 build_stage('Test: short', !Settings.RunAllTests) {
159 dir (BuildDir) {
[3e93c00]160 //Run the tests from the tests directory
[4c51aca]161 sh "make --no-print-directory -C tests archiveerrors=${BuildDir}/tests/crashes/short"
[3e93c00]162 }
[4c1b9ea8]163 }
164
165 build_stage('Test: full', Settings.RunAllTests) {
166 dir (BuildDir) {
167 //Run the tests from the tests directory
[4c51aca]168 sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/full-debug"""
169 sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no archiveerrors=${BuildDir}/tests/crashes/full-nodebug"""
[143e6f3]170 }
[9beae23]171 }
[620dd2b]172 }
[4c1b9ea8]173 catch (Exception err) {
174 echo "Archiving core dumps"
[c95fdc9]175 dir (BuildDir) {
176 archiveArtifacts artifacts: "tests/crashes/**/*", fingerprint: true
177 }
[4c1b9ea8]178 throw err
179 }
[95fdb0a]180}
181
182def benchmark() {
[6c55a3d]183 build_stage('Benchmark', Settings.RunBenchmark) {
[5b8413b4]184 dir (BuildDir) {
[0dc3ac3]185 //Append bench results
[c6f1f3e]186 sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
[0dc3ac3]187 }
[620dd2b]188 }
[9beae23]189}
[efd60d67]190
[95fdb0a]191def build_doc() {
[6c55a3d]192 build_stage('Documentation', Settings.BuildDocumentation) {
[9beae23]193 dir ('doc/user') {
194 make_doc()
195 }
196
197 dir ('doc/refrat') {
198 make_doc()
199 }
[620dd2b]200 }
[9beae23]201}
202
[95fdb0a]203def publish() {
[6c55a3d]204 build_stage('Publish', true) {
[95fdb0a]205
[1b3eef8]206 if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
[95fdb0a]207
[3221a2b]208 def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
209 def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
[a2a0065]210
[3898392]211 //Then publish the results
[3221a2b]212 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , false, 'Compilation')
213 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff' , groupCompile , true , 'Compilation (relative)')
214 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch' , groupConcurrency, false, 'Context Switching')
215 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff', groupConcurrency, true , 'Context Switching (relative)')
216 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, false, 'Mutual Exclusion')
217 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff' , groupConcurrency, true , 'Mutual Exclusion (relative)')
218 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal' , groupConcurrency, false, 'Internal and External Scheduling')
219 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal.diff' , groupConcurrency, true , 'Internal and External Scheduling (relative)')
[620dd2b]220 }
[95fdb0a]221}
222
[29f4fe62]223//===========================================================================================================
224//Routine responsible of sending the email notification once the build is completed
225//===========================================================================================================
[a336d46]226def GitLogMessage() {
227 if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
[e8a22a7]228
[fce01e7]229 def oldRef = Settings.GitOldRef
230 def newRef = Settings.GitNewRef
[6badd87]231
[249091f]232 def revisions = sh(returnStdout: true, script: "git rev-list ${oldRef}..${newRef}").trim()
[fce01e7]233 def gitUpdate = ""
[6e31c43]234
[fce01e7]235 revisions.eachLine {
236 def rev = it
[249091f]237 def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
[fce01e7]238 gitUpdate = gitUpdate + " via ${rev} (${type})"
239 }
240
241 def rev = oldRef
[249091f]242 def type = sh(returnStdout: true, script: "git cat-file -t ${rev}").trim()
243 gitUpdate = gitUpdate + " from ${rev} (${type})"
[fce01e7]244
[249091f]245 def gitLog = sh(returnStdout: true, script: "git rev-list --format=short ${oldRef}...${newRef}").trim()
[fce01e7]246
[249091f]247 def gitDiff = sh(returnStdout: true, script: "git diff --stat --color ${newRef} ${oldRef}").trim()
[fce01e7]248 gitDiff = gitDiff.replace('[32m', '<span style="color: #00AA00;">')
249 gitDiff = gitDiff.replace('[31m', '<span style="color: #AA0000;">')
250 gitDiff = gitDiff.replace('[m', '</span>')
[7a927ed0]251
[a336d46]252 return """
[13c98a4]253<pre>
[848fb00]254The branch ${env.BRANCH_NAME} has been updated.
[7a927ed0]255${gitUpdate}
[13c98a4]256</pre>
257
258<p>Check console output at ${env.BUILD_URL} to view the results.</p>
[7b1a604]259
[13c98a4]260<p>- Status --------------------------------------------------------------</p>
[7b1a604]261
[13c98a4]262<p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
[7b1a604]263
[13c98a4]264<p>- Log -----------------------------------------------------------------</p>
[e8a22a7]265
[13c98a4]266<pre>
[7a927ed0]267${gitLog}
[13c98a4]268</pre>
269
270<p>-----------------------------------------------------------------------</p>
271<pre>
[7b1a604]272Summary of changes:
[7a927ed0]273${gitDiff}
[13c98a4]274</pre>
[7b1a604]275"""
[a336d46]276}
277
278//Standard build email notification
[13c98a4]279def email(boolean log) {
[a336d46]280 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
281 //Configurations for email format
282 echo 'Notifying users of result'
283
284 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
285 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
[13c98a4]286 def email_body = """<p>This is an automated email from the Jenkins build machine. It was
[a336d46]287generated because of a git hooks/post-receive script following
[986e260]288a ref change which was pushed to the C\u2200 repository.</p>
[a336d46]289""" + GitLogMessage()
[e8a22a7]290
[13c98a4]291 def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
[e8a22a7]292
[13c98a4]293 if( Settings && !Settings.Silent ) {
[094a42c]294 //send email notification
295 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
296 } else {
297 echo "Would send email to: ${email_to}"
298 echo "With title: ${email_subject}"
299 echo "Content: \n${email_body}"
300 }
[e8a22a7]301}
[5b8413b4]302
303//===========================================================================================================
304// Helper classes/variables/routines
305//===========================================================================================================
306//Description of a compiler (Must be serializable since pipelines are persistent)
307class CC_Desc implements Serializable {
[93fe3154]308 public String name
309 public String CXX
[6ebc13f]310 public String CC
[93fe3154]311
[6ebc13f]312 CC_Desc(String name, String CXX, String CC) {
[93fe3154]313 this.name = name
314 this.CXX = CXX
[6ebc13f]315 this.CC = CC
[5b8413b4]316 }
317}
318
319//Description of an architecture (Must be serializable since pipelines are persistent)
320class Arch_Desc implements Serializable {
321 public String name
322 public String flags
[5307c33]323 public String node
[5b8413b4]324
[5307c33]325 Arch_Desc(String name, String flags, String node) {
[5b8413b4]326 this.name = name
327 this.flags = flags
[5307c33]328 this.node = node
[5b8413b4]329 }
330}
331
332class BuildSettings implements Serializable {
333 public final CC_Desc Compiler
334 public final Arch_Desc Architecture
335 public final Boolean RunAllTests
336 public final Boolean RunBenchmark
337 public final Boolean BuildDocumentation
338 public final Boolean Publish
339 public final Boolean Silent
340 public final Boolean IsSandbox
341 public final String DescLong
342 public final String DescShort
343
[a336d46]344 public String GitNewRef
345 public String GitOldRef
346
[490cb3c]347 BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
[5b8413b4]348 switch( param.Compiler ) {
349 case 'gcc-6':
350 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
351 break
352 case 'gcc-5':
353 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
354 break
355 case 'gcc-4.9':
356 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
357 break
358 case 'clang':
359 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
360 break
361 default :
362 error "Unhandled compiler : ${cc}"
363 }
364
365 switch( param.Architecture ) {
366 case 'x64':
[a3e8281]367 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
[5b8413b4]368 break
369 case 'x86':
[a3e8281]370 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
[5b8413b4]371 break
372 default :
373 error "Unhandled architecture : ${arch}"
374 }
375
[f95e8f0]376 this.IsSandbox = (branch == "jenkins-sandbox")
[5b8413b4]377 this.RunAllTests = param.RunAllTests
[7a230fd]378 this.RunBenchmark = param.RunBenchmark
[5b8413b4]379 this.BuildDocumentation = param.BuildDocumentation
[7a230fd]380 this.Publish = param.Publish
[5b8413b4]381 this.Silent = param.Silent
382
383 def full = param.RunAllTests ? " (Full)" : ""
[490cb3c]384 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
[5b8413b4]385
[93fe3154]386 this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
[5b8413b4]387Architecture : ${ this.Architecture.name }
388Arc Flags : ${ this.Architecture.flags }
389Run All Tests : ${ this.RunAllTests.toString() }
390Run Benchmark : ${ this.RunBenchmark.toString() }
391Build Documentation : ${ this.BuildDocumentation.toString() }
392Publish : ${ this.Publish.toString() }
393Silent : ${ this.Silent.toString() }
394"""
[a336d46]395
396 this.GitNewRef = ''
397 this.GitOldRef = ''
[5b8413b4]398 }
399}
400
[490cb3c]401class PlotGroup implements Serializable {
402 public String name
403 public String unit
404 public boolean log
405
406 PlotGroup(String name, String unit, boolean log) {
407 this.name = name
408 this.unit = unit
409 this.log = log
410 }
411}
412
[5b8413b4]413def prepare_build() {
414 // prepare the properties
415 properties ([ \
416 [$class: 'ParametersDefinitionProperty', \
417 parameterDefinitions: [ \
418 [$class: 'ChoiceParameterDefinition', \
419 description: 'Which compiler to use', \
420 name: 'Compiler', \
421 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
422 defaultValue: 'gcc-6', \
423 ], \
424 [$class: 'ChoiceParameterDefinition', \
425 description: 'The target architecture', \
426 name: 'Architecture', \
427 choices: 'x64\nx86', \
428 defaultValue: 'x64', \
429 ], \
430 [$class: 'BooleanParameterDefinition', \
431 description: 'If false, only the quick test suite is ran', \
432 name: 'RunAllTests', \
433 defaultValue: false, \
434 ], \
435 [$class: 'BooleanParameterDefinition', \
436 description: 'If true, jenkins also runs benchmarks', \
437 name: 'RunBenchmark', \
438 defaultValue: false, \
439 ], \
440 [$class: 'BooleanParameterDefinition', \
441 description: 'If true, jenkins also builds documentation', \
442 name: 'BuildDocumentation', \
443 defaultValue: true, \
444 ], \
445 [$class: 'BooleanParameterDefinition', \
446 description: 'If true, jenkins also publishes results', \
447 name: 'Publish', \
448 defaultValue: false, \
449 ], \
450 [$class: 'BooleanParameterDefinition', \
451 description: 'If true, jenkins will not send emails', \
452 name: 'Silent', \
453 defaultValue: false, \
454 ], \
455 ],
456 ]])
457
[4c55047]458 // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
459 checkout scm
[2407853]460
[490cb3c]461 final settings = new BuildSettings(params, env.BRANCH_NAME)
[5b8413b4]462
463 currentBuild.description = settings.DescShort
464 echo settings.DescLong
465
466 return settings
467}
468
[6c55a3d]469def build_stage(String name, boolean run, Closure block ) {
[5b8413b4]470 StageName = name
471 echo " -------- ${StageName} -------- "
[8ecb590]472 if(run) {
473 stage(name, block)
474 } else {
475 stage(name) { Utils.markStageSkippedForConditional(STAGE_NAME) }
476 }
[5b8413b4]477}
478
479def make_doc() {
480 def err = null
481 try {
482 sh 'make clean > /dev/null'
483 sh 'make > /dev/null 2>&1'
484 }
485 catch (Exception caughtError) {
486 err = caughtError //rethrow error later
[65f4a51]487 sh 'cat build/*.log'
[5b8413b4]488 }
489 finally {
490 if (err) throw err // Must re-throw exception to propagate error
491 }
[a2a0065]492}
493
[3221a2b]494def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
[8d63649]495
[1b3eef8]496 if(new_data) {
497 echo "Publishing new data"
498 }
499
[cdcd53dc]500 def series = new_data ? [[
[df57a84]501 file: "${file}.csv",
[3c40dc2a]502 exclusionValues: '',
503 displayTableFlag: false,
504 inclusionFlag: 'OFF',
505 url: ''
[cdcd53dc]506 ]] : [];
[8d63649]507
508 echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
509 dir("${BuildDir}/benchmark/") {
510 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
511 csvSeries: series,
[490cb3c]512 group: "${group.name}",
[3c40dc2a]513 title: "${title}",
514 style: 'lineSimple',
515 exclZero: false,
516 keepRecords: false,
[3221a2b]517 logarithmic: !relative && group.log,
[3c40dc2a]518 numBuilds: '120',
519 useDescr: true,
[490cb3c]520 yaxis: group.unit,
[3c40dc2a]521 yaxisMaximum: '',
522 yaxisMinimum: ''
[df57a84]523 }
524}
Note: See TracBrowser for help on using the repository browser.