summaryrefslogtreecommitdiff
path: root/netci.groovy
blob: 17683bc4e339ed267d5e7244baa15b47a104a823 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
// Import the utility functionality.

import jobs.generation.Utilities;

def project = 'dotnet/coreclr'

// Map of OS's to labels.  TODO: Maybe move this into the Utils

def machineLabelMap = ['Ubuntu':'ubuntu',
                       'OSX':'mac',
                       'Windows_NT':'windows',
                       'FreeBSD': 'freebsd',
                       'CentOS7.1': 'centos-71',
                       'OpenSUSE13.2': 'openSuSE-132']
                       
// Map of the build OS to the directory that will have the outputs
def osGroupMap = ['Ubuntu':'Linux',
                    'OSX':'OSX',
                    'Windows_NT':'Windows_NT',
                    'FreeBSD':'FreeBSD',
                    'CentOS7.1': 'Linux',
                    'OpenSUSE13.2': 'Linux']
      
// Innerloop build OS's
def osList = ['Ubuntu', 'OSX', 'Windows_NT', 'FreeBSD', 'CentOS7.1', 'OpenSUSE13.2']

def static getBuildJobName(def configuration, def architecture, def os) {
    // If the architecture is x64, do not add that info into the build name.
    // Need to change around some systems and other builds to pick up the right builds
    // to do that.
    
    if (architecture == 'x64') {
        return configuration.toLowerCase() + '_' + os.toLowerCase()
    }
    else {
        // Massage names a bit
        return architecture.toLowerCase() + '_' + configuration.toLowerCase() + '_' + os.toLowerCase()
    }
}

// **************************
// Define the basic inner loop builds for PR and commit.  This is basically just the set
// of coreclr builds over linux/osx/freebsd/windows and debug/release.  In addition, the windows
// builds will do a couple extra steps.
// **************************

// Loop over the options and build up the innerloop build matrix
// Default architecture is x64.  Right now that isn't built into the
// build name.  We'll need to change that eventually, but for now leave as is.
// x86 builds have the new build name

['x64', 'x86'].each { architecture ->
    ['Debug', 'Release'].each { configuration ->
        osList.each { os ->
            // Calculate names
            def lowerConfiguration = configuration.toLowerCase()
            
            // Calculate job name
            def jobName = getBuildJobName(configuration, architecture, os)
            def buildCommands = [];
            
            def osGroup = osGroupMap[os]
            
            // Calculate the build commands
            if (os == 'Windows_NT') {
                // On Windows we build the mscorlibs too.
                buildCommands += "build.cmd ${lowerConfiguration} ${architecture}"
                
                // If x64, we run tests
                if (architecture == 'x64') {
                    buildCommands += "tests\\runtest.cmd ${lowerConfiguration} ${architecture}"
                }
                
                // Build the mscorlib for the other OS's
                buildCommands += "build.cmd ${lowerConfiguration} ${architecture} linuxmscorlib"
                buildCommands += "build.cmd ${lowerConfiguration} ${architecture} freebsdmscorlib"
                buildCommands += "build.cmd ${lowerConfiguration} ${architecture} osxmscorlib"
                // Zip up the tests directory so that we don't use so much space/time copying
                // 10s of thousands of files around.
                buildCommands += "powershell -Command \"Add-Type -Assembly 'System.IO.Compression.FileSystem'; [System.IO.Compression.ZipFile]::CreateFromDirectory('.\\bin\\tests\\${osGroup}.${architecture}.${configuration}', '.\\bin\\tests\\tests.zip')\"";
            }
            else {
                // On other OS's we skipmscorlib but run the pal tests
                buildCommands += "./build.sh skipmscorlib verbose ${lowerConfiguration} ${architecture}"
                buildCommands += "src/pal/tests/palsuite/runpaltests.sh \${WORKSPACE}/bin/obj/${osGroup}.${architecture}.${configuration} \${WORKSPACE}/bin/paltestout"
            }
            
            // Create the new job
            def newCommitJob = job(Utilities.getFullJobName(project, jobName, false)) {
                // Set the label.
                label(machineLabelMap[os])
                steps {
                    if (os == 'Windows_NT') {
                        buildCommands.each { buildCommand ->
                            batchFile(buildCommand)
                        }
                    }
                    else {
                        buildCommands.each { buildCommand ->
                            shell(buildCommand)
                        }
                    }
                }
            }

            // Add commit job options
            Utilities.addScm(newCommitJob, project)
            Utilities.addStandardNonPRParameters(newCommitJob)
            
            // Add a push trigger.  Do not enable the push trigger for non-windows x86,
            // which do not work at the moment.
            if (architecture == 'x64' || osGroup == 'Windows_NT') {
                Utilities.addGithubPushTrigger(newCommitJob)
            }
            
            // Create the new PR job
            
            def newPRJob = job(Utilities.getFullJobName(project, jobName, true)) {
                // Set the label.
                label(machineLabelMap[os])
                steps {
                    if (os == 'Windows_NT') {
                        buildCommands.each { buildCommand ->
                            batchFile(buildCommand)
                        }
                    }
                    else {
                        buildCommands.each { buildCommand ->
                            shell(buildCommand)
                        }
                    }
                }
            }
            
            // Add a PR trigger.  For some OS's, create an explicit trigger
            // PR's are run for everything except SuSE by default.  Add on-demand triggers 
            // for everything else.  This probably deserves a bit of cleanup eventually once we
            // have an easy way to do regex trigger phrases, to put in some more structured test phrases.
            def triggerPhraseString = ''
            def triggerByPhraseOnly = true;
            if (os == 'OpenSUSE13.2' && architecture == 'x64') {
                triggerPhraseString = '(?i).*test\\W+suse.*'
            } else if (architecture == 'x86' && osGroup == 'Linux') {
                triggerPhraseString = '(?i).*test\\W+x86\\W+linux.*'
            } else if (architecture == 'x86' && osGroup == 'OSX') {
                triggerPhraseString = '(?i).*test\\W+x86\\W+osx.*'
            } else if (architecture == 'x86' && osGroup == 'FreeBSD') {
                triggerPhraseString = '(?i).*test\\W+x86\\W+freebsd.*'
            }
            Utilities.addGithubPRTrigger(newPRJob, "${os} ${architecture} ${configuration} Build", triggerPhraseString, triggerByPhraseOnly)
            Utilities.addPRTestSCM(newPRJob, project)
            Utilities.addStandardPRParameters(newPRJob, project)
            
            // Add common options:
            
            [newPRJob, newCommitJob].each { newJob ->
                Utilities.addStandardOptions(newJob)
                
                // Instead of packing up all the 
                if (osGroup == 'Windows_NT' && architecture == 'x64') {
                    Utilities.addXUnitDotNETResults(newJob, 'bin/**/TestRun*.xml')
                    Utilities.addArchival(newJob, "bin/Product/**,bin/tests/tests.zip")
                } else if (osGroup != 'Windows_NT') {
                    // Add .NET results for the 
                    Utilities.addXUnitDotNETResults(newJob, '**/pal_tests.xml')
                    Utilities.addArchival(newJob, "bin/Product/**,bin/obj/*/tests/**")
                }
            }
        } // os
    } // configuration
} // architecture

// Ubuntu cross compiled arm and arm64 builds
// Scheduled for nightly and on-demand PR for now
// Cross compiled OS names go here
['Ubuntu'].each { os ->
    [true, false].each { isPR ->
        ['Debug', 'Release'].each { configuration ->
            def lowerConfiguration = configuration.toLowerCase()
            
            // Create the new job
            def newArm64Job = job(Utilities.getFullJobName(project, "arm64_cross_${os.toLowerCase()}_${lowerConfiguration}", isPR)) {
                // Set the label.
                label(machineLabelMap[os])
                steps {
                    shell("""
    echo \"Using rootfs in /opt/aarch64-linux-gnu-root\"
    ROOTFS_DIR=/opt/aarch64-linux-gnu-root ./build.sh skipmscorlib arm64 cross verbose ${lowerConfiguration}""")
                }
            }
            
            if (!isPR) {
                // Add rolling job options
                Utilities.addScm(newArm64Job, project)
                Utilities.addStandardNonPRParameters(newArm64Job)
                Utilities.addPeriodicTrigger(newArm64Job, '@daily')
                Utilities.addArchival(newArm64Job, "bin/Product/**")
            }
            else {
                // Add PR job options
                Utilities.addPRTestSCM(newArm64Job, project)
                Utilities.addStandardPRParameters(newArm64Job, project)
                Utilities.addGithubPRTrigger(newArm64Job, "Arm64 ${os} cross ${configuration} Build", '(?i).*test\\W+arm.*', true /* trigger by phrase only */)
            }
            
            // Create the new job
            def newArmJob = job(Utilities.getFullJobName(project, "arm_cross_${os.toLowerCase()}_${lowerConfiguration}", isPR)) {
                // Set the label.
                label(machineLabelMap[os])
                steps {
                    shell("""
    echo \"Using rootfs in /opt/arm-liux-genueabihf-root\"
    ROOTFS_DIR=/opt/arm-linux-genueabihf-root ./build.sh skipmscorlib arm cross verbose ${lowerConfiguration}""")
                }
            }
            
            if (!isPR) {
                // Add rolling job options
                Utilities.addScm(newArmJob, project)
                Utilities.addStandardNonPRParameters(newArmJob)
                Utilities.addPeriodicTrigger(newArmJob, '@daily')
                Utilities.addArchival(newArmJob, "bin/Product/**")
            }
            else {
                // Add PR job options
                Utilities.addPRTestSCM(newArmJob, project)
                Utilities.addStandardPRParameters(newArmJob, project)
                Utilities.addGithubPRTrigger(newArmJob, "Arm ${os} cross ${configuration} Build", '(?i).*test\\W+arm.*', true /* trigger by phrase only */)
            }
            
            [newArmJob, newArm64Job].each { newJob ->
                Utilities.addStandardOptions(newJob)
            }
        }
    }
}

// Create the Linux coreclr test leg for debug and release.
// Architectures
['x64', 'x86'].each { architecture ->
    // Put the OS's supported for coreclr cross testing here
    ['Ubuntu'].each { os ->
        [true, false].each { isPR ->
            ['Debug', 'Release'].each { configuration ->
                
                def lowerConfiguration = configuration.toLowerCase()
                def osGroup = osGroupMap[os]
                def jobName = getBuildJobName(configuration, architecture, os) + "_tst"
                def inputCoreCLRBuildName = Utilities.getFolderName(project) + '/' + 
                    Utilities.getFullJobName(project, getBuildJobName(configuration, architecture, os), isPR)
                def inputWindowTestsBuildName = Utilities.getFolderName(project) + '/' + 
                    Utilities.getFullJobName(project, getBuildJobName(configuration, architecture, 'windows_nt'), isPR)
                
                def newJob = job(Utilities.getFullJobName(project, jobName, isPR)) {
                    // Set the label.
                    label(machineLabelMap[os])
                    
                    // Add parameters for the inputs
                    
                    parameters {
                        stringParam('CORECLR_WINDOWS_BUILD', '', 'Build number to copy CoreCLR windows test binaries from')
                        stringParam('CORECLR_LINUX_BUILD', '', 'Build number to copy CoreCLR linux binaries from')
                    }
                    
                    steps {
                        // Set up the copies
                        
                        // Coreclr build we are trying to test
                        
                        copyArtifacts(inputCoreCLRBuildName) {
                            excludePatterns('**/testResults.xml', '**/*.ni.dll')
                            buildSelector {
                                buildNumber('${CORECLR_LINUX_BUILD}')
                            }
                        }
                        
                        // Coreclr build containing the tests and mscorlib
                        
                        copyArtifacts(inputWindowTestsBuildName) {
                            excludePatterns('**/testResults.xml', '**/*.ni.dll')
                            buildSelector {
                                buildNumber('${CORECLR_WINDOWS_BUILD}')
                            }
                        }
                        
                        // Corefx native components
                        copyArtifacts("dotnet_corefx_linux_nativecomp_debug") {
                            includePatterns('bin/**')
                            buildSelector {
                                latestSuccessful(true)
                            }
                        }
                        
                        // Corefx linux binaries
                        copyArtifacts("dotnet_corefx_linux_debug") {
                            includePatterns('bin/Linux*/**')
                            buildSelector {
                                latestSuccessful(true)
                            }
                        }
                        
                        // Unzip the tests first.  Exit with 0
                        shell("unzip -q -o ./bin/tests/tests.zip -d ./bin/tests/Windows_NT.${architecture}.${configuration} || exit 0")
                        
                        // Execute the tests
                        shell("""
    ./tests/runtest.sh \\
        --testRootDir=\"\${WORKSPACE}/bin/tests/Windows_NT.${architecture}.${configuration}\" \\
        --testNativeBinDir=\"\${WORKSPACE}/bin/obj/Linux.${architecture}.${configuration}/tests\" \\
        --coreClrBinDir=\"\${WORKSPACE}/bin/Product/Linux.${architecture}.${configuration}\" \\
        --mscorlibDir=\"\${WORKSPACE}/bin/Product/Linux.${architecture}.${configuration}\" \\
        --coreFxBinDir=\"\${WORKSPACE}/bin/Linux.AnyCPU.Debug\" \\
        --coreFxNativeBinDir=\"\${WORKSPACE}/bin/Linux.${architecture}.Debug\"""")
                    }
                }
                
                if (!isPR) {
                    // Add rolling job options
                    Utilities.addScm(newJob, project)
                    Utilities.addStandardNonPRParameters(newJob)
                }
                else {
                    // Add PR job options
                    Utilities.addPRTestSCM(newJob, project)
                    Utilities.addStandardPRParameters(newJob, project)
                }
                Utilities.addStandardOptions(newJob)
                Utilities.addXUnitDotNETResults(newJob, '**/coreclrtests.xml')
                
                // Create a build flow to join together the build and tests required to run this
                // test.
                // Windows CoreCLR build and Linux CoreCLR build (in parallel) ->
                // Linux CoreCLR test
                def flowJobName = getBuildJobName(configuration, architecture, os) + "_flow"
                def fullTestJobName = Utilities.getFolderName(project) + '/' + newJob.name
                def newFlowJob = buildFlowJob(Utilities.getFullJobName(project, flowJobName, isPR)) {
                    buildFlow("""
// Grab the checked out git commit hash so that it can be passed to the child
// builds.
// Temporarily output the properties for diagnosis of issues with the statement below
out.println 'Triggered Parameters Map:'
out.println params
out.println 'Build Object Properties:'
build.properties.each { out.println \"\$it.key -> \$it.value\" }
// globalParams = params + [GitBranchOrCommit: build.environment.get('GIT_COMMIT')]
globalParams = params
// Build the input jobs in parallel
parallel (
    { linuxBuildJob = build(globalParams, '${inputCoreCLRBuildName}') },
    { windowsBuildJob = build(globalParams, '${inputWindowTestsBuildName}') }
)
    
// And then build the test build
build(globalParams + [CORECLR_LINUX_BUILD: linuxBuildJob.build.number, 
                CORECLR_WINDOWS_BUILD: windowsBuildJob.build.number], '${fullTestJobName}')    
""")

                    // Needs a workspace
                    configure {
                        def buildNeedsWorkspace = it / 'buildNeedsWorkspace'
                        buildNeedsWorkspace.setValue('true')
                    }
                }

                if (isPR) {
                    Utilities.addPRTestSCM(newFlowJob, project)
                    Utilities.addStandardPRParameters(newFlowJob, project)
                    if (architecture == 'x64') {
                        if (configuration == 'Release') {
                            // Tests will be run on x64 Release by default (no trigger phase required).
                            Utilities.addGithubPRTrigger(newFlowJob, "Ubuntu ${architecture} ${configuration} Build and Test",
                            "(?i).*test\\W+ubuntu\\W+release.*", false /* trigger by phrase only */)
                        } else {
                            Utilities.addGithubPRTrigger(newFlowJob, "Ubuntu ${architecture} ${configuration} Build and Test", "(?i).*test\\W+ubuntu\\W+debug.*", true /* trigger by phrase only */)
                        }
                    } else if (architecture == 'x86') {
                        if (configuration == 'Release') {
                            Utilities.addGithubPRTrigger(newFlowJob, "Ubuntu ${architecture} ${configuration} Build and Test", "(?i).*test\\W+ubuntu\\W+x86.*", true /* trigger by phrase only */)
                        } else {
                            Utilities.addGithubPRTrigger(newFlowJob, "Ubuntu ${architecture} ${configuration} Build and Test", "(?i).*test\\W+ubuntu\\W+x86\\W+debug.*", true /* trigger by phrase only */)
                        }
                    }
                }
                else {
                    Utilities.addScm(newFlowJob, project)
                    Utilities.addStandardNonPRParameters(newFlowJob)
                    if (architecture == 'x64') {
                        Utilities.addGithubPushTrigger(newFlowJob)
                    }
                }
                
                Utilities.addStandardOptions(newFlowJob)
            }
        }
    }
}