source: Jenkinsfile @ cbef27b

ADTarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since cbef27b was 3898392, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Moved group globals into publish function

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