source: Jenkinsfile @ b98313c

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexer
Last change on this file since b98313c was b98313c, checked in by Thierry Delisle <tdelisle@…>, 3 years ago

Clean now handled in checkout and started looking into currentBuild changeSets

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