source: Jenkinsfile@ c431138

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

Globals in groovy are annoying

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