source: Jenkinsfile@ 3ad40e2

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr no_list persistent-indexer pthread-emulation qualifiedEnum
Last change on this file since 3ad40e2 was 3ad40e2, checked in by Thierry Delisle <tdelisle@…>, 7 years ago

Trying to understand staic member calls

  • Property mode set to 100644
File size: 12.5 KB
Line 
1#!groovy
2
3//===========================================================================================================
4// Main loop of the compilation
5//===========================================================================================================
6node ('master'){
7
8 def err = null
9 def log_needed = false
10
11 Settings = null
12
13 stage_name = ''
14
15 gitRefOldValue = ''
16 gitRefNewValue = ''
17
18 builddir = pwd tmp: true
19 srcdir = pwd tmp: false
20
21 currentBuild.result = "SUCCESS"
22
23 try {
24 //Wrap build to add timestamp to command line
25 wrap([$class: 'TimestamperBuildWrapper']) {
26
27 notify_server(0)
28
29 Settings = prepare_build()
30
31 clean()
32
33 checkout()
34
35 notify_server(0)
36
37 build()
38
39 test()
40
41 benchmark()
42
43 build_doc()
44
45 publish()
46
47 notify_server(45)
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 = "${stage_name} FAILURE".trim()
64 }
65
66 finally {
67 //Send email with final results if this is not a full build
68 if( Settings && !Settings.Silent ) {
69 echo 'Notifying users of result'
70 email(currentBuild.result, log_needed, bIsSandbox)
71 }
72
73 echo 'Build Completed'
74
75 /* Must re-throw exception to propagate error */
76 if (err) {
77 throw err
78 }
79 }
80}
81
82//===========================================================================================================
83// Helper classes/variables/routines
84//===========================================================================================================
85class BuildSettings implements Serializable {
86 public final CC_Desc Compiler
87 public final Arch_Desc Architecture
88 public final Boolean RunAllTests
89 public final Boolean RunBenchmark
90 public final Boolean BuildDocumentation
91 public final Boolean Publish
92 public final Boolean Silent
93 public final Boolean IsSandbox
94 public final String Branch
95 public final String Commit
96 public final String PrevCommit
97 public final String RepoUrl
98 public final String DescLong
99 public final String DescShort
100
101
102 //Description of a compiler (Must be serializable since pipelines are persistent)
103 private class CC_Desc implements Serializable {
104 public String cc_name
105 public String cpp_cc
106 public String cfa_cc
107
108 CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
109 this.cc_name = cc_name
110 this.cpp_cc = cpp_cc
111 this.cfa_cc = cfa_cc
112 }
113 }
114
115 private static CC_Desc compiler_from_params(String cc) {
116 switch( cc ) {
117 case 'gcc-6':
118 return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
119 break
120 case 'gcc-5':
121 return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
122 break
123 case 'gcc-4.9':
124 return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
125 break
126 case 'clang':
127 return new CC_Desc('clang', 'clang++', 'gcc-6')
128 break
129 default :
130 error "Unhandled compiler : ${cc}"
131 }
132 }
133
134 //Description of an architecture (Must be serializable since pipelines are persistent)
135 private class Arch_Desc implements Serializable {
136 public String name
137 public String flags
138
139 Arch_Desc(String name, String flags) {
140 this.name = name
141 this.flags = flags
142 }
143 }
144
145 private static Arch_Desc architecture_from_params( String arch ) {
146 switch( arch ) {
147 case 'x64':
148 return new Arch_Desc('x64', '--host=x86_64')
149 break
150 case 'x86':
151 return new Arch_Desc('x86', '--host=i386')
152 break
153 default :
154 error "Unhandled architecture : ${arch}"
155 }
156 }
157
158 BuildSettings(java.util.Collections$UnmodifiableMap param, java.util.TreeMap scmVars) {
159 this.Compiler = BuildSettings.compiler_from_params( param.Compiler )
160 this.Architecture = BuildSettings.architecture_from_params( param.Architecture )
161 this.RunAllTests = param.RunAllTests
162 this.RunBenchmark = param.RunBenchmark
163 this.BuildDocumentation = param.BuildDocumentation
164 this.Publish = param.Publish
165 this.Silent = param.Silent
166 this.IsSandbox = scmVars.GIT_BRANCH == "jenkins-sandbox"
167 this.Branch = scmVars.GIT_BRANCH
168 this.Commit = scmVars.GIT_COMMIT
169 this.PrevCommit = scmVars.GIT_PREVIOUS_COMMIT
170 this.RepoUrl = scmVars.GIT_URL
171
172 def full = param.RunAllTests ? " (Full)" : ""
173 this.DescShort = "${ this.Compiler.cc_name }:${ this.Architecture.name }${full}"
174
175 this.DescLong """Compiler : ${ this.Compiler.cc_name } (${ this.Compiler.cpp_cc }/${ this.Compiler.cfa_cc })
176Architecture : ${ this.Architecture.name }
177Arc Flags : ${ this.Architecture.flags }
178Run All Tests : ${ this.RunAllTests.toString() }
179Run Benchmark : ${ this.RunBenchmark.toString() }
180Build Documentation : ${ this.BuildDocumentation.toString() }
181Publish : ${ this.Publish.toString() }
182Silent : ${ this.Silent.toString() }
183"""
184 }
185}
186
187def prepare_build() {
188 // prepare the properties
189 properties ([ \
190 [$class: 'ParametersDefinitionProperty', \
191 parameterDefinitions: [ \
192 [$class: 'ChoiceParameterDefinition', \
193 description: 'Which compiler to use', \
194 name: 'Compiler', \
195 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
196 defaultValue: 'gcc-6', \
197 ], \
198 [$class: 'ChoiceParameterDefinition', \
199 description: 'The target architecture', \
200 name: 'Architecture', \
201 choices: 'x64\nx86', \
202 defaultValue: 'x64', \
203 ], \
204 [$class: 'BooleanParameterDefinition', \
205 description: 'If false, only the quick test suite is ran', \
206 name: 'RunAllTests', \
207 defaultValue: false, \
208 ], \
209 [$class: 'BooleanParameterDefinition', \
210 description: 'If true, jenkins also runs benchmarks', \
211 name: 'RunBenchmark', \
212 defaultValue: false, \
213 ], \
214 [$class: 'BooleanParameterDefinition', \
215 description: 'If true, jenkins also builds documentation', \
216 name: 'BuildDocumentation', \
217 defaultValue: true, \
218 ], \
219 [$class: 'BooleanParameterDefinition', \
220 description: 'If true, jenkins also publishes results', \
221 name: 'Publish', \
222 defaultValue: false, \
223 ], \
224 [$class: 'BooleanParameterDefinition', \
225 description: 'If true, jenkins will not send emails', \
226 name: 'Silent', \
227 defaultValue: false, \
228 ], \
229 ],
230 ]])
231
232 // Collect git information
233 final scmVars = checkout scm
234
235 final settings = new BuildSettings(params, scmVars)
236
237 currentBuild.description = settings.DescShort
238 echo settings.DescLong
239
240 return settings
241}
242
243def build_stage(String name, Closure block ) {
244 stage_name = name
245 stage(name, block)
246}
247
248def notify_server(int wait) {
249 sh """curl --silent --show-error --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
250 return
251}
252
253def make_doc() {
254 def err = null
255 try {
256 sh 'make clean > /dev/null'
257 sh 'make > /dev/null 2>&1'
258 }
259 catch (Exception caughtError) {
260 err = caughtError //rethrow error later
261 sh 'cat *.log'
262 }
263 finally {
264 if (err) throw err // Must re-throw exception to propagate error
265 }
266}
267
268//===========================================================================================================
269// Main compilation routines
270//===========================================================================================================
271def clean() {
272 build_stage('Cleanup') {
273 // clean the build by wipping the build directory
274 dir(builddir) {
275 deleteDir()
276 }
277
278 //Clean all temporary files to make sure no artifacts of the previous build remain
279 sh 'git clean -fdqx'
280
281 //Reset the git repo so no local changes persist
282 sh 'git reset --hard'
283 }
284}
285
286//Compilation script is done here but environnement set-up and error handling is done in main loop
287def checkout() {
288 build_stage('Checkout') {
289 //checkout the source code and clean the repo
290 checkout scm
291 }
292}
293
294def build() {
295 build_stage('Build') {
296 // Build outside of the src tree to ease cleaning
297 dir (builddir) {
298 //Configure the conpilation (Output is not relevant)
299 //Use the current directory as the installation target so nothing escapes the sandbox
300 //Also specify the compiler by hand
301 targets=""
302 if( Settings.RunAllTests ) {
303 targets="--with-target-hosts='host:debug,host:nodebug'"
304 } else {
305 targets="--with-target-hosts='host:debug'"
306 }
307
308 sh "${srcdir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"
309
310 //Compile the project
311 sh 'make -j 8 --no-print-directory'
312 }
313 }
314}
315
316def test() {
317 build_stage('Test') {
318
319 dir (builddir) {
320 //Run the tests from the tests directory
321 if ( Settings.RunAllTests ) {
322 sh 'make --no-print-directory -C tests all-tests debug=yes'
323 sh 'make --no-print-directory -C tests all-tests debug=no '
324 }
325 else {
326 sh 'make --no-print-directory -C tests'
327 }
328 }
329 }
330}
331
332def benchmark() {
333 build_stage('Benchmark') {
334
335 if( !Settings.RunBenchmark ) return
336
337 dir (builddir) {
338 //Append bench results
339 sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${Settings.Architecture} | tee ${srcdir}/bench.json"
340 }
341 }
342}
343
344def build_doc() {
345 build_stage('Documentation') {
346
347 if( !Settings.BuildDocumentation ) return
348
349 dir ('doc/user') {
350 make_doc()
351 }
352
353 dir ('doc/refrat') {
354 make_doc()
355 }
356 }
357}
358
359def publish() {
360 build_stage('Publish') {
361
362 if( !Settings.Publish ) return
363
364 //Then publish the results
365 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
366 }
367}
368
369//===========================================================================================================
370//Routine responsible of sending the email notification once the build is completed
371//===========================================================================================================
372def gitBranchUpdate(String gitRefOldValue, String gitRefNewValue) {
373 def update = ""
374 sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG";
375 readFile('GIT_LOG').eachLine { rev ->
376 sh "git cat-file -t ${rev} > GIT_TYPE"
377 def type = readFile('GIT_TYPE')
378
379 update += " via ${rev} (${type})\n"
380 }
381 def rev = gitRefOldValue
382 sh "git cat-file -t ${rev} > GIT_TYPE"
383 def type = readFile('GIT_TYPE')
384
385 update += " from ${rev} (${type})\n"
386 return update
387
388def output=readFile('result').trim()
389echo "output=$output";
390}
391
392//Standard build email notification
393def email(String status, boolean log, boolean bIsSandbox) {
394 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
395 //Configurations for email format
396 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
397
398 def gitLog = 'Error retrieving git logs'
399 def gitDiff = 'Error retrieving git diff'
400 def gitUpdate = 'Error retrieving update'
401
402 try {
403 gitUpdate = gitBranchUpdate(Settings.PrevCommit, Settings.Commit)
404
405 sh "git rev-list --format=short ${Settings.PrevCommit}...${Settings.Commit} > GIT_LOG"
406 gitLog = readFile('GIT_LOG')
407
408 sh "git diff --stat ${Settings.Commit} ${Settings.PrevCommit} > GIT_DIFF"
409 gitDiff = readFile('GIT_DIFF')
410 }
411 catch (Exception error) {
412 echo error.toString()
413 echo error.getMessage()
414 }
415
416 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
417 def email_body = """This is an automated email from the Jenkins build machine. It was
418generated because of a git hooks/post-receive script following
419a ref change was pushed to the repository containing
420the project "UNNAMED PROJECT".
421
422The branch ${env.BRANCH_NAME} has been updated.
423${gitUpdate}
424
425Check console output at ${env.BUILD_URL} to view the results.
426
427- Status --------------------------------------------------------------
428
429BUILD# ${env.BUILD_NUMBER} - ${status}
430
431- Log -----------------------------------------------------------------
432${gitLog}
433-----------------------------------------------------------------------
434Summary of changes:
435${gitDiff}
436"""
437
438 def email_to = "cforall@lists.uwaterloo.ca"
439
440 if( !bIsSandbox ) {
441 //send email notification
442 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
443 } else {
444 echo "Would send email to: ${email_to}"
445 echo "With title: ${email_subject}"
446 echo "Content: \n${email_body}"
447 }
448}
Note: See TracBrowser for help on using the repository browser.