source: Jenkinsfile @ 3a9aceb

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

Removed first unnecessary checkout

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