source: Jenkinsfile@ 4f9e706

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 4f9e706 was 4f9e706, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Testing what can happen outside of nodes

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