source: Jenkinsfile@ e0549dba

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

Fix error and print current build

  • Property mode set to 100644
File size: 11.9 KB
Line 
1#!groovy
2
3//===========================================================================================================
4// Main loop of the compilation
5//===========================================================================================================
6node ('master'){
7
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 echo "${currentBuild.changeSets}"
28
29 clean()
30
31 checkout()
32
33 notify_server(0)
34
35 build()
36
37 test()
38
39 benchmark()
40
41 build_doc()
42
43 publish()
44
45 notify_server(45)
46 }
47 }
48
49 //If an exception is caught we need to change the status and remember to
50 //attach the build log to the email
51 catch (Exception caughtError) {
52 //rethrow error later
53 err = caughtError
54
55 echo err.toString()
56
57 //An error has occured, the build log is relevent
58 log_needed = true
59
60 //Store the result of the build log
61 currentBuild.result = "${StageName} FAILURE".trim()
62 }
63
64 finally {
65 //Send email with final results if this is not a full build
66 if( Settings && !Settings.Silent ) {
67 echo 'Notifying users of result'
68 email(currentBuild.result, log_needed, bIsSandbox)
69 }
70
71 echo 'Build Completed'
72
73 /* Must re-throw exception to propagate error */
74 if (err) {
75 throw err
76 }
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 checkout scm
97 }
98}
99
100def build() {
101 build_stage('Build') {
102 // Build outside of the src tree to ease cleaning
103 dir (BuildDir) {
104 //Configure the conpilation (Output is not relevant)
105 //Use the current directory as the installation target so nothing escapes the sandbox
106 //Also specify the compiler by hand
107 targets=""
108 if( Settings.RunAllTests ) {
109 targets="--with-target-hosts='host:debug,host:nodebug'"
110 } else {
111 targets="--with-target-hosts='host:debug'"
112 }
113
114 sh "${SrcDir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"
115
116 //Compile the project
117 sh 'make -j 8 --no-print-directory'
118 }
119 }
120}
121
122def test() {
123 build_stage('Test') {
124
125 dir (BuildDir) {
126 //Run the tests from the tests directory
127 if ( Settings.RunAllTests ) {
128 sh 'make --no-print-directory -C tests all-tests debug=yes'
129 sh 'make --no-print-directory -C tests all-tests debug=no '
130 }
131 else {
132 sh 'make --no-print-directory -C tests'
133 }
134 }
135 }
136}
137
138def benchmark() {
139 build_stage('Benchmark') {
140
141 if( !Settings.RunBenchmark ) return
142
143 dir (BuildDir) {
144 //Append bench results
145 sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${Settings.Architecture} | tee ${SrcDir}/bench.json"
146 }
147 }
148}
149
150def build_doc() {
151 build_stage('Documentation') {
152
153 if( !Settings.BuildDocumentation ) return
154
155 dir ('doc/user') {
156 make_doc()
157 }
158
159 dir ('doc/refrat') {
160 make_doc()
161 }
162 }
163}
164
165def publish() {
166 build_stage('Publish') {
167
168 if( !Settings.Publish ) return
169
170 //Then publish the results
171 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
172 }
173}
174
175//===========================================================================================================
176//Routine responsible of sending the email notification once the build is completed
177//===========================================================================================================
178def gitBranchUpdate(String gitRefOldValue, String gitRefNewValue) {
179 def update = ""
180 sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG";
181 readFile('GIT_LOG').eachLine { rev ->
182 sh "git cat-file -t ${rev} > GIT_TYPE"
183 def type = readFile('GIT_TYPE')
184
185 update += " via ${rev} (${type})\n"
186 }
187 def rev = gitRefOldValue
188 sh "git cat-file -t ${rev} > GIT_TYPE"
189 def type = readFile('GIT_TYPE')
190
191 update += " from ${rev} (${type})\n"
192 return update
193
194 def output=readFile('result').trim()
195 echo "output=$output";
196}
197
198//Standard build email notification
199def email(String status, boolean log, boolean bIsSandbox) {
200 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
201 //Configurations for email format
202 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
203
204 def gitLog = 'Error retrieving git logs'
205 def gitDiff = 'Error retrieving git diff'
206 def gitUpdate = 'Error retrieving update'
207
208 try {
209 final scmVars = checkout(scm)
210
211 gitUpdate = gitBranchUpdate(scmVars.GIT_PREVIOUS_COMMIT, scmVars.GIT_COMMIT)
212
213 sh "git rev-list --format=short ${scmVars.GIT_PREVIOUS_COMMIT}...${scmVars.GIT_COMMIT} > ${BuildDir}/GIT_LOG"
214 gitLog = readFile("${BuildDir}/GIT_LOG")
215
216 sh "git diff --stat ${scmVars.GIT_COMMIT} ${scmVars.GIT_PREVIOUS_COMMIT} > ${BuildDir}/GIT_DIFF"
217 gitDiff = readFile("${BuildDir}/GIT_DIFF")
218 }
219 catch (Exception error) {
220 echo error.toString()
221 echo error.getMessage()
222 }
223
224 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
225 def email_body = """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 was pushed to the repository containing
228the project "UNNAMED PROJECT".
229
230The branch ${env.BRANCH_NAME} has been updated.
231${gitUpdate}
232
233Check console output at ${env.BUILD_URL} to view the results.
234
235- Status --------------------------------------------------------------
236
237BUILD# ${env.BUILD_NUMBER} - ${status}
238
239- Log -----------------------------------------------------------------
240${gitLog}
241-----------------------------------------------------------------------
242Summary of changes:
243${gitDiff}
244"""
245
246 def email_to = "cforall@lists.uwaterloo.ca"
247
248 if( Settings && !Settings.IsSandbox ) {
249 //send email notification
250 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
251 } else {
252 echo "Would send email to: ${email_to}"
253 echo "With title: ${email_subject}"
254 echo "Content: \n${email_body}"
255 }
256}
257
258//===========================================================================================================
259// Helper classes/variables/routines
260//===========================================================================================================
261//Description of a compiler (Must be serializable since pipelines are persistent)
262class CC_Desc implements Serializable {
263 public String cc_name
264 public String cpp_cc
265 public String cfa_cc
266
267 CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
268 this.cc_name = cc_name
269 this.cpp_cc = cpp_cc
270 this.cfa_cc = cfa_cc
271 }
272}
273
274//Description of an architecture (Must be serializable since pipelines are persistent)
275class Arch_Desc implements Serializable {
276 public String name
277 public String flags
278
279 Arch_Desc(String name, String flags) {
280 this.name = name
281 this.flags = flags
282 }
283}
284
285class BuildSettings implements Serializable {
286 public final CC_Desc Compiler
287 public final Arch_Desc Architecture
288 public final Boolean RunAllTests
289 public final Boolean RunBenchmark
290 public final Boolean BuildDocumentation
291 public final Boolean Publish
292 public final Boolean Silent
293 public final Boolean IsSandbox
294 public final String DescLong
295 public final String DescShort
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')
318 break
319 case 'x86':
320 this.Architecture = new Arch_Desc('x86', '--host=i386')
321 break
322 default :
323 error "Unhandled architecture : ${arch}"
324 }
325
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 this.IsSandbox = (branch == "jenkins-sandbox")
332
333 def full = param.RunAllTests ? " (Full)" : ""
334 this.DescShort = "${ this.Compiler.cc_name }:${ this.Architecture.name }${full}"
335
336 this.DescLong = """Compiler : ${ this.Compiler.cc_name } (${ this.Compiler.cpp_cc }/${ this.Compiler.cfa_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}
347
348def prepare_build() {
349 // prepare the properties
350 properties ([ \
351 [$class: 'ParametersDefinitionProperty', \
352 parameterDefinitions: [ \
353 [$class: 'ChoiceParameterDefinition', \
354 description: 'Which compiler to use', \
355 name: 'Compiler', \
356 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
357 defaultValue: 'gcc-6', \
358 ], \
359 [$class: 'ChoiceParameterDefinition', \
360 description: 'The target architecture', \
361 name: 'Architecture', \
362 choices: 'x64\nx86', \
363 defaultValue: 'x64', \
364 ], \
365 [$class: 'BooleanParameterDefinition', \
366 description: 'If false, only the quick test suite is ran', \
367 name: 'RunAllTests', \
368 defaultValue: false, \
369 ], \
370 [$class: 'BooleanParameterDefinition', \
371 description: 'If true, jenkins also runs benchmarks', \
372 name: 'RunBenchmark', \
373 defaultValue: false, \
374 ], \
375 [$class: 'BooleanParameterDefinition', \
376 description: 'If true, jenkins also builds documentation', \
377 name: 'BuildDocumentation', \
378 defaultValue: true, \
379 ], \
380 [$class: 'BooleanParameterDefinition', \
381 description: 'If true, jenkins also publishes results', \
382 name: 'Publish', \
383 defaultValue: false, \
384 ], \
385 [$class: 'BooleanParameterDefinition', \
386 description: 'If true, jenkins will not send emails', \
387 name: 'Silent', \
388 defaultValue: false, \
389 ], \
390 ],
391 ]])
392
393 final settings = new BuildSettings(params, env.BRANCH_NAME)
394
395 currentBuild.description = settings.DescShort
396 echo settings.DescLong
397
398 return settings
399}
400
401def build_stage(String name, Closure block ) {
402 StageName = name
403 echo " -------- ${StageName} -------- "
404 stage(name, block)
405}
406
407def notify_server(int wait) {
408 sh """curl --silent --show-error --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
409 return
410}
411
412def make_doc() {
413 def err = null
414 try {
415 sh 'make clean > /dev/null'
416 sh 'make > /dev/null 2>&1'
417 }
418 catch (Exception caughtError) {
419 err = caughtError //rethrow error later
420 sh 'cat *.log'
421 }
422 finally {
423 if (err) throw err // Must re-throw exception to propagate error
424 }
425}
Note: See TracBrowser for help on using the repository browser.