source: Jenkinsfile @ 4b82db3

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexer
Last change on this file since 4b82db3 was 4b82db3, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Groovy and Java interaction is weird

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