source: Jenkinsfile @ 5afeab9

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

Now using global settings file

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