source: Jenkinsfile @ a8a7612

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

Since incremental builds have been quite painful in jenkins and we probably should avoid them in the first place for our build machine, Jenkins now disables dependency tracking all together when configuring

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