source: Jenkinsfile@ 490cb3c

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

Some improvements on plots to be correct for both fine grain concurrency and compilation

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