source: Jenkinsfile @ 8f99233

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexerpthread-emulationqualifiedEnum
Last change on this file since 8f99233 was 8f99233, checked in by Thierry Delisle <tdelisle@…>, 6 years ago

Second attempt at pipefail using an external script. closes #110

  • Property mode set to 100644
File size: 11.7 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 "${SrcDir}/jenkins.sh ${GitNewRef} ${Architecture} ${BuildDir}/bench.json"
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
180                //Then publish the results
181                sh 'curl --silent --show-error -H \'Content-Type: application/json\' --data @${BuildDir}/bench.json https://cforall.uwaterloo.ca:8082/jenkins/publish > /dev/null || true'
182        }
183}
184
185//===========================================================================================================
186//Routine responsible of sending the email notification once the build is completed
187//===========================================================================================================
188def GitLogMessage() {
189        if (!Settings || !Settings.GitOldRef || !Settings.GitNewRef) return "\nERROR retrieveing git information!\n"
190
191        sh "${SrcDir}/tools/PrettyGitLogs.sh ${SrcDir} ${BuildDir} ${Settings.GitOldRef} ${Settings.GitNewRef}"
192
193        def gitUpdate = readFile("${BuildDir}/GIT_UPDATE")
194        def gitLog    = readFile("${BuildDir}/GIT_LOG")
195        def gitDiff   = readFile("${BuildDir}/GIT_DIFF")
196
197        return """
198The branch ${env.BRANCH_NAME} has been updated.
199${gitUpdate}
200
201Check console output at ${env.BUILD_URL} to view the results.
202
203- Status --------------------------------------------------------------
204
205BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}
206
207- Log -----------------------------------------------------------------
208${gitLog}
209-----------------------------------------------------------------------
210Summary of changes:
211${gitDiff}
212"""
213}
214
215//Standard build email notification
216def email(boolean log, boolean bIsSandbox) {
217        //Since tokenizer doesn't work, figure stuff out from the environnement variables and command line
218        //Configurations for email format
219        echo 'Notifying users of result'
220
221        def project_name = (env.JOB_NAME =~ /(.+)\/.+/)[0][1].toLowerCase()
222        def email_subject = "[${project_name} git][BUILD# ${env.BUILD_NUMBER} - ${currentBuild.result}] - branch ${env.BRANCH_NAME}"
223        def email_body = """This is an automated email from the Jenkins build machine. It was
224generated because of a git hooks/post-receive script following
225a ref change which was pushed to the Cforall repository.
226""" + GitLogMessage()
227
228        def email_to = "cforall@lists.uwaterloo.ca"
229
230        if( Settings && !Settings.IsSandbox ) {
231                //send email notification
232                emailext body: email_body, subject: email_subject, to: email_to, attachLog: log
233        } else {
234                echo "Would send email to: ${email_to}"
235                echo "With title: ${email_subject}"
236                echo "Content: \n${email_body}"
237        }
238}
239
240//===========================================================================================================
241// Helper classes/variables/routines
242//===========================================================================================================
243//Description of a compiler (Must be serializable since pipelines are persistent)
244class CC_Desc implements Serializable {
245        public String name
246        public String CXX
247        public String CC
248
249        CC_Desc(String name, String CXX, String CC) {
250                this.name = name
251                this.CXX = CXX
252                this.CC = CC
253        }
254}
255
256//Description of an architecture (Must be serializable since pipelines are persistent)
257class Arch_Desc implements Serializable {
258        public String name
259        public String flags
260        public String node
261
262        Arch_Desc(String name, String flags, String node) {
263                this.name  = name
264                this.flags = flags
265                this.node  = node
266        }
267}
268
269class BuildSettings implements Serializable {
270        public final CC_Desc Compiler
271        public final Arch_Desc Architecture
272        public final Boolean RunAllTests
273        public final Boolean RunBenchmark
274        public final Boolean BuildDocumentation
275        public final Boolean Publish
276        public final Boolean Silent
277        public final Boolean IsSandbox
278        public final String DescLong
279        public final String DescShort
280
281        public String GitNewRef
282        public String GitOldRef
283
284        BuildSettings(java.util.Collections$UnmodifiableMap param, String branch) {
285                switch( param.Compiler ) {
286                        case 'gcc-6':
287                                this.Compiler = new CC_Desc('gcc-6', 'g++-6', 'gcc-6')
288                        break
289                        case 'gcc-5':
290                                this.Compiler = new CC_Desc('gcc-5', 'g++-5', 'gcc-5')
291                        break
292                        case 'gcc-4.9':
293                                this.Compiler = new CC_Desc('gcc-4.9', 'g++-4.9', 'gcc-4.9')
294                        break
295                        case 'clang':
296                                this.Compiler = new CC_Desc('clang', 'clang++', 'gcc-6')
297                        break
298                        default :
299                                error "Unhandled compiler : ${cc}"
300                }
301
302                switch( param.Architecture ) {
303                        case 'x64':
304                                this.Architecture = new Arch_Desc('x64', '--host=x86_64', 'x64')
305                        break
306                        case 'x86':
307                                this.Architecture = new Arch_Desc('x86', '--host=i386', 'x86')
308                        break
309                        default :
310                                error "Unhandled architecture : ${arch}"
311                }
312
313                this.RunAllTests        = param.RunAllTests
314                this.RunBenchmark       = param.RunBenchmark
315                this.BuildDocumentation = param.BuildDocumentation
316                this.Publish            = param.Publish
317                this.Silent             = param.Silent
318                this.IsSandbox          = (branch == "jenkins-sandbox")
319
320                def full = param.RunAllTests ? " (Full)" : ""
321                this.DescShort = "${ this.Compiler.name }:${ this.Architecture.name }${full}"
322
323                this.DescLong = """Compiler              : ${ this.Compiler.name } (${ this.Compiler.CXX }/${ this.Compiler.CC })
324Architecture            : ${ this.Architecture.name }
325Arc Flags               : ${ this.Architecture.flags }
326Run All Tests           : ${ this.RunAllTests.toString() }
327Run Benchmark           : ${ this.RunBenchmark.toString() }
328Build Documentation     : ${ this.BuildDocumentation.toString() }
329Publish                 : ${ this.Publish.toString() }
330Silent                  : ${ this.Silent.toString() }
331"""
332
333                this.GitNewRef = ''
334                this.GitOldRef = ''
335        }
336}
337
338def prepare_build() {
339        // prepare the properties
340        properties ([                                                                                                   \
341                [$class: 'ParametersDefinitionProperty',                                                                \
342                        parameterDefinitions: [                                                                         \
343                                [$class: 'ChoiceParameterDefinition',                                           \
344                                        description: 'Which compiler to use',                                   \
345                                        name: 'Compiler',                                                                       \
346                                        choices: 'gcc-6\ngcc-5\ngcc-4.9\nclang',                                        \
347                                        defaultValue: 'gcc-6',                                                          \
348                                ],                                                                                              \
349                                [$class: 'ChoiceParameterDefinition',                                           \
350                                        description: 'The target architecture',                                 \
351                                        name: 'Architecture',                                                           \
352                                        choices: 'x64\nx86',                                                            \
353                                        defaultValue: 'x64',                                                            \
354                                ],                                                                                              \
355                                [$class: 'BooleanParameterDefinition',                                                  \
356                                        description: 'If false, only the quick test suite is ran',              \
357                                        name: 'RunAllTests',                                                            \
358                                        defaultValue: false,                                                            \
359                                ],                                                                                              \
360                                [$class: 'BooleanParameterDefinition',                                                  \
361                                        description: 'If true, jenkins also runs benchmarks',           \
362                                        name: 'RunBenchmark',                                                           \
363                                        defaultValue: false,                                                            \
364                                ],                                                                                              \
365                                [$class: 'BooleanParameterDefinition',                                                  \
366                                        description: 'If true, jenkins also builds documentation',              \
367                                        name: 'BuildDocumentation',                                                     \
368                                        defaultValue: true,                                                             \
369                                ],                                                                                              \
370                                [$class: 'BooleanParameterDefinition',                                                  \
371                                        description: 'If true, jenkins also publishes results',                 \
372                                        name: 'Publish',                                                                        \
373                                        defaultValue: false,                                                            \
374                                ],                                                                                              \
375                                [$class: 'BooleanParameterDefinition',                                                  \
376                                        description: 'If true, jenkins will not send emails',           \
377                                        name: 'Silent',                                                                         \
378                                        defaultValue: false,                                                            \
379                                ],                                                                                              \
380                        ],
381                ]])
382
383        // It's unfortunate but it looks like we need to checkout the entire repo just to get the pretty git printer
384        checkout scm
385
386        final settings = new BuildSettings(params, env.BRANCH_NAME)
387
388        currentBuild.description = settings.DescShort
389        echo                       settings.DescLong
390
391        return settings
392}
393
394def build_stage(String name, Closure block ) {
395        StageName = name
396        echo " -------- ${StageName} -------- "
397        stage(name, block)
398}
399
400def notify_server(int wait) {
401        sh """curl --silent --show-error --data "wait=${wait}" -X POST https://cforall.uwaterloo.ca:8082/jenkins/notify > /dev/null || true"""
402        return
403}
404
405def make_doc() {
406        def err = null
407        try {
408                sh 'make clean > /dev/null'
409                sh 'make > /dev/null 2>&1'
410        }
411        catch (Exception caughtError) {
412                err = caughtError //rethrow error later
413                sh 'cat build/*.log'
414        }
415        finally {
416                if (err) throw err // Must re-throw exception to propagate error
417        }
418}
Note: See TracBrowser for help on using the repository browser.