Skip to content

Commit 5374ff5

Browse files
Improve jenkinsfile parse perf, and fix parallel xz test result file compressing
Only read the supported and default jdks once. Also add debug when starting the pipeline on the parameters that will be used for building and testing. ref: https://the-asf.slack.com/archives/CK23JSY2K/p1763714160975359 patch by Mick Semb Wever; reviewed by Sam Tunnicliffe for CASSANDRA-21044
1 parent f8f456f commit 5374ff5

File tree

1 file changed

+45
-38
lines changed

1 file changed

+45
-38
lines changed

.jenkins/Jenkinsfile

Lines changed: 45 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
// - cassandra-amd64-medium : 3 cpu, 5GB ram
3636
// - cassandra-medium : 3 cpu, 5GB ram (alias for above but for any arch)
3737
// - cassandra-amd64-large : 7 cpu, 16GB ram
38-
// - cassandra-large : 7 cpu, 16GB ram
38+
// - cassandra-large : 7 cpu, 16GB ram
3939
//
4040
// When running builds parameterised to other architectures the corresponding labels are expected.
4141
// For example 'arm64' requires the labels: cassandra-arm64-small, cassandra-arm64-medium, cassandra-arm64-large.
@@ -56,6 +56,12 @@
5656
// `curl -X POST -F "jenkinsfile=<.jenkins/Jenkinsfile" https://ci-cassandra.apache.org/pipeline-model-converter/validate`
5757
//
5858

59+
/** CONSTANTS for both the pipeline and scripting **/
60+
import groovy.transform.Field
61+
@Field List<String> archsSupported = ["amd64", "arm64"]
62+
@Field List<String> pythonsSupported = ["3.8", "3.11"]
63+
@Field String pythonDefault = "3.8"
64+
/** CONSTANTS end **********************************/
5965

6066
pipeline {
6167
agent { label 'cassandra-small' }
@@ -70,13 +76,22 @@ pipeline {
7076
choice(name: 'profile', choices: pipelineProfileNames(params.profile ?: ''), description: 'Pick a pipeline profile.')
7177
string(name: 'profile_custom_regexp', defaultValue: params.profile_custom_regexp ?: '', description: 'Regexp for stages when using custom profile. See `testSteps` in Jenkinsfile for list of stages. Example: stress.*|jvm-dtest.*')
7278

73-
choice(name: 'architecture', choices: archsSupported() + "all", description: 'Pick architecture. The ARM64 is disabled by default at the moment.')
79+
choice(name: 'architecture', choices: archsSupported + "all", description: 'Pick architecture. The ARM64 is disabled by default at the moment.')
7480
string(name: 'jdk', defaultValue: params.jdk ?: '', description: 'Restrict JDK versions. (e.g. "11", "17", etc)')
7581

7682
string(name: 'dtest_repository', defaultValue: params.dtest_repository ?: 'https://github.com/apache/cassandra-dtest', description: 'Cassandra DTest Repository')
7783
string(name: 'dtest_branch', defaultValue: params.dtest_branch ?: 'trunk', description: 'DTest Branch')
7884
}
7985
stages {
86+
stage('init') {
87+
steps {
88+
script {
89+
// this helps assure folk their parameters are correct and will be used (despite the earlier output about the configured job coordinates)
90+
echo "Printing parameters used for this build"
91+
["Repository: ${params.repository}", "Branch: ${params.branch}", "Profile: ${params.profile}", "Custom Profile Regexp: ${params.profile_custom_regexp}", "Architecture: ${params.architecture}", "JDK: ${params.jdk}", "DTest Repository: ${params.dtest_repository}", "DTest Branch: ${params.dtest_branch}"].each { println it }
92+
}
93+
}
94+
}
8095
stage('jar') {
8196
// the jar stage executes only the 'jar' build step, via the build(…) function
8297
// the results of these (per jdk, per arch) are then stashed and used for every other build and test step
@@ -120,10 +135,7 @@ pipeline {
120135
//// scripting support ////
121136
///////////////////////////
122137

123-
def archsSupported() { return ["amd64", "arm64"] }
124-
def pythonsSupported() { return ["3.8", "3.11"] }
125-
def pythonDefault() { return "3.8" }
126-
138+
@NonCPS
127139
def pipelineProfiles() {
128140
return [
129141
'packaging': ['artifacts', 'lint', 'debian', 'redhat'],
@@ -135,14 +147,19 @@ def pipelineProfiles() {
135147
]
136148
}
137149

150+
@NonCPS
138151
def pipelineProfileNames(putFirst) {
139152
set = pipelineProfiles().keySet() as List
140153
set = set - putFirst
141154
set.add(0, putFirst)
142155
return set
143156
}
144157

158+
@Field Map cachedTasks = null
159+
145160
def tasks() {
161+
if (null != cachedTasks) return cachedTasks
162+
146163
// Steps config
147164
def buildSteps = [
148165
'jar': [script: 'build-jars.sh', toCopy: null],
@@ -200,23 +217,30 @@ def tasks() {
200217

201218
def stepsMap = buildSteps + testSteps
202219

220+
// find the default JDK and the supported JDKs defined in the build.xml
221+
def build_xml = readFile(file: 'build.xml')
222+
def javaVersionDefaultMatch = (build_xml =~ /property\s*name="java\.default"\s*value="([^"]*)"/)
223+
assert javaVersionDefaultMatch, "java.default property not found in build.xml"
224+
def javaVersionDefault = javaVersionDefaultMatch[0][1]
225+
def javaVersionsSupportedMatch = (build_xml =~ /property\s*name="java\.supported"\s*value="([^"]*)"/)
226+
assert javaVersionsSupportedMatch, "java.supported property not found in build.xml"
227+
def javaVersionsSupported = javaVersionsSupportedMatch[0][1].split(',') as List
228+
203229
// define matrix axes
204230
def Map matrix_axes = [
205-
arch: archsSupported(),
206-
jdk: javaVersionsSupported(),
207-
python: pythonsSupported(),
231+
arch: archsSupported,
232+
jdk: javaVersionsSupported,
233+
python: pythonsSupported,
208234
cython: ['yes', 'no'],
209235
step: stepsMap.keySet(),
210236
split: (1..testSteps.values().splits.max()).toList()
211237
]
212238

213-
def javaVersionDefault = javaVersionDefault()
214-
215239
def List _axes = getMatrixAxes(matrix_axes).findAll { axis ->
216240
(isArchEnabled(axis['arch'])) && // skip disabled archs
217241
(isJdkEnabled(axis['jdk'])) && // skip disabled jdks
218242
(isStageEnabled(axis['step'])) && // skip disabled steps
219-
!(axis['python'] != pythonDefault() && 'cqlsh-test' != axis['step']) && // Use only python 3.8 for all tests but cqlsh-test
243+
!(axis['python'] != pythonDefault && 'cqlsh-test' != axis['step']) && // Use only python 3.8 for all tests but cqlsh-test
220244
!(axis['cython'] != 'no' && 'cqlsh-test' != axis['step']) && // cython only for cqlsh-test, disable for others
221245
!(axis['jdk'] != javaVersionDefault && ('cqlsh-test' == axis['step'] || 'simulator-dtest' == axis['step'] || axis['step'].contains('dtest-upgrade'))) && // run cqlsh-test, simulator-dtest, *dtest-upgrade only with jdk11
222246
// Disable splits for all but proper stages
@@ -238,7 +262,7 @@ def tasks() {
238262
}
239263
}
240264

241-
return tasks
265+
return cachedTasks = tasks
242266
}
243267

244268
@NonCPS
@@ -264,34 +288,14 @@ def getStepName(cell, command) {
264288

265289
def getJarTasks() {
266290
Map jars = tasks()['jars']
267-
assertJarTasks(jars)
291+
assert jars.size() > 1, "Nothing to build. Check parameters: jdk ${params.jdk}, arch ${params.architecture}"
268292
return jars
269293
}
270294

271-
def assertJarTasks(jars) {
272-
if (jars.size() < 2) {
273-
error("Nothing to build. Check parameters: jdk ${params.jdk} (${javaVersionsSupported()}), arch ${params.architecture} (${archsSupported()})")
274-
}
275-
}
276-
277295
def hasNonJarTasks() {
278296
return tasks()['tests'].size() > 1
279297
}
280298

281-
/**
282-
* Return the default JDK defined by build.xml
283-
**/
284-
def javaVersionDefault() {
285-
sh (returnStdout: true, script: 'grep \'property\\s*name=\"java.default\"\' build.xml | sed -ne \'s/.*value=\"\\([^\"]*\\)\".*/\\1/p\'').trim()
286-
}
287-
288-
/**
289-
* Return the supported JDKs defined by build.xml
290-
**/
291-
def javaVersionsSupported() {
292-
sh (returnStdout: true, script: 'grep \'property\\s*name=\"java.supported\"\' build.xml | sed -ne \'s/.*value=\"\\([^\"]*\\)\".*/\\1/p\'').trim().split(',')
293-
}
294-
295299
/**
296300
* Is this a post-commit build (or a pre-commit build)
297301
**/
@@ -412,12 +416,15 @@ def test(command, cell) {
412416
dir("build") {
413417
sh """
414418
mkdir -p test/output/${cell.step}
415-
find test/output -type f -name TEST*.xml -execdir mkdir -p jdk_${cell.jdk}/${cell.arch} ';' -execdir mv {} jdk_${cell.jdk}/${cell.arch}/{} ';'
419+
find test/output -type f -name "TEST*.xml" -execdir mkdir -p jdk_${cell.jdk}/${cell.arch} ';' -execdir mv {} jdk_${cell.jdk}/${cell.arch}/{} ';'
416420
find test/output -name cqlshlib.xml -execdir mv cqlshlib.xml ${cell.step}/cqlshlib${cell_suffix}.xml ';'
417421
find test/output -name nosetests.xml -execdir mv nosetests.xml ${cell.step}/nosetests${cell_suffix}.xml ';'
418422
"""
419423
junit testResults: "test/**/TEST-*.xml,test/**/cqlshlib*.xml,test/**/nosetests*.xml", testDataPublishers: [[$class: 'StabilityTestDataPublisher']]
420-
sh "find test/output -type f -name *.xml -exec sh -c 'xz -f {} &' ';' ; wait ; find test/output -type f -name *.xml.xz | wc -l"
424+
sh """
425+
find test/output -type f -name "*.xml" -print0 | xargs -0 -r -n1 -P"\$(nproc)" xz -f
426+
echo "test result files compressed"; find test/output -type f -name "*.xml.xz" | wc -l
427+
"""
421428
archiveArtifacts artifacts: "test/logs/**,test/**/TEST-*.xml.xz,test/**/cqlshlib*.xml.xz,test/**/nosetests*.xml.xz", fingerprint: true
422429
copyToNightlies("${logfile}, test/logs/**", "${cell.step}/${cell.arch}/jdk${cell.jdk}/python${cell.python}/cython_${cell.cython}/" + "split_${cell.split}_${splits}".replace("/", "_"))
423430
}
@@ -557,8 +564,8 @@ def generateTestReports() {
557564
// TODO parallelised for loop
558565
// TODO results_details.tar.xz needs to include all logs for failed tests
559566
sh """${script_vars} (
560-
find build/test/output -type f -name *.xml.xz | wc -l
561-
find build/test/output -name *.xml.xz -exec sh -c 'xz -f --decompress {} &' ';' ; wait
567+
echo "test result files to decompress"; find build/test/output -type f -name "*.xml.xz" | wc -l
568+
find build/test/output -type f -name "*.xml.xz" -print0 | xargs -0 -r -n1 -P"\$(nproc)" xz -f --decompress
562569
563570
for target in \$(ls build/test/output/) ; do
564571
if test -d build/test/output/\${target} ; then

0 commit comments

Comments
 (0)