source: Jenkinsfile @ 2469a6e

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

Fixed bad copy-paste

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