-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
/
Jenkinsfile
248 lines (232 loc) · 10.3 KB
/
Jenkinsfile
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
#!/usr/bin/env groovy
/*
* This Jenkinsfile is intended to run on https://ci.jenkins.io and may fail anywhere else.
* It makes assumptions about plugins being installed, labels mapping to nodes that can build what is needed, etc.
*/
def failFast = false
properties([
buildDiscarder(logRotator(numToKeepStr: '50', artifactNumToKeepStr: '3')),
disableConcurrentBuilds(abortPrevious: true)
])
def axes = [
platforms: ['linux', 'windows'],
jdks: [17, 21],
]
stage('Record build') {
retry(conditions: [kubernetesAgent(handleNonKubernetes: true), nonresumable()], count: 2) {
node('maven-17') {
infra.checkoutSCM()
/*
* Record the primary build for this CI job.
*/
withCredentials([string(credentialsId: 'launchable-jenkins-jenkins', variable: 'LAUNCHABLE_TOKEN')]) {
/*
* TODO Add the commits of the transitive closure of the Jenkins WAR under test to this build.
*/
sh 'launchable verify && launchable record build --name ${BUILD_TAG} --source jenkinsci/jenkins=.'
axes.values().combinations {
def (platform, jdk) = it
if (platform == 'windows' && jdk != 17) {
return // unnecessary use of hardware
}
def sessionFile = "launchable-session-${platform}-jdk${jdk}.txt"
sh "launchable record session --build ${env.BUILD_TAG} --flavor platform=${platform} --flavor jdk=${jdk} >${sessionFile}"
stash name: sessionFile, includes: sessionFile
}
}
/*
* Record commits for use in downstream CI jobs that may consume this artifact.
*/
withCredentials([string(credentialsId: 'launchable-jenkins-acceptance-test-harness', variable: 'LAUNCHABLE_TOKEN')]) {
sh 'launchable verify && launchable record commit'
}
withCredentials([string(credentialsId: 'launchable-jenkins-bom', variable: 'LAUNCHABLE_TOKEN')]) {
sh 'launchable verify && launchable record commit'
}
}
}
}
def builds = [:]
axes.values().combinations {
def (platform, jdk) = it
if (platform == 'windows' && jdk != 17) {
return // unnecessary use of hardware
}
builds["${platform}-jdk${jdk}"] = {
// see https://github.com/jenkins-infra/documentation/blob/master/ci.adoc#node-labels for information on what node types are available
def agentContainerLabel = 'maven-' + jdk
if (platform == 'windows') {
agentContainerLabel += '-windows'
}
retry(conditions: [kubernetesAgent(handleNonKubernetes: true), nonresumable()], count: 2) {
node(agentContainerLabel) {
// First stage is actually checking out the source. Since we're using Multibranch
// currently, we can use "checkout scm".
stage("${platform.capitalize()} - JDK ${jdk} - Checkout") {
infra.checkoutSCM()
}
def tmpDir = pwd(tmp: true)
def changelistF = "${tmpDir}/changelist"
def m2repo = "${tmpDir}/m2repo"
def session
// Now run the actual build.
stage("${platform.capitalize()} - JDK ${jdk} - Build / Test") {
timeout(time: 6, unit: 'HOURS') {
dir(tmpDir) {
def sessionFile = "launchable-session-${platform}-jdk${jdk}.txt"
unstash sessionFile
session = readFile(sessionFile).trim()
}
def mavenOptions = [
'-Pdebug',
'-Penable-jacoco',
'--update-snapshots',
"-Dmaven.repo.local=$m2repo",
'-Dmaven.test.failure.ignore',
'-DforkCount=2',
'-Dspotbugs.failOnError=false',
'-Dcheckstyle.failOnViolation=false',
'-Dset.changelist',
'help:evaluate',
'-Dexpression=changelist',
"-Doutput=$changelistF",
'clean',
'install',
]
if (env.CHANGE_ID && !pullRequest.labels.contains('full-test')) {
def excludesFile
def target = platform == 'windows' ? '30%' : '100%'
withCredentials([string(credentialsId: 'launchable-jenkins-jenkins', variable: 'LAUNCHABLE_TOKEN')]) {
if (isUnix()) {
excludesFile = "${tmpDir}/excludes.txt"
sh "launchable verify && launchable subset --session ${session} --target ${target} --get-tests-from-previous-sessions --output-exclusion-rules maven >${excludesFile}"
} else {
excludesFile = "${tmpDir}\\excludes.txt"
bat "launchable verify && launchable subset --session ${session} --target ${target}% --get-tests-from-previous-sessions --output-exclusion-rules maven >${excludesFile}"
}
}
mavenOptions.add(0, "-Dsurefire.excludesFile=${excludesFile}")
}
withChecks(name: 'Tests', includeStage: true) {
realtimeJUnit(healthScaleFactor: 20.0, testResults: '*/target/surefire-reports/*.xml') {
infra.runMaven(mavenOptions, jdk)
if (isUnix()) {
sh 'git add . && git diff --exit-code HEAD'
}
}
}
}
}
// Once we've built, archive the artifacts and the test results.
stage("${platform.capitalize()} - JDK ${jdk} - Publish") {
archiveArtifacts allowEmptyArchive: true, artifacts: '**/target/surefire-reports/*.dumpstream'
// cli and war have been migrated to JUnit 5
if (failFast && currentBuild.result == 'UNSTABLE') {
error 'There were test failures; halting early'
}
if (platform == 'linux' && jdk == axes['jdks'][0]) {
def folders = env.JOB_NAME.split('/')
if (folders.length > 1) {
discoverGitReferenceBuild(scm: folders[1])
}
recordCoverage(tools: [[parser: 'JACOCO', pattern: 'coverage/target/site/jacoco-aggregate/jacoco.xml']],
sourceCodeRetention: 'MODIFIED', sourceDirectories: [[path: 'core/src/main/java']])
echo "Recording static analysis results for '${platform.capitalize()}'"
recordIssues(
enabledForFailure: true,
tools: [java()],
filters: [excludeFile('.*Assert.java')],
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY'
)
recordIssues(
enabledForFailure: true,
tools: [javaDoc()],
filters: [excludeFile('.*Assert.java')],
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY',
qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]
)
recordIssues([tool: spotBugs(pattern: '**/target/spotbugsXml.xml'),
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY',
qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]])
recordIssues([tool: checkStyle(pattern: '**/target/checkstyle-result.xml'),
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY',
qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]])
recordIssues([tool: esLint(pattern: '**/target/eslint-warnings.xml'),
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY',
qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]])
recordIssues([tool: styleLint(pattern: '**/target/stylelint-warnings.xml'),
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY',
qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]])
if (failFast && currentBuild.result == 'UNSTABLE') {
error 'Static analysis quality gates not passed; halting early'
}
def changelist = readFile(changelistF)
dir(m2repo) {
archiveArtifacts(
artifacts: "**/*$changelist/*$changelist*",
excludes: '**/*.lastUpdated,**/jenkins-coverage*/,**/jenkins-test*/',
allowEmptyArchive: true, // in case we forgot to reincrementalify
fingerprint: true
)
}
}
withCredentials([string(credentialsId: 'launchable-jenkins-jenkins', variable: 'LAUNCHABLE_TOKEN')]) {
if (isUnix()) {
sh "launchable verify && launchable record tests --session ${session} --flavor platform=${platform} --flavor jdk=${jdk} maven './**/target/surefire-reports'"
} else {
bat "launchable verify && launchable record tests --session ${session} --flavor platform=${platform} --flavor jdk=${jdk} maven ./**/target/surefire-reports"
}
}
}
}
}
}
}
def athAxes = [
platforms: ['linux'],
jdks: [17],
browsers: ['firefox'],
]
athAxes.values().combinations {
def (platform, jdk, browser) = it
builds["ath-${platform}-jdk${jdk}-${browser}"] = {
retry(conditions: [agent(), nonresumable()], count: 2) {
node('docker-highmem') {
// Just to be safe
deleteDir()
checkout scm
withChecks(name: 'Tests', includeStage: true) {
infra.withArtifactCachingProxy {
sh "bash ath.sh ${jdk} ${browser}"
}
junit testResults: 'target/ath-reports/TEST-*.xml', testDataPublishers: [[$class: 'AttachmentPublisher']]
}
/*
* Currently disabled, as the fact that this is a manually created subset will confuse Launchable,
* which expects this to be a full build. When we implement subsetting, this can be re-enabled using
* Launchable's subset rather than our own.
*/
/*
withCredentials([string(credentialsId: 'launchable-jenkins-acceptance-test-harness', variable: 'LAUNCHABLE_TOKEN')]) {
sh "launchable verify && launchable record tests --no-build --flavor platform=${platform} --flavor jdk=${jdk} --flavor browser=${browser} maven './target/ath-reports'"
}
*/
}
}
}
}
builds.failFast = failFast
parallel builds
infra.maybePublishIncrementals()