source: Jenkinsfile@ 6c55a3d

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

Change jenkins file to mark staged as skipped rather than lasted 0s

  • Property mode set to 100644
File size: 12.9 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', true) {
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', true) {
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', true) {
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', true) {
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=1200" all-tests debug=yes'
133 sh 'make --no-print-directory -C tests timeouts="--timeout=1200" 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', Settings.RunBenchmark) {
144 dir (BuildDir) {
145 //Append bench results
146 sh "make --no-print-directory -C benchmark jenkins"
147 }
148 }
149}
150
151def build_doc() {
152 build_stage('Documentation', Settings.BuildDocumentation) {
153 dir ('doc/user') {
154 make_doc()
155 }
156
157 dir ('doc/refrat') {
158 make_doc()
159 }
160 }
161}
162
163def publish() {
164 build_stage('Publish', true) {
165
166 if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
167
168 def groupCompile = new PlotGroup('Compilation', 'seconds', true)
169 def groupConcurrency = new PlotGroup('Concurrency', 'nanoseconds', false)
170
171 //Then publish the results
172 do_plot(Settings.RunBenchmark && Settings.Publish, 'compile' , groupCompile , 'Compilation')
173 do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch', groupConcurrency, 'Context Switching')
174 do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex' , groupConcurrency, 'Mutual Exclusion')
175 do_plot(Settings.RunBenchmark && Settings.Publish, 'signal' , groupConcurrency, 'Internal and External Scheduling')
176 }
177}
178
179//===========================================================================================================
180//Routine responsible of sending the email notification once the build is completed
181//===========================================================================================================
182def GitLogMessage() {
183 if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
184
185 sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
186
187 def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
188 def gitLog = readFile("${BuildDir}/GIT_LOG")
189 def gitDiff = readFile("${BuildDir}/GIT_DIFF")
190
191 return """
192<pre>
193The branch ${env.BRANCH_NAME} has been updated.
194${gitUpdate}
195</pre>
196
197<p>Check console output at ${env.BUILD_URL} to view the results.</p>
198
199<p>- Status --------------------------------------------------------------</p>
200
201<p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
202
203<p>- Log -----------------------------------------------------------------</p>
204
205<pre>
206${gitLog}
207</pre>
208
209<p>-----------------------------------------------------------------------</p>
210<pre>
211Summary of changes:
212${gitDiff}
213</pre>
214"""
215}
216
217//Standard build email notification
218def email(boolean log) {
219 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
220 //Configurations for email format
221 echo 'Notifying users of result'
222
223 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
224 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
225 def email_body = """<p>This is an automated email from the Jenkins build machine. It was
226generated because of a git hooks/post-receive script following
227a ref change which was pushed to the C\u2200 repository.</p>
228""" + GitLogMessage()
229
230 def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
231
232 if( Settings && !Settings.Silent ) {
233 //send email notification
234 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
235 } else {
236 echo "Would send email to: ${email_to}"
237 echo "With title: ${email_subject}"
238 echo "Content: \n${email_body}"
239 }
240}
241
242//===========================================================================================================
243// Helper classes/variables/routines
244//===========================================================================================================
245//Description of a compiler (Must be serializable since pipelines are persistent)
246class CC_Desc implements Serializable {
247 public String name
248 public String CXX
249 public String CC
250
251 CC_Desc(String name, String CXX, String CC) {
252 this.name = name
253 this.CXX = CXX
254 this.CC = CC
255 }
256}
257
258//Description of an architecture (Must be serializable since pipelines are persistent)
259class Arch_Desc implements Serializable {
260 public String name
261 public String flags
262 public String node
263
264 Arch_Desc(String name, String flags, String node) {
265 this.name = name
266 this.flags = flags
267 this.node = node
268 }
269}
270
271class BuildSettings implements Serializable {
272 public final CC_Desc Compiler
273 public final Arch_Desc Architecture
274 public final Boolean RunAllTests
275 public final Boolean RunBenchmark
276 public final Boolean BuildDocumentation
277 public final Boolean Publish
278 public final Boolean Silent
279 public final Boolean IsSandbox
280 public final String DescLong
281 public final String DescShort
282
283 public String GitNewRef
284 public String GitOldRef
285
286 BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
287 switch( param.Compiler ) {
288 case 'gcc-6':
289 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
290 break
291 case 'gcc-5':
292 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
293 break
294 case 'gcc-4.9':
295 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
296 break
297 case 'clang':
298 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
299 break
300 default :
301 error "Unhandled compiler : ${cc}"
302 }
303
304 switch( param.Architecture ) {
305 case 'x64':
306 this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
307 break
308 case 'x86':
309 this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
310 break
311 default :
312 error "Unhandled architecture : ${arch}"
313 }
314
315 this.IsSandbox = (branch == "jenkins-sandbox")
316 this.RunAllTests = param.RunAllTests
317 this.RunBenchmark = param.RunBenchmark
318 this.BuildDocumentation = param.BuildDocumentation
319 this.Publish = param.Publish
320 this.Silent = param.Silent
321
322 def full = param.RunAllTests ? " (Full)" : ""
323 this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
324
325 this.DescLong = """Compiler : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
326Architecture : ${ this.Architecture.name }
327Arc Flags : ${ this.Architecture.flags }
328Run All Tests : ${ this.RunAllTests.toString() }
329Run Benchmark : ${ this.RunBenchmark.toString() }
330Build Documentation : ${ this.BuildDocumentation.toString() }
331Publish : ${ this.Publish.toString() }
332Silent : ${ this.Silent.toString() }
333"""
334
335 this.GitNewRef = ''
336 this.GitOldRef = ''
337 }
338}
339
340class PlotGroup implements Serializable {
341 public String name
342 public String unit
343 public boolean log
344
345 PlotGroup(String name, String unit, boolean log) {
346 this.name = name
347 this.unit = unit
348 this.log = log
349 }
350}
351
352def prepare_build() {
353 // prepare the properties
354 properties ([ \
355 [$class: 'ParametersDefinitionProperty', \
356 parameterDefinitions: [ \
357 [$class: 'ChoiceParameterDefinition', \
358 description: 'Which compiler to use', \
359 name: 'Compiler', \
360 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
361 defaultValue: 'gcc-6', \
362 ], \
363 [$class: 'ChoiceParameterDefinition', \
364 description: 'The target architecture', \
365 name: 'Architecture', \
366 choices: 'x64\nx86', \
367 defaultValue: 'x64', \
368 ], \
369 [$class: 'BooleanParameterDefinition', \
370 description: 'If false, only the quick test suite is ran', \
371 name: 'RunAllTests', \
372 defaultValue: false, \
373 ], \
374 [$class: 'BooleanParameterDefinition', \
375 description: 'If true, jenkins also runs benchmarks', \
376 name: 'RunBenchmark', \
377 defaultValue: false, \
378 ], \
379 [$class: 'BooleanParameterDefinition', \
380 description: 'If true, jenkins also builds documentation', \
381 name: 'BuildDocumentation', \
382 defaultValue: true, \
383 ], \
384 [$class: 'BooleanParameterDefinition', \
385 description: 'If true, jenkins also publishes results', \
386 name: 'Publish', \
387 defaultValue: false, \
388 ], \
389 [$class: 'BooleanParameterDefinition', \
390 description: 'If true, jenkins will not send emails', \
391 name: 'Silent', \
392 defaultValue: false, \
393 ], \
394 ],
395 ]])
396
397 // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
398 checkout scm
399
400 final settings = new BuildSettings(params, env.BRANCH_NAME)
401
402 currentBuild.description = settings.DescShort
403 echo settings.DescLong
404
405 return settings
406}
407
408def build_stage(String name, boolean run, Closure block ) {
409 StageName = name
410 echo " -------- ${StageName} -------- "
411 stage(name, run ? block : false)
412}
413
414def make_doc() {
415 def err = null
416 try {
417 sh 'make clean > /dev/null'
418 sh 'make > /dev/null 2>&1'
419 }
420 catch (Exception caughtError) {
421 err = caughtError //rethrow error later
422 sh 'cat build/*.log'
423 }
424 finally {
425 if (err) throw err // Must re-throw exception to propagate error
426 }
427}
428
429def do_plot(boolean new_data, String file, PlotGroup group, String title) {
430
431 if(new_data) {
432 echo "Publishing new data"
433 }
434
435 def series = new_data ? [[
436 file: "${file}.csv",
437 exclusionValues: '',
438 displayTableFlag: false,
439 inclusionFlag: 'OFF',
440 url: ''
441 ]] : [];
442
443 echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
444 dir("${BuildDir}/benchmark/") {
445 plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
446 csvSeries: series,
447 group: "${group.name}",
448 title: "${title}",
449 style: 'lineSimple',
450 exclZero: false,
451 keepRecords: false,
452 logarithmic: group.log,
453 numBuilds: '120',
454 useDescr: true,
455 yaxis: group.unit,
456 yaxisMaximum: '',
457 yaxisMinimum: ''
458 }
459}
Note: See TracBrowser for help on using the repository browser.