source: Jenkinsfile@ 1947795

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

Move print of changeset to after 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 // 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 echo "${currentBuild.changeSets}"
98 }
99}
100
101def build() {
102 build_stage('Build') {
103 // Build outside of the src tree to ease cleaning
104 dir (BuildDir) {
105 //Configure the conpilation (Output is not relevant)
106 //Use the current directory as the installation target so nothing escapes the sandbox
107 //Also specify the compiler by hand
108 targets=""
109 if( Settings.RunAllTests ) {
110 targets="--with-target-hosts='host:debug,host:nodebug'"
111 } else {
112 targets="--with-target-hosts='host:debug'"
113 }
114
115 sh "${SrcDir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"
116
117 //Compile the project
118 sh 'make -j 8 --no-print-directory'
119 }
120 }
121}
122
123def test() {
124 build_stage('Test') {
125
126 dir (BuildDir) {
127 //Run the tests from the tests directory
128 if ( Settings.RunAllTests ) {
129 sh 'make --no-print-directory -C tests all-tests debug=yes'
130 sh 'make --no-print-directory -C tests all-tests debug=no '
131 }
132 else {
133 sh 'make --no-print-directory -C tests'
134 }
135 }
136 }
137}
138
139def benchmark() {
140 build_stage('Benchmark') {
141
142 if( !Settings.RunBenchmark ) return
143
144 dir (BuildDir) {
145 //Append bench results
146 sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${Settings.Architecture} | tee ${SrcDir}/bench.json"
147 }
148 }
149}
150
151def build_doc() {
152 build_stage('Documentation') {
153
154 if( !Settings.BuildDocumentation ) return
155
156 dir ('doc/user') {
157 make_doc()
158 }
159
160 dir ('doc/refrat') {
161 make_doc()
162 }
163 }
164}
165
166def publish() {
167 build_stage('Publish') {
168
169 if( !Settings.Publish ) return
170
171 //Then publish the results
172 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
173 }
174}
175
176//===========================================================================================================
177//Routine responsible of sending the email notification once the build is completed
178//===========================================================================================================
179def gitBranchUpdate(String gitRefOldValue, String gitRefNewValue) {
180 def update = ""
181 sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG";
182 readFile('GIT_LOG').eachLine { rev ->
183 sh "git cat-file -t ${rev} > GIT_TYPE"
184 def type = readFile('GIT_TYPE')
185
186 update += " via ${rev} (${type})\n"
187 }
188 def rev = gitRefOldValue
189 sh "git cat-file -t ${rev} > GIT_TYPE"
190 def type = readFile('GIT_TYPE')
191
192 update += " from ${rev} (${type})\n"
193 return update
194
195 def output=readFile('result').trim()
196 echo "output=$output";
197}
198
199//Standard build email notification
200def email(String status, boolean log, boolean bIsSandbox) {
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( Settings && !Settings.IsSandbox ) {
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.