forked from hibernate/hibernate-search
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Jenkinsfile
329 lines (321 loc) · 14.1 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
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
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
@Library('[email protected]') _
// NOTE: Remember to update the matrix axes below when adding/removing entries here.
// Also make sure to update the parameters in the parameters {} section of the pipeline.
Map settings() {
switch (env.DEPENDENCY_UPDATE_NAME) {
case 'orm6.6plus':
return [
updateProperties: ['version.org.hibernate.orm'],
onlyRunTestDependingOn: ['hibernate-search-mapper-orm'],
// rebuild orm utils to address removal of the bytecode enhanced engine
additionalMavenArgs: '-pl :hibernate-search-util-internal-integrationtest-mapper-orm'
]
case 'orm7':
return [
updateProperties: ['version.org.hibernate.orm'],
onlyRunTestDependingOn: ['hibernate-search-mapper-orm'],
// just rebuild all dependants since ORM7 upgrade will affect all mappers
additionalMavenArgs: '-am'
]
case 'lucene9.12':
return [
updateProperties: ['version.org.apache.lucene'],
onlyRunTestDependingOn: ['hibernate-search-backend-lucene'],
additionalMavenArgs: '-Dtest.elasticsearch.skip=true',
// Usually the "current-version"snapshots get stale,
// but just in case there are any new snapshots for 9.12 branch:
skipSourceModifiedCheck: true
]
case 'lucene9':
return [
updateProperties: ['version.org.apache.lucene'],
onlyRunTestDependingOn: ['hibernate-search-backend-lucene'],
additionalMavenArgs: '-Dtest.elasticsearch.skip=true -pl :hibernate-search-backend-lucene,:hibernate-search-util-internal-integrationtest-backend-lucene',
skipSourceModifiedCheck: true
]
case 'lucene10':
return [
updateProperties: ['version.org.apache.lucene'],
onlyRunTestDependingOn: ['hibernate-search-backend-lucene'],
additionalMavenArgs: '-Dtest.elasticsearch.skip=true -pl :hibernate-search-engine,:hibernate-search-backend-lucene,:hibernate-search-util-internal-integrationtest-backend-lucene,:hibernate-search-v5migrationhelper-engine'
]
// Targets the next micro release of the latest/currently integrated version of Elasticsearch
// (previous minor version is already published)
case 'elasticsearch-current':
return [
// There are no properties to update in this case.
updateProperties: [],
onlyRunTestDependingOn: ['hibernate-search-backend-elasticsearch'],
// We want to use the snapshot version of an image from the ES registry since that's where they are publishing their snapshots.
additionalMavenArgs: '-Dtest.lucene.skip=true -Dtest.elasticsearch.run.elastic.image.name=docker.elastic.co/elasticsearch/elasticsearch -Dtest.elasticsearch.run.elastic.image.tag=8.16.1-SNAPSHOT',
// This job won't change the versions in the pom. We are passing the latest Elasticsearch version through an additional maven argument `-D`
skipSourceModifiedCheck: true
]
// Targets the next major/minor release of the of Elasticsearch
// (currently not published at all)
case 'elasticsearch-next':
return [
// There are no properties to update in this case.
updateProperties: [],
onlyRunTestDependingOn: ['hibernate-search-backend-elasticsearch'],
// We want to use the snapshot version of an image from the ES registry since that's where they are publishing their snapshots.
additionalMavenArgs: '-Dtest.lucene.skip=true -Dtest.elasticsearch.run.elastic.image.name=docker.elastic.co/elasticsearch/elasticsearch -Dtest.elasticsearch.run.elastic.image.tag=8.17.0-SNAPSHOT',
// This job won't change the versions in the pom. We are passing the latest Elasticsearch version through an additional maven argument `-D`
skipSourceModifiedCheck: true
]
// Targets the next major release of the of Elasticsearch
// (currently not published at all)
case 'elasticsearch-future':
return [
// There are no properties to update in this case.
updateProperties: [],
onlyRunTestDependingOn: ['hibernate-search-backend-elasticsearch'],
// We want to use the snapshot version of an image from the ES registry since that's where they are publishing their snapshots.
additionalMavenArgs: '-Dtest.lucene.skip=true -Dtest.elasticsearch.run.elastic.image.name=docker.elastic.co/elasticsearch/elasticsearch -Dtest.elasticsearch.run.elastic.image.tag=9.0.0-SNAPSHOT',
// This job won't change the versions in the pom. We are passing the latest Elasticsearch version through an additional maven argument `-D`
skipSourceModifiedCheck: true
]
default:
return [:]
}
}
// Perform authenticated pulls of container images, to avoid failure due to download throttling on dockerhub.
def pullContainerImages() {
String containerImageRefsString = ((String) sh(script: "./ci/list-container-images.sh -U -Pdist -Pdependency-update ${env[qualify('ADDITIONAL_MAVEN_ARGS')]}", returnStdout: true))
String[] containerImageRefs = containerImageRefsString ? containerImageRefsString.split('\\s+') : new String[0]
echo 'Container images to be used in tests: ' + Arrays.toString(containerImageRefs)
if (containerImageRefs.length == 0) {
return
}
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
// Cannot use a foreach loop because then Jenkins wants to serialize the iterator,
// and obviously the iterator is not serializable.
for (int i = 0; i < containerImageRefs.length; i++) {
containerImageRef = containerImageRefs[i]
docker.image(containerImageRef).pull()
}
}
}
def withMavenWorkspace(Closure body) {
def actualJdk = settings().testCompilerTool == null ? 'OpenJDK 21 Latest' : settings().testCompilerTool
withMaven(jdk: actualJdk, maven: 'Apache Maven 3.9',
mavenLocalRepo: env.WORKSPACE_TMP + '/.m2repository',
options: [
// Artifacts are not needed and take up disk space
artifactsPublisher(disabled: true),
// stdout/stderr for successful tests is not needed and takes up disk space
// we archive test results and stdout/stderr as part of the build scan anyway,
// see https://ge.hibernate.org/scans?search.rootProjectNames=Hibernate%20Search
junitPublisher(disabled: true)
]) {
withCredentials([string(credentialsId: 'ge.hibernate.org-access-key',
variable: 'DEVELOCITY_ACCESS_KEY')]) {
withGradle { // withDevelocity, actually: https://plugins.jenkins.io/gradle/#plugin-content-capturing-build-scans-from-jenkins-pipeline
body()
}
}
}
}
String normalize(String string) {
return string.replaceAll('[^\\w]', '_')
}
// env is shared between parallel executions,
// so if we want a variable that is local to a given execution branch,
// we have to qualify its name to avoid conflicts...
String qualify(String radical) {
return '_' + normalize(env.DEPENDENCY_UPDATE_NAME) + '_' + radical
}
pipeline {
agent none
triggers {
// Run at least once per week, in case of snapshot updates.
cron '@weekly'
}
parameters {
// choice parameter doesn't have a default, but the first value should be treated as a default, if it wasn't specified manually.
// Make sure tp update axis and settings() when adding new choice parameter.
choice(name: 'UPDATE_JOB', choices: ['all', 'orm6.6plus', 'orm7', 'lucene9.12','lucene9', 'lucene10', 'elasticsearch-current', 'elasticsearch-next', 'elasticsearch-future'], description: 'Select which update jobs to run. `All` will include all configured update jobs.')
string(name: 'ORM_REPOSITORY', defaultValue: '', description: 'Git URL to Hibernate ORM repository. If provided, Hibernate ORM will be built locally. Works only in pair with ORM_BRANCH. Provide an http repository URL rather than an ssh one.')
string(name: 'ORM_BRANCH', defaultValue: '', description: 'Hibernate ORM branch to build from. If provided, Hibernate ORM will be built locally. Works only in pair with ORM_REPOSITORY. Either a pull request ID or a branch name should be provided, but not both at the same time. Use branch if you want to build from a fork repository.')
string(name: 'ORM_PULL_REQUEST_ID', defaultValue: '', description: 'Hibernate ORM pull request id to build from. If provided, Hibernate ORM will be built locally. Works only in pair with ORM_REPOSITORY. Either a pull request ID or a branch name should be provided, but not both at the same time.')
}
options {
buildDiscarder logRotator(daysToKeepStr: '10', numToKeepStr: '3')
disableConcurrentBuilds(abortPrevious: true)
overrideIndexTriggers(false)
}
environment {
TESTCONTAINERS_REUSE_ENABLE = 'true'
}
stages {
// This allows testing the original (unpatched) artifacts,
// while patching tests where necessary.
// Especially important when testing the compatibility
// of published artifacts with different versions of dependencies.
stage('Pre-build original code') {
parallel {
stage('Build Hibernate ORM') {
agent {
label 'Worker&&Containers'
}
post {
cleanup {
dir('hibernate-orm-local-copy') {
deleteDir()
}
}
}
when {
beforeAgent true
expression {
return params.ORM_REPOSITORY?.trim() || params.ORM_BRANCH?.trim() || params.ORM_PULL_REQUEST_ID?.trim()
}
}
steps {
script {
if (params.ORM_BRANCH?.trim() && params.ORM_PULL_REQUEST_ID?.trim()) {
error "Both ORM_BRANCH and ORM_PULL_REQUEST_ID are provided. Use only one of these parameters."
}
if (!params.ORM_REPOSITORY?.trim() || !(params.ORM_BRANCH?.trim() || params.ORM_PULL_REQUEST_ID?.trim())) {
error "Both ORM_REPOSITORY and either ORM_BRANCH or ORM_PULL_REQUEST_ID must be not blank if a local build of Hibernate ORM is required. Repository: [${params.ORM_REPOSITORY}], branch: [${params.ORM_BRANCH}, pull request: [${params.ORM_PULL_REQUEST_ID}]]."
}
}
script {
dir('hibernate-orm-local-copy') {
// We may get either an http or an ssh repository URLs.
// Since this job can work correctly only with an http URL we will try to adapt the ssh url if we spot one:
def repositoryUrl = params.ORM_REPOSITORY ==~ /^git@github\.com:.+$/ ? params.ORM_REPOSITORY.replace("[email protected]:", "https://github.com/") : params.ORM_REPOSITORY
if (params.ORM_BRANCH?.trim()) {
sh "git clone ${repositoryUrl} --depth 1 --branch ${params.ORM_BRANCH} --single-branch ."
} else {
sh "git clone ${repositoryUrl} --depth 1 --single-branch ."
sh "git fetch origin pull/${params.ORM_PULL_REQUEST_ID}/head:orm-branch-to-build"
sh "git switch orm-branch-to-build"
}
sh "./gradlew publishToMavenLocal -x test -Dmaven.repo.local=${env.WORKSPACE_TMP}/.m2repository"
}
dir(env.WORKSPACE_TMP + '/.m2repository') {
stash name: 'orm-local-build-result', includes: "org/hibernate/orm/**"
}
}
}
}
stage('Build Hibernate Search') {
agent {
label 'Worker&&Containers'
}
post {
cleanup {
sh 'ci/docker-cleanup.sh'
}
}
steps {
// The timeout cannot be in stage options, because that would
// include the time needed to provision a node.
timeout(time: 30, unit: 'MINUTES') {
withMavenWorkspace {
sh "mvn clean install -U -Pdist -DskipTests"
dir(env.WORKSPACE_TMP + '/.m2repository') {
stash name: 'original-build-result', includes: "org/hibernate/search/**"
}
}
}
}
}
}
}
stage('Update dependency and test') {
matrix {
axes {
axis {
name 'DEPENDENCY_UPDATE_NAME'
// NOTE: Remember to update the settings() method above when changing this.
// And also add a new choice parameter in the parameters {} section of the pipeline
values 'orm6.6plus', 'orm7', 'lucene9.12','lucene9', 'lucene10', 'elasticsearch-current', 'elasticsearch-next', 'elasticsearch-future'
}
}
stages {
stage('Build') {
agent {
label 'Worker&&Containers'
}
when {
beforeAgent true
expression {
return params.UPDATE_JOB?.trim() == 'all' || params.UPDATE_JOB?.trim() == env.DEPENDENCY_UPDATE_NAME
}
}
stages {
stage('Init') {
steps {
sh 'ci/docker-cleanup.sh'
dir(env.WORKSPACE_TMP + '/.m2repository') {
unstash name: 'original-build-result'
}
dir(env.WORKSPACE_TMP + '/.m2repository') {
script{
try {
unstash name: 'orm-local-build-result'
} catch (e) {
echo 'Hibernate ORM was not built, ignoring unstash of snapshot ORM jars'
}
}
}
withMavenWorkspace {
script {
env[qualify('ADDITIONAL_MAVEN_ARGS')] = settings().additionalMavenArgs ?: ''
if (settings().onlyRunTestDependingOn) {
env[qualify('ADDITIONAL_MAVEN_ARGS')] += ' -pl ' + sh(script: "./ci/list-dependent-integration-tests.sh ${settings().onlyRunTestDependingOn.join(' ')}", returnStdout: true).trim()
}
}
}
}
}
stage('Update dependency') {
steps {
withMavenWorkspace {
sh "ci/dependency-update/perform-update.sh ${env.DEPENDENCY_UPDATE_NAME} '${settings().updateProperties?.join(",") ?: ''}'"
}
script {
if (!settings().skipSourceModifiedCheck && 0 != sh(script: "git diff origin/${BRANCH_NAME} | grep -q '.'", returnStatus: true)) {
error "This job does not seem to update any dependency; perhaps it is misconfigured? The source code has not been updated, neither by merging a WIP branch nor by updating version properties."
}
}
}
}
stage('Test') {
post {
cleanup {
sh 'ci/docker-cleanup.sh'
}
}
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
withMavenWorkspace {
pullContainerImages()
sh """ \
mvn clean install -U -Pdependency-update -Pdist -Pci-build -Dsurefire.environment=${normalize(env.DEPENDENCY_UPDATE_NAME)} \
--fail-at-end \
${env[qualify('ADDITIONAL_MAVEN_ARGS')]} \
"""
}
}
}
}
}
}
}
}
}
post {
always {
notifyBuildResult maintainers: '[email protected]'
}
}
}