source: Jenkinsfile@ a8a7612

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

Since incremental builds have been quite painful in jenkins and we probably should avoid them in the first place for our build machine, Jenkins now disables dependency tracking all together when configuring

  • Property mode set to 100644
File size: 10.3 KB
Line 
1#!groovy
2
3//===========================================================================================================
4// Main loop of the compilation
5//===========================================================================================================
6node ('master'){
7
8 boolean bIsSandbox = env.BRANCH_NAME == "jenkins-sandbox"
9 def err = null
10 def log_needed = false
11
12 stage_name = ''
13
14 compiler = null
15 arch_name = ''
16 architecture = ''
17
18 do_alltests = false
19 do_benchmark = false
20 do_doc = false
21 do_publish = false
22 do_sendemail = true
23
24 currentBuild.result = "SUCCESS"
25
26 try {
27 //Wrap build to add timestamp to command line
28 wrap([$class: 'TimestamperBuildWrapper']) {
29
30 notify_server(0)
31
32 prepare_build()
33
34 checkout()
35
36 notify_server(0)
37
38 build()
39
40 test()
41
42 benchmark()
43
44 clean()
45
46 build_doc()
47
48 publish()
49
50 notify_server(45)
51 }
52 }
53
54 //If an exception is caught we need to change the status and remember to
55 //attach the build log to the email
56 catch (Exception caughtError) {
57 //rethrow error later
58 err = caughtError
59
60 //An error has occured, the build log is relevent
61 log_needed = true
62
63 //Store the result of the build log
64 currentBuild.result = "${stage_name} FAILURE".trim()
65 }
66
67 finally {
68 //Send email with final results if this is not a full build
69 if( do_sendemail && !bIsSandbox ) {
70 echo 'Notifying users of result'
71 email(currentBuild.result, log_needed)
72 }
73
74 echo 'Build Completed'
75
76 /* Must re-throw exception to propagate error */
77 if (err) {
78 throw err
79 }
80 }
81}
82
83//===========================================================================================================
84// Helper classes/variables/routines
85//===========================================================================================================
86//Helper routine to collect information about the git history
87def collect_git_info() {
88
89 checkout scm
90
91 //create the temporary output directory in case it doesn't already exist
92 def out_dir = pwd tmp: true
93 sh "mkdir -p ${out_dir}"
94
95 //parse git logs to find what changed
96 gitRefName = env.BRANCH_NAME
97 sh "git reflog > ${out_dir}/GIT_COMMIT"
98 git_reflog = readFile("${out_dir}/GIT_COMMIT")
99 gitRefOldValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][1]
100 gitRefNewValue = (git_reflog =~ /moving from (.+) to (.+)/)[0][2]
101}
102
103def prepare_build() {
104 properties ([ \
105 [$class: 'ParametersDefinitionProperty', \
106 parameterDefinitions: [ \
107 [$class: 'ChoiceParameterDefinition', \
108 description: 'Which compiler to use', \
109 name: 'pCompiler', \
110 choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang', \
111 defaultValue: 'gcc-6', \
112 ], \
113 [$class: 'ChoiceParameterDefinition', \
114 description: 'The target architecture', \
115 name: 'pArchitecture', \
116 choices: 'x64\nx86', \
117 defaultValue: 'x64', \
118 ], \
119 [$class: 'BooleanParameterDefinition', \
120 description: 'If false, only the quick test suite is ran', \
121 name: 'pRunAllTests', \
122 defaultValue: false, \
123 ], \
124 [$class: 'BooleanParameterDefinition', \
125 description: 'If true, jenkins also runs benchmarks', \
126 name: 'pRunBenchmark', \
127 defaultValue: true, \
128 ], \
129 [$class: 'BooleanParameterDefinition', \
130 description: 'If true, jenkins also builds documentation', \
131 name: 'pBuildDocumentation', \
132 defaultValue: true, \
133 ], \
134 [$class: 'BooleanParameterDefinition', \
135 description: 'If true, jenkins also publishes results', \
136 name: 'pPublish', \
137 defaultValue: false, \
138 ], \
139 [$class: 'BooleanParameterDefinition', \
140 description: 'If true, jenkins will not send emails', \
141 name: 'pSilent', \
142 defaultValue: false, \
143 ], \
144 ],
145 ]])
146
147 compiler = compiler_from_params( pCompiler )
148 arch_name = pArchitecture
149 architecture = architecture_from_params( arch_name )
150
151 do_alltests = (pRunAllTests == 'true')
152 do_benchmark = (pRunBenchmark == 'true')
153 do_doc = (pBuildDocumentation == 'true')
154 do_publish = (pPublish == 'true')
155 do_sendemail = ! (pSilent == 'true')
156
157 echo """Compiler : ${compiler.cc_name} (${compiler.cpp_cc}/${compiler.cfa_cc})
158Architecture : ${arch_name}
159Arc Flags : ${architecture}
160Run All Tests : ${ pRunAllTests.toString() }
161Run Benchmark : ${ pRunBenchmark.toString() }
162Build Documentation : ${ pBuildDocumentation.toString() }
163Publish : ${ pPublish.toString() }
164Silent : ${ pSilent.toString() }
165"""
166
167 collect_git_info()
168}
169
170def build_stage(String name, Closure block ) {
171 stage_name = name
172 stage(name, block)
173}
174
175def notify_server(int wait) {
176 sh """curl --silent --show-error --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
177 return
178}
179
180def make_doc() {
181 def err = null
182 try {
183 sh 'make clean > /dev/null'
184 sh 'make > /dev/null 2>&1'
185 }
186 catch (Exception caughtError) {
187 err = caughtError //rethrow error later
188 sh 'cat *.log'
189 }
190 finally {
191 if (err) throw err // Must re-throw exception to propagate error
192 }
193}
194
195//Description of a compiler (Must be serializable since pipelines are persistent)
196class CC_Desc implements Serializable {
197 public String cc_name
198 public String cpp_cc
199 public String cfa_cc
200
201 CC_Desc(String cc_name, String cpp_cc, String cfa_cc) {
202 this.cc_name = cc_name
203 this.cpp_cc = cpp_cc
204 this.cfa_cc = cfa_cc
205 }
206}
207
208def compiler_from_params(cc) {
209 switch( cc ) {
210 case 'gcc-6':
211 return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
212 break
213 case 'gcc-5':
214 return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
215 break
216 case 'gcc-4.9':
217 return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
218 break
219 case 'clang':
220 return new CC_Desc('clang', 'clang++', 'gcc-6')
221 break
222 default :
223 error "Unhandled compiler : ${cc}"
224 }
225}
226
227def architecture_from_params( arch ) {
228 switch( arch ) {
229 case 'x64':
230 return '--host=x86_64'
231 break
232 case 'x86':
233 return '--host=i386'
234 break
235 default :
236 error "Unhandled architecture : ${arch}"
237 }
238}
239
240//===========================================================================================================
241// Main compilation routines
242//===========================================================================================================
243//Compilation script is done here but environnement set-up and error handling is done in main loop
244def checkout() {
245 build_stage('Checkout') {
246 //checkout the source code and clean the repo
247 checkout scm
248
249 //Clean all temporary files to make sure no artifacts of the previous build remain
250 sh 'git clean -fdqx'
251
252 //Reset the git repo so no local changes persist
253 sh 'git reset --hard'
254 }
255}
256
257def build() {
258 build_stage('Build') {
259
260 def install_dir = pwd tmp: true
261
262 // Build outside of the src tree to ease cleaning
263 sh "mkdir -p build"
264 dir ('build') {
265 //Configure the conpilation (Output is not relevant)
266 //Use the current directory as the installation target so nothing escapes the sandbox
267 //Also specify the compiler by hand
268 sh "../configure CXX=${compiler.cpp_cc} ${architecture} --with-backend-compiler=${compiler.cfa_cc} --prefix=${install_dir} --enable-silent-rules --quiet --disable-dependency-tracking"
269
270 //Compile the project
271 sh 'make -j 8 --no-print-directory'
272 }
273 }
274}
275
276def test() {
277 build_stage('Test') {
278
279 //Run the tests from the tests directory
280 if ( do_alltests ) {
281 sh 'make -C build/src/tests all-tests debug=yes --no-print-directory'
282 sh 'make -C build/src/tests all-tests debug=no --no-print-directory'
283 }
284 else {
285 sh 'make -C build/src/tests --no-print-directory'
286 }
287 }
288}
289
290def benchmark() {
291 build_stage('Benchmark') {
292
293 if( !do_benchmark ) return
294
295 //Append bench results
296 sh 'make -C build/src/benchmark --no-print-directory jenkins githash=' + gitRefNewValue + ' arch=' + arch_name + ' | tee bench.json'
297 }
298}
299
300def clean() {
301 build_stage('Cleanup') {
302 // clean the build by wipping the build directory
303 sh 'rm -rf build'
304 }
305}
306
307def build_doc() {
308 build_stage('Documentation') {
309
310 if( !do_doc ) return
311
312 dir ('doc/user') {
313 make_doc()
314 }
315
316 dir ('doc/refrat') {
317 make_doc()
318 }
319 }
320}
321
322def publish() {
323 build_stage('Publish') {
324
325 if( !do_publish ) return
326
327 //Then publish the results
328 sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
329 }
330}
331
332//===========================================================================================================
333//Routine responsible of sending the email notification once the build is completed
334//===========================================================================================================
335//Standard build email notification
336def email(String status, boolean log) {
337 //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
338 //Configurations for email format
339 def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
340
341 def gitLog = 'Error retrieving git logs'
342 def gitDiff = 'Error retrieving git diff'
343
344 try {
345
346 sh "git rev-list --format=short ${gitRefOldValue}...${gitRefNewValue} > GIT_LOG"
347 gitLog = readFile('GIT_LOG')
348
349 sh "git diff --stat ${gitRefNewValue} ${gitRefOldValue} > GIT_DIFF"
350 gitDiff = readFile('GIT_DIFF')
351 }
352 catch (Exception error) {}
353
354 def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
355 def email_body = """This is an automated email from the Jenkins build machine. It was
356generated because of a git hooks/post-receive script following
357a ref change was pushed to the repository containing
358the project "UNNAMED PROJECT".
359
360The branch ${env.BRANCH_NAME} has been updated.
361 via ${gitRefOldValue} (commit)
362 from ${gitRefNewValue} (commit)
363
364Check console output at ${env.BUILD_URL} to view the results.
365
366- Status --------------------------------------------------------------
367
368BUILD# ${env.BUILD_NUMBER} - ${status}
369
370- Log -----------------------------------------------------------------
371${gitLog}
372-----------------------------------------------------------------------
373Summary of changes:
374${gitDiff}
375"""
376
377 def email_to = "cforall@lists.uwaterloo.ca"
378
379 //send email notification
380 emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
381}
Note: See TracBrowser for help on using the repository browser.