source: Jenkinsfile@ b98313c

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 stuck-waitfor-destruct
Last change on this file since b98313c was b98313c, checked in by Thierry Delisle <tdelisle@…>, 8 years ago

Clean now handled in checkout and started looking into currentBuild changeSets

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