source: Jenkinsfile@ 939fd39

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

Echo was in the wrong place

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