source: Jenkinsfile @ f15fe0a

arm-ehcleanup-dtorsjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since f15fe0a was f15fe0a, checked in by tdelisle <tdelisle@…>, 3 years ago

Jenkins benchmarks updated to use plot plugin

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