source: Jenkinsfile@ 8ecb590

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

More obscure tentative for skipped builds

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