source: Jenkinsfile @ 952ee7a

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

more testing

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