source: Jenkinsfile@ 3898392

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

Moved group globals into publish function

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