source: Jenkinsfile @ 89427de

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexerpthread-emulationqualifiedEnum
Last change on this file since 89427de was 89427de, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Typo lead to stupid unintelligeable exceptions

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