source: Jenkinsfile@ 3a9aceb

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

Removed first unnecessary checkout

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