source: Jenkinsfile@ a336d46

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

Tentative to improve handling of git changes

  • 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 email(log_needed, Settings.IsSandbox)
67 }
68
69 echo 'Build Completed'
70
71 /* Must re-throw exception to propagate error */
72 if (err) {
73 throw err
74 }
75 }
76}
77
78//===========================================================================================================
79// Main compilation routines
80//===========================================================================================================
81def clean() {
82 build_stage('Cleanup') {
83 // clean the build by wipping the build directory
84 dir(BuildDir) {
85 deleteDir()
86 }
87 }
88}
89
90//Compilation script is done here but environnement set-up and error handling is done in main loop
91def checkout() {
92 build_stage('Checkout') {
93 //checkout the source code and clean the repo
94 final scmVars = checkout scm
95 Settings.GitNewRef = scmVars.GIT_COMMIT
96 Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
97
98 echo GitLogMessage()
99 }
100}
101
102def build() {
103 build_stage('Build') {
104 // Build outside of the src tree to ease cleaning
105 dir (BuildDir) {
106 //Configure the conpilation (Output is not relevant)
107 //Use the current directory as the installation target so nothing escapes the sandbox
108 //Also specify the compiler by hand
109 targets=""
110 if( Settings.RunAllTests ) {
111 targets="--with-target-hosts='host:debug,host:nodebug'"
112 } else {
113 targets="--with-target-hosts='host:debug'"
114 }
115
116 sh "${SrcDir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"
117
118 //Compile the project
119 sh 'make -j 8 --no-print-directory'
120 }
121 }
122}
123
124def test() {
125 build_stage('Test') {
126
127 dir (BuildDir) {
128 //Run the tests from the tests directory
129 if ( Settings.RunAllTests ) {
130 sh 'make --no-print-directory -C tests all-tests debug=yes'
131 sh 'make --no-print-directory -C tests all-tests debug=no '
132 }
133 else {
134 sh 'make --no-print-directory -C tests'
135 }
136 }
137 }
138}
139
140def benchmark() {
141 build_stage('Benchmark') {
142
143 if( !Settings.RunBenchmark ) return
144
145 dir (BuildDir) {
146 //Append bench results
147 sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${Settings.Architecture} | tee ${SrcDir}/bench.json"
148 }
149 }
150}
151
152def build_doc() {
153 build_stage('Documentation') {
154
155 if( !Settings.BuildDocumentation ) return
156
157 dir ('doc/user') {
158 make_doc()
159 }
160
161 dir ('doc/refrat') {
162 make_doc()
163 }
164 }
165}
166
167def publish() {
168 build_stage('Publish') {
169
170 if( !Settings.Publish ) return
171
172 //Then publish the results
173 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
174 }
175}
176
177//===========================================================================================================
178//Routine responsible of sending the email notification once the build is completed
179//===========================================================================================================
180def gitUpdate(String gitRefOldValue, String gitRefNewValue) {
181 def update = ""
182 sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG";
183 readFile('GIT_LOG').eachLine { rev ->
184 sh "git cat-file -t ${rev} > GIT_TYPE"
185 def type = readFile('GIT_TYPE')
186
187 update += " via ${rev} (${type})\n"
188 }
189 def rev = gitRefOldValue
190 sh "git cat-file -t ${rev} > GIT_TYPE"
191 def type = readFile('GIT_TYPE')
192
193 update += " from ${rev} (${type})\n"
194 return update
195}
196
197def gitLog(String gitRefOldValue, String gitRefNewValue) {
198 sh "git rev-list --format=short ${oldRef}...${newRef} > ${BuildDir}/GIT_LOG"
199 return readFile("${BuildDir}/GIT_LOG")
200}
201
202def gitDiff(String gitRefOldValue, String gitRefNewValue) {
203 sh "git diff --stat ${newRef} ${oldRef} > ${BuildDir}/GIT_DIFF"
204 return readFile("${BuildDir}/GIT_DIFF")
205}
206
207def GitLogMessage() {
208 if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
209
210 return """
211The branch ${env.BRANCH_NAME} has been updated.
212${gitUpdate(Settings.GitOldRef, Settings.GitNewRef)}
213
214Check console output at ${env.BUILD_URL} to view the results.
215
216- Status --------------------------------------------------------------
217
218BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}
219
220- Log -----------------------------------------------------------------
221${gitLog(Settings.GitOldRef, Settings.GitNewRef)}
222-----------------------------------------------------------------------
223Summary of changes:
224${gitDiff(Settings.GitOldRef, Settings.GitNewRef)}
225"""
226}
227
228//Standard build email notification
229def email(boolean log, boolean bIsSandbox) {
230 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
231 //Configurations for email format
232 echo 'Notifying users of result'
233
234 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
235 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
236 def email_body = """This is an automated email from the Jenkins build machine. It was
237generated because of a git hooks/post-receive script following
238a ref change which was pushed to the Cforall repository.
239""" + GitLogMessage()
240
241 def email_to = "cforall@lists.uwaterloo.ca"
242
243 if( Settings && !Settings.IsSandbox ) {
244 //send email notification
245 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
246 } else {
247 echo "Would send email to: ${email_to}"
248 echo "With title: ${email_subject}"
249 echo "Content: \n${email_body}"
250 }
251}
252
253//===========================================================================================================
254// Helper classes/variables/routines
255//===========================================================================================================
256//Description of a compiler (Must be serializable since pipelines are persistent)
257class CC_Desc implements Serializable {
258 public String cc_name
259 public String cpp_cc
260 public String cfa_cc
261
262 CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
263 this.cc_name = cc_name
264 this.cpp_cc = cpp_cc
265 this.cfa_cc = cfa_cc
266 }
267}
268
269//Description of an architecture (Must be serializable since pipelines are persistent)
270class Arch_Desc implements Serializable {
271 public String name
272 public String flags
273
274 Arch_Desc(String name, String flags) {
275 this.name = name
276 this.flags = flags
277 }
278}
279
280class BuildSettings implements Serializable {
281 public final CC_Desc Compiler
282 public final Arch_Desc Architecture
283 public final Boolean RunAllTests
284 public final Boolean RunBenchmark
285 public final Boolean BuildDocumentation
286 public final Boolean Publish
287 public final Boolean Silent
288 public final Boolean IsSandbox
289 public final String DescLong
290 public final String DescShort
291
292 public String GitNewRef
293 public String GitOldRef
294
295 BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
296 switch( param.Compiler ) {
297 case 'gcc-6':
298 this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
299 break
300 case 'gcc-5':
301 this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
302 break
303 case 'gcc-4.9':
304 this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
305 break
306 case 'clang':
307 this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
308 break
309 default :
310 error "Unhandled compiler : ${cc}"
311 }
312
313 switch( param.Architecture ) {
314 case 'x64':
315 this.Architecture = new Arch_Desc('x64', '--host=x86_64')
316 break
317 case 'x86':
318 this.Architecture = new Arch_Desc('x86', '--host=i386')
319 break
320 default :
321 error "Unhandled architecture : ${arch}"
322 }
323
324 this.RunAllTests = param.RunAllTests
325 this.RunBenchmark = param.RunBenchmark
326 this.BuildDocumentation = param.BuildDocumentation
327 this.Publish = param.Publish
328 this.Silent = param.Silent
329 this.IsSandbox = (branch == "jenkins-sandbox")
330
331 def full = param.RunAllTests ? " (Full)" : ""
332 this.DescShort = "${ this.Compiler.cc_name }:${ this.Architecture.name }${full}"
333
334 this.DescLong = """Compiler : ${ this.Compiler.cc_name } (${ this.Compiler.cpp_cc }/${ this.Compiler.cfa_cc })
335Architecture : ${ this.Architecture.name }
336Arc Flags : ${ this.Architecture.flags }
337Run All Tests : ${ this.RunAllTests.toString() }
338Run Benchmark : ${ this.RunBenchmark.toString() }
339Build Documentation : ${ this.BuildDocumentation.toString() }
340Publish : ${ this.Publish.toString() }
341Silent : ${ this.Silent.toString() }
342"""
343
344 this.GitNewRef = ''
345 this.GitOldRef = ''
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.