source: Jenkinsfile @ 490cb3c

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

Some improvements on plots to be correct for both fine grain concurrency and compilation

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