source: Jenkinsfile @ 5b8413b4

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

More Jenkinsfile cleanup

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