source: Jenkinsfile @ 94c9b810

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

I though classes where like java...

  • Property mode set to 100644
File size: 12.4 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        def compiler_from_params(cc) {
126                switch( cc ) {
127                        case 'gcc-6':
128                                return new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
129                        break
130                        case 'gcc-5':
131                                return new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
132                        break
133                        case 'gcc-4.9':
134                                return new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
135                        break
136                        case 'clang':
137                                return new CC_Desc('clang', 'clang++', 'gcc-6')
138                        break
139                        default :
140                                error "Unhandled compiler : ${cc}"
141                }
142        }
143
144        def architecture_from_params( arch ) {
145                switch( arch ) {
146                        case 'x64':
147                                return new Arch_Desc('x64', '--host=x86_64')
148                        break
149                        case 'x86':
150                                return new Arch_Desc('x86', '--host=i386')
151                        break
152                        default :
153                                error "Unhandled architecture : ${arch}"
154                }
155        }
156
157        BuildSettings(java.util.Collections$UnmodifiableMap param, java.util.TreeMap scmVars) {
158                this.Compiler         = compiler_from_params( param.Compiler )
159                this.Architecture       = architecture_from_params( param.Architecture )
160                this.RunAllTests        = param.RunAllTests
161                this.RunBenchmark       = param.RunBenchmark
162                this.BuildDocumentation = param.BuildDocumentation
163                this.Publish            = param.Publish
164                this.Silent             = param.Silent
165                this.IsSandbox          = scmVars.GIT_BRANCH == "jenkins-sandbox"
166                this.Branch             = scmVars.GIT_BRANCH
167                this.Commit             = scmVars.GIT_COMMIT
168                this.PrevCommit         = scmVars.GIT_PREVIOUS_COMMIT
169                this.RepoUrl            = scmVars.GIT_URL
170
171                def full = param.RunAllTests ? " (Full)" : ""
172                this.DescShort = "${ this.Compiler.cc_name }:${ this.Architecture.name }${full}"
173
174                this.DescLong """Compiler                : ${ this.Compiler.cc_name } (${ this.Compiler.cpp_cc }/${ this.Compiler.cfa_cc })
175Architecture            : ${ this.Architecture.name }
176Arc Flags               : ${ this.Architecture.flags }
177Run All Tests           : ${ this.RunAllTests.toString() }
178Run Benchmark           : ${ this.RunBenchmark.toString() }
179Build Documentation     : ${ this.BuildDocumentation.toString() }
180Publish                 : ${ this.Publish.toString() }
181Silent                  : ${ this.Silent.toString() }
182"""
183        }
184}
185
186def prepare_build() {
187        // prepare the properties
188        properties ([                                                                                                   \
189                [$class: 'ParametersDefinitionProperty',                                                                \
190                        parameterDefinitions: [                                                                         \
191                                [$class: 'ChoiceParameterDefinition',                                           \
192                                        description: 'Which compiler to use',                                   \
193                                        name: 'Compiler',                                                                       \
194                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
195                                        defaultValue: 'gcc-6',                                                          \
196                                ],                                                                                              \
197                                [$class: 'ChoiceParameterDefinition',                                           \
198                                        description: 'The target architecture',                                 \
199                                        name: 'Architecture',                                                           \
200                                        choices: 'x64\nx86',                                                            \
201                                        defaultValue: 'x64',                                                            \
202                                ],                                                                                              \
203                                [$class: 'BooleanParameterDefinition',                                                  \
204                                        description: 'If false, only the quick test suite is ran',              \
205                                        name: 'RunAllTests',                                                            \
206                                        defaultValue: false,                                                            \
207                                ],                                                                                              \
208                                [$class: 'BooleanParameterDefinition',                                                  \
209                                        description: 'If true, jenkins also runs benchmarks',           \
210                                        name: 'RunBenchmark',                                                           \
211                                        defaultValue: false,                                                            \
212                                ],                                                                                              \
213                                [$class: 'BooleanParameterDefinition',                                                  \
214                                        description: 'If true, jenkins also builds documentation',              \
215                                        name: 'BuildDocumentation',                                                     \
216                                        defaultValue: true,                                                             \
217                                ],                                                                                              \
218                                [$class: 'BooleanParameterDefinition',                                                  \
219                                        description: 'If true, jenkins also publishes results',                 \
220                                        name: 'Publish',                                                                        \
221                                        defaultValue: false,                                                            \
222                                ],                                                                                              \
223                                [$class: 'BooleanParameterDefinition',                                                  \
224                                        description: 'If true, jenkins will not send emails',           \
225                                        name: 'Silent',                                                                         \
226                                        defaultValue: false,                                                            \
227                                ],                                                                                              \
228                        ],
229                ]])
230
231        // Collect git information
232        final scmVars = checkout scm
233
234        final settings = new BuildSettings(params, scmVars)
235
236        currentBuild.description = settings.DescShort
237        echo                       settings.DescLong
238
239        return settings
240}
241
242def build_stage(String name, Closure block ) {
243        stage_name = name
244        stage(name, block)
245}
246
247def notify_server(int wait) {
248        sh """curl --silent --show-error --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
249        return
250}
251
252def make_doc() {
253        def err = null
254        try {
255                sh 'make clean > /dev/null'
256                sh 'make > /dev/null 2>&1'
257        }
258        catch (Exception caughtError) {
259                err = caughtError //rethrow error later
260                sh 'cat *.log'
261        }
262        finally {
263                if (err) throw err // Must re-throw exception to propagate error
264        }
265}
266
267//===========================================================================================================
268// Main compilation routines
269//===========================================================================================================
270def clean() {
271        build_stage('Cleanup') {
272                // clean the build by wipping the build directory
273                dir(builddir) {
274                        deleteDir()
275                }
276
277                //Clean all temporary files to make sure no artifacts of the previous build remain
278                sh 'git clean -fdqx'
279
280                //Reset the git repo so no local changes persist
281                sh 'git reset --hard'
282        }
283}
284
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
293def build() {
294        build_stage('Build') {
295                // Build outside of the src tree to ease cleaning
296                dir (builddir) {
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
300                        targets=""
301                        if( Settings.RunAllTests ) {
302                                targets="--with-target-hosts='host:debug,host:nodebug'"
303                        } else {
304                                targets="--with-target-hosts='host:debug'"
305                        }
306
307                        sh "${srcdir}/configure CXX=${Settings.Compiler.cpp_cc} ${Settings.Architecture.flags} ${targets} --with-backend-compiler=${Settings.Compiler.cfa_cc} --quiet"
308
309                        //Compile the project
310                        sh 'make -j 8 --no-print-directory'
311                }
312        }
313}
314
315def test() {
316        build_stage('Test') {
317
318                dir (builddir) {
319                        //Run the tests from the tests directory
320                        if ( Settings.RunAllTests ) {
321                                sh 'make --no-print-directory -C tests all-tests debug=yes'
322                                sh 'make --no-print-directory -C tests all-tests debug=no '
323                        }
324                        else {
325                                sh 'make --no-print-directory -C tests'
326                        }
327                }
328        }
329}
330
331def benchmark() {
332        build_stage('Benchmark') {
333
334                if( !Settings.RunBenchmark ) return
335
336                dir (builddir) {
337                        //Append bench results
338                        sh "make --no-print-directory -C benchmark jenkins githash=${gitRefNewValue} arch=${Settings.Architecture} | tee ${srcdir}/bench.json"
339                }
340        }
341}
342
343def build_doc() {
344        build_stage('Documentation') {
345
346                if( !Settings.BuildDocumentation ) return
347
348                dir ('doc/user') {
349                        make_doc()
350                }
351
352                dir ('doc/refrat') {
353                        make_doc()
354                }
355        }
356}
357
358def publish() {
359        build_stage('Publish') {
360
361                if( !Settings.Publish ) return
362
363                //Then publish the results
364                sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
365        }
366}
367
368//===========================================================================================================
369//Routine responsible of sending the email notification once the build is completed
370//===========================================================================================================
371def gitBranchUpdate(String gitRefOldValue, String gitRefNewValue) {
372        def update = ""
373        sh "git rev-list ${gitRefOldValue}..${gitRefNewValue} > GIT_LOG";
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
391//Standard build email notification
392def email(String status, boolean log, boolean bIsSandbox) {
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
397        def gitLog = 'Error retrieving git logs'
398        def gitDiff = 'Error retrieving git diff'
399        def gitUpdate = 'Error retrieving update'
400
401        try {
402                gitUpdate = gitBranchUpdate(Settings.PrevCommit, Settings.Commit)
403
404                sh "git rev-list --format=short ${Settings.PrevCommit}...${Settings.Commit} > GIT_LOG"
405                gitLog = readFile('GIT_LOG')
406
407                sh "git diff --stat ${Settings.Commit} ${Settings.PrevCommit} > GIT_DIFF"
408                gitDiff = readFile('GIT_DIFF')
409        }
410        catch (Exception error) {
411                echo error.toString()
412                echo error.getMessage()
413        }
414
415        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${status}] - branch ${env.BRANCH_NAME}"
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".
420
421The branch ${env.BRANCH_NAME} has been updated.
422${gitUpdate}
423
424Check console output at ${env.BUILD_URL} to view the results.
425
426- Status --------------------------------------------------------------
427
428BUILD# ${env.BUILD_NUMBER} - ${status}
429
430- Log -----------------------------------------------------------------
431${gitLog}
432-----------------------------------------------------------------------
433Summary of changes:
434${gitDiff}
435"""
436
437        def email_to = "cforall@lists.uwaterloo.ca"
438
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        }
447}
Note: See TracBrowser for help on using the repository browser.