source: Jenkinsfile@ 5afeab9

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

Now using global settings file

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