source: Jenkinsfile@ 97144e2

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

Screw functions let's just inline the code

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