source: Jenkinsfile @ 143e6f3

arm-ehjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since 143e6f3 was 143e6f3, checked in by Thierry Delisle <tdelisle@…>, 2 years ago

Trying out archive build failures

  • Property mode set to 100644
File size: 14.8 KB
Line 
1#!groovy
2
3import groovy.transform.Field
4
5// For skipping stages
6import org.jenkinsci.plugins.pipeline.modeldefinition.Utils
7
8//===========================================================================================================
9// Main loop of the compilation
10//===========================================================================================================
11
12node('master') {
13        // Globals
14        BuildDir  = pwd tmp: true
15        SrcDir    = pwd tmp: false
16        Settings  = null
17        StageName = ''
18
19        // Local variables
20        def err = null
21        def log_needed = false
22
23        currentBuild.result = "SUCCESS"
24
25        try {
26                //Wrap build to add timestamp to command line
27                wrap([$class: 'TimestamperBuildWrapper']) {
28
29                        Settings = prepare_build()
30
31                        node(Settings.Architecture.node) {
32                                BuildDir  = pwd tmp: true
33                                SrcDir    = pwd tmp: false
34
35                                clean()
36
37                                checkout()
38
39                                build()
40
41                                test()
42
43                                benchmark()
44
45                                build_doc()
46
47                                publish()
48                        }
49
50                        // Update the build directories when exiting the node
51                        BuildDir  = pwd tmp: true
52                        SrcDir    = pwd tmp: false
53                }
54        }
55
56        //If an exception is caught we need to change the status and remember to
57        //attach the build log to the email
58        catch (Exception caughtError) {
59                //rethrow error later
60                err = caughtError
61
62                echo err.toString()
63
64                //An error has occured, the build log is relevent
65                log_needed = true
66
67                //Store the result of the build log
68                currentBuild.result = "${StageName} FAILURE".trim()
69        }
70
71        finally {
72                //Send email with final results if this is not a full build
73                email(log_needed)
74
75                echo 'Build Completed'
76
77                /* Must re-throw exception to propagate error */
78                if (err) {
79                        throw err
80                }
81        }
82}
83//===========================================================================================================
84// Main compilation routines
85//===========================================================================================================
86def clean() {
87        build_stage('Cleanup', true) {
88                // clean the build by wipping the build directory
89                dir(BuildDir) {
90                        deleteDir()
91                }
92        }
93}
94
95//Compilation script is done here but environnement set-up and error handling is done in main loop
96def checkout() {
97        build_stage('Checkout', true) {
98                //checkout the source code and clean the repo
99                final scmVars = checkout scm
100                Settings.GitNewRef = scmVars.GIT_COMMIT
101                Settings.GitOldRef = scmVars.GIT_PREVIOUS_COMMIT
102
103                echo GitLogMessage()
104        }
105}
106
107def build() {
108        debug = true
109        release = Settings.RunAllTests || Settings.RunBenchmark
110        build_stage('Build : configure', true) {
111                // Build outside of the src tree to ease cleaning
112                dir (BuildDir) {
113                        //Configure the conpilation (Output is not relevant)
114                        //Use the current directory as the installation target so nothing escapes the sandbox
115                        //Also specify the compiler by hand
116                        targets=""
117                        if( Settings.RunAllTests || Settings.RunBenchmark ) {
118                                targets="--with-target-hosts='host:debug,host:nodebug'"
119                        } else {
120                                targets="--with-target-hosts='host:debug'"
121                        }
122
123                        sh "${SrcDir}/configure CXX=${Settings.Compiler.CXX} CC=${Settings.Compiler.CC} ${Settings.Architecture.flags} ${targets} --quiet"
124
125                        // Configure libcfa
126                        sh 'make -j 8 --no-print-directory configure-libcfa'
127                }
128        }
129
130        build_stage('Build : cfa-cpp', true) {
131                // Build outside of the src tree to ease cleaning
132                dir (BuildDir) {
133                        // Build driver
134                        sh 'make -j 8 --no-print-directory -C driver'
135
136                        // Build translator
137                        sh 'make -j 8 --no-print-directory -C src'
138                }
139        }
140
141        build_stage('Build : libcfa(debug)', debug) {
142                // Build outside of the src tree to ease cleaning
143                dir (BuildDir) {
144                        sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-debug"
145                }
146        }
147
148        build_stage('Build : libcfa(nodebug)', release) {
149                // Build outside of the src tree to ease cleaning
150                dir (BuildDir) {
151                        sh "make -j 8 --no-print-directory -C libcfa/${Settings.Architecture.name}-nodebug"
152                }
153        }
154}
155
156def test() {
157        build_stage('Test: short', !Settings.RunAllTests) {
158                dir (BuildDir) {
159                        //Run the tests from the tests directory
160                        sh 'make --no-print-directory -C tests'
161                }
162        }
163
164        build_stage('Test: full', Settings.RunAllTests) {
165                dir (BuildDir) {
166                        //Run the tests from the tests directory
167                        sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=yes archiveerrors=${BuildDir}/tests/crashes/debug"""
168                        sh """make --no-print-directory -C tests timeouts="--timeout=600 --global-timeout=14400" all-tests debug=no  archiveerrors=${BuildDir}/tests/crashes/nodebug"""
169
170                        if(fileExists "${BuildDir}/tests/crashes") {
171                                archiveArtifacts artifacts: "${BuildDir}/tests/crashes", fingerprint: true
172                        }
173                }
174        }
175}
176
177def benchmark() {
178        build_stage('Benchmark', Settings.RunBenchmark) {
179                dir (BuildDir) {
180                        //Append bench results
181                        sh "make --no-print-directory -C benchmark jenkins arch=${Settings.Architecture.name}"
182                }
183        }
184}
185
186def build_doc() {
187        build_stage('Documentation', Settings.BuildDocumentation) {
188                dir ('doc/user') {
189                        make_doc()
190                }
191
192                dir ('doc/refrat') {
193                        make_doc()
194                }
195        }
196}
197
198def publish() {
199        build_stage('Publish', true) {
200
201                if( Settings.Publish && !Settings.RunBenchmark ) { echo 'No results to publish!!!' }
202
203                def groupCompile = new PlotGroup('Compilation', 'duration (s) - lower is better', true)
204                def groupConcurrency = new PlotGroup('Concurrency', 'duration (n) - lower is better', false)
205
206                //Then publish the results
207                do_plot(Settings.RunBenchmark && Settings.Publish, 'compile'       , groupCompile    , false, 'Compilation')
208                do_plot(Settings.RunBenchmark && Settings.Publish, 'compile.diff'  , groupCompile    , true , 'Compilation (relative)')
209                do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch'     , groupConcurrency, false, 'Context Switching')
210                do_plot(Settings.RunBenchmark && Settings.Publish, 'ctxswitch.diff', groupConcurrency, true , 'Context Switching (relative)')
211                do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex'         , groupConcurrency, false, 'Mutual Exclusion')
212                do_plot(Settings.RunBenchmark && Settings.Publish, 'mutex.diff'    , groupConcurrency, true , 'Mutual Exclusion (relative)')
213                do_plot(Settings.RunBenchmark && Settings.Publish, 'signal'        , groupConcurrency, false, 'Internal and External Scheduling')
214                do_plot(Settings.RunBenchmark && Settings.Publish, 'signal.diff'   , groupConcurrency, true , 'Internal and External Scheduling (relative)')
215        }
216}
217
218//===========================================================================================================
219//Routine responsible of sending the email notification once the build is completed
220//===========================================================================================================
221def GitLogMessage() {
222        if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
223
224        sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
225
226        def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
227        def gitLog    = readFile("${BuildDir}/GIT_LOG")
228        def gitDiff   = readFile("${BuildDir}/GIT_DIFF")
229
230        return """
231<pre>
232The branch ${env.BRANCH_NAME} has been updated.
233${gitUpdate}
234</pre>
235
236<p>Check console output at ${env.BUILD_URL} to view the results.</p>
237
238<p>- Status --------------------------------------------------------------</p>
239
240<p>BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}</p>
241
242<p>- Log -----------------------------------------------------------------</p>
243
244<pre>
245${gitLog}
246</pre>
247
248<p>-----------------------------------------------------------------------</p>
249<pre>
250Summary of changes:
251${gitDiff}
252</pre>
253"""
254}
255
256//Standard build email notification
257def email(boolean log) {
258        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
259        //Configurations for email format
260        echo 'Notifying users of result'
261
262        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
263        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
264        def email_body = """<p>This is an automated email from the Jenkins build machine. It was
265generated because of a git hooks/post-receive script following
266a ref change which was pushed to the C\u2200 repository.</p>
267""" + GitLogMessage()
268
269        def email_to = !Settings.IsSandbox ? "cforall@lists.uwaterloo.ca" : "tdelisle@uwaterloo.ca"
270
271        if( Settings && !Settings.Silent ) {
272                //send email notification
273                emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
274        } else {
275                echo "Would send email to: ${email_to}"
276                echo "With title: ${email_subject}"
277                echo "Content: \n${email_body}"
278        }
279}
280
281//===========================================================================================================
282// Helper classes/variables/routines
283//===========================================================================================================
284//Description of a compiler (Must be serializable since pipelines are persistent)
285class CC_Desc implements Serializable {
286        public String name
287        public String CXX
288        public String CC
289
290        CC_Desc(String name, String CXX, String CC) {
291                this.name = name
292                this.CXX = CXX
293                this.CC = CC
294        }
295}
296
297//Description of an architecture (Must be serializable since pipelines are persistent)
298class Arch_Desc implements Serializable {
299        public String name
300        public String flags
301        public String node
302
303        Arch_Desc(String name, String flags, String node) {
304                this.name  = name
305                this.flags = flags
306                this.node  = node
307        }
308}
309
310class BuildSettings implements Serializable {
311        public final CC_Desc Compiler
312        public final Arch_Desc Architecture
313        public final Boolean RunAllTests
314        public final Boolean RunBenchmark
315        public final Boolean BuildDocumentation
316        public final Boolean Publish
317        public final Boolean Silent
318        public final Boolean IsSandbox
319        public final String DescLong
320        public final String DescShort
321
322        public String GitNewRef
323        public String GitOldRef
324
325        BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
326                switch( param.Compiler ) {
327                        case 'gcc-6':
328                                this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
329                        break
330                        case 'gcc-5':
331                                this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
332                        break
333                        case 'gcc-4.9':
334                                this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
335                        break
336                        case 'clang':
337                                this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
338                        break
339                        default :
340                                error "Unhandled compiler : ${cc}"
341                }
342
343                switch( param.Architecture ) {
344                        case 'x64':
345                                this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
346                        break
347                        case 'x86':
348                                this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
349                        break
350                        default :
351                                error "Unhandled architecture : ${arch}"
352                }
353
354                this.IsSandbox          = (branch == "jenkins-sandbox")
355                this.RunAllTests        = param.RunAllTests
356                this.RunBenchmark       = param.RunBenchmark
357                this.BuildDocumentation = param.BuildDocumentation
358                this.Publish            = param.Publish
359                this.Silent             = param.Silent
360
361                def full = param.RunAllTests ? " (Full)" : ""
362                this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
363
364                this.DescLong = """Compiler              : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
365Architecture            : ${ this.Architecture.name }
366Arc Flags               : ${ this.Architecture.flags }
367Run All Tests           : ${ this.RunAllTests.toString() }
368Run Benchmark           : ${ this.RunBenchmark.toString() }
369Build Documentation     : ${ this.BuildDocumentation.toString() }
370Publish                 : ${ this.Publish.toString() }
371Silent                  : ${ this.Silent.toString() }
372"""
373
374                this.GitNewRef = ''
375                this.GitOldRef = ''
376        }
377}
378
379class PlotGroup implements Serializable {
380        public String name
381        public String unit
382        public boolean log
383
384        PlotGroup(String name, String unit, boolean log) {
385                this.name = name
386                this.unit = unit
387                this.log = log
388        }
389}
390
391def prepare_build() {
392        // prepare the properties
393        properties ([                                                                                                   \
394                [$class: 'ParametersDefinitionProperty',                                                                \
395                        parameterDefinitions: [                                                                         \
396                                [$class: 'ChoiceParameterDefinition',                                           \
397                                        description: 'Which compiler to use',                                   \
398                                        name: 'Compiler',                                                                       \
399                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
400                                        defaultValue: 'gcc-6',                                                          \
401                                ],                                                                                              \
402                                [$class: 'ChoiceParameterDefinition',                                           \
403                                        description: 'The target architecture',                                 \
404                                        name: 'Architecture',                                                           \
405                                        choices: 'x64\nx86',                                                            \
406                                        defaultValue: 'x64',                                                            \
407                                ],                                                                                              \
408                                [$class: 'BooleanParameterDefinition',                                                  \
409                                        description: 'If false, only the quick test suite is ran',              \
410                                        name: 'RunAllTests',                                                            \
411                                        defaultValue: false,                                                            \
412                                ],                                                                                              \
413                                [$class: 'BooleanParameterDefinition',                                                  \
414                                        description: 'If true, jenkins also runs benchmarks',           \
415                                        name: 'RunBenchmark',                                                           \
416                                        defaultValue: false,                                                            \
417                                ],                                                                                              \
418                                [$class: 'BooleanParameterDefinition',                                                  \
419                                        description: 'If true, jenkins also builds documentation',              \
420                                        name: 'BuildDocumentation',                                                     \
421                                        defaultValue: true,                                                             \
422                                ],                                                                                              \
423                                [$class: 'BooleanParameterDefinition',                                                  \
424                                        description: 'If true, jenkins also publishes results',                 \
425                                        name: 'Publish',                                                                        \
426                                        defaultValue: false,                                                            \
427                                ],                                                                                              \
428                                [$class: 'BooleanParameterDefinition',                                                  \
429                                        description: 'If true, jenkins will not send emails',           \
430                                        name: 'Silent',                                                                         \
431                                        defaultValue: false,                                                            \
432                                ],                                                                                              \
433                        ],
434                ]])
435
436        // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
437        checkout scm
438
439        final settings = new BuildSettings(params, env.BRANCH_NAME)
440
441        currentBuild.description = settings.DescShort
442        echo                       settings.DescLong
443
444        return settings
445}
446
447def build_stage(String name, boolean run, Closure block ) {
448        StageName = name
449        echo " -------- ${StageName} -------- "
450        if(run) {
451                stage(name, block)
452        } else {
453                stage(name) { Utils.markStageSkippedForConditional(STAGE_NAME) }
454        }
455}
456
457def make_doc() {
458        def err = null
459        try {
460                sh 'make clean > /dev/null'
461                sh 'make > /dev/null 2>&1'
462        }
463        catch (Exception caughtError) {
464                err = caughtError //rethrow error later
465                sh 'cat build/*.log'
466        }
467        finally {
468                if (err) throw err // Must re-throw exception to propagate error
469        }
470}
471
472def do_plot(boolean new_data, String file, PlotGroup group, boolean relative, String title) {
473
474        if(new_data) {
475                echo "Publishing new data"
476        }
477
478        def series = new_data ? [[
479                                file: "${file}.csv",
480                                exclusionValues: '',
481                                displayTableFlag: false,
482                                inclusionFlag: 'OFF',
483                                url: ''
484                        ]] : [];
485
486        echo "file is ${BuildDir}/benchmark/${file}.csv, group ${group}, title ${title}"
487        dir("${BuildDir}/benchmark/") {
488                plot csvFileName: "cforall-${env.BRANCH_NAME}-${file}.csv",
489                        csvSeries: series,
490                        group: "${group.name}",
491                        title: "${title}",
492                        style: 'lineSimple',
493                        exclZero: false,
494                        keepRecords: false,
495                        logarithmic: !relative && group.log,
496                        numBuilds: '120',
497                        useDescr: true,
498                        yaxis: group.unit,
499                        yaxisMaximum: '',
500                        yaxisMinimum: ''
501        }
502}
Note: See TracBrowser for help on using the repository browser.