source: Jenkinsfile@ d9f2874

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 d9f2874 was d4510ea, checked in by tdelisle <tdelisle@…>, 6 years ago

Jenkins now also builds the nodebug version if the build should NOT run all tests but SHOULD run benchmarks

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