blob: 83e0b51a009140c2af04d8c61953db2487faf63b [file] [log] [blame]
#!/usr/bin/env groovy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
def call(Map params = [:]) {
Map taskContext = [:]
def branchesToNotify = params.containsKey("branchesToNotify") ? params.branchesToNotify : ['master', 'main']
try {
def buildProperties = []
if (env.BRANCH_NAME == 'master') {
// set build retention time first
buildProperties.add(buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '5', daysToKeepStr: '15', numToKeepStr: '10')))
// ensure a build is done every month
buildProperties.add(pipelineTriggers([cron('@monthly')]))
} else {
buildProperties.add(buildDiscarder(logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '2', daysToKeepStr: '7', numToKeepStr: '3')))
}
properties(buildProperties)
// now determine the matrix of parallel builds
def oses = params.containsKey('os') ? params.os : ['linux']
// minimum, LTS, current and next ea
def jdks = params.containsKey('jdks') ? params.jdks : params.containsKey('jdk') ? params.jdk : ['8','11','17','21']
def jdkMin = jdks[0];
def mavens = params.containsKey('maven') ? params.maven : ['3.6.x', '3.9.x']
// def failFast = params.containsKey('failFast') ? params.failFast : true
// Just temporarily
def failFast = false;
def siteJdks = params.containsKey('siteJdk') ? params.siteJdk : ['11']
def siteMvn = params.containsKey('siteMvn') ? params.siteMvn : '3.9.x'
def tmpWs = params.containsKey('tmpWs') ? params.tmpWs : false
taskContext['failFast'] = failFast;
taskContext['tmpWs'] = tmpWs;
taskContext['archives'] = params.archives
taskContext['siteWithPackage'] = params.containsKey('siteWithPackage') ? params.siteWithPackage : false // workaround for MNG-7289
Map tasks = [failFast: failFast]
boolean first = true
for (String os in oses) {
for (def mvn in mavens) {
for (def jdk in jdks) {
doCreateTask(os, jdk, mvn, tasks, first, 'build', taskContext)
}
}
for (def jdk in siteJdks) {
// doesn't work for multimodules yet
doCreateTask( os, jdk, siteMvn, tasks, first, 'site', taskContext )
}
// run with apache-release profile, consider it a dryRun with SNAPSHOTs
// doCreateTask( os, siteJdk, siteMvn, tasks, first, 'release', taskContext )
}
// run the parallel builds
parallel(tasks)
// JENKINS-34376 seems to make it hard to detect the aborted builds
} catch (org.jenkinsci.plugins.workflow.steps.FlowInterruptedException e) {
// this ambiguous condition means a user probably aborted
if (e.causes.size() == 0) {
currentBuild.result = "ABORTED"
} else {
currentBuild.result = "FAILURE"
}
throw e
} catch (hudson.AbortException e) {
// this ambiguous condition means during a shell step, user probably aborted
if (e.getMessage().contains('script returned exit code 143')) {
currentBuild.result = "ABORTED"
} else {
currentBuild.result = "FAILURE"
}
throw e
} catch (InterruptedException e) {
currentBuild.result = "ABORTED"
throw e
} catch (Throwable e) {
currentBuild.result = "FAILURE"
throw e
} finally {
// notify completion
if (taskContext.failingFast != null) {
echo "***** FAST FAILURE *****\n\nFast failure triggered by ${taskContext.failingFast}\n\n***** FAST FAILURE *****"
}
if (branchesToNotify.contains(env.BRANCH_NAME)) {
stage("Notifications") {
jenkinsNotify()
}
}
}
}
def doCreateTask( os, jdk, maven, tasks, first, plan, taskContext )
{
String label = jenkinsEnv.labelForOS(os);
String jdkName = jenkinsEnv.jdkFromVersion(os, "${jdk}")
String mvnName = jenkinsEnv.mvnFromVersion(os, "${maven}")
echo "OS: ${os} JDK: ${jdk} Maven: ${maven} => Label: ${label} JDK: ${jdkName} Maven: ${mvnName}"
if (label == null || jdkName == null || mvnName == null) {
echo "Skipping ${os}-jdk${jdk} as unsupported by Jenkins Environment"
return;
}
def cmd = [
'mvn', '-V',
'-DtrimStackTrace=false',
'-P+run-its',
'-Dmaven.test.failure.ignore=true',
'-Dfindbugs.failOnError=false',
'-e',
]
if (!first) {
cmd += '-Dfindbugs.skip=true'
// } else { // Requires authorization on SonarQube first
// cmd += 'sonar:sonar'
}
if (plan == 'build') {
cmd += 'clean'
if (env.BRANCH_NAME == 'master' && jdk == '21' && maven == '3.9.x' && os == 'linux' ) {
cmd += 'deploy'
} else {
cmd += 'verify -Dpgpverify.skip'
}
}
else if (plan == 'site') {
if (taskContext.siteWithPackage) {
cmd += 'package'
}
cmd += 'site'
cmd += '-Preporting'
}
else if (plan == 'release') {
cmd += 'verify'
cmd += '-Papache-release'
}
def disablePublishers = !first
first = false
String stageId = "${os}-jdk${jdk}-m${maven}_${plan}"
tasks[stageId] = {
node(jenkinsEnv.nodeSelection(label)) {
def wsDir = pwd()
def stageDir = stageId
if (os == 'windows' && taskContext.tmpWs) {
// wsDir = "$TEMP\\$BUILD_TAG" // or use F:\jenkins\jenkins-slave\workspace or F:\short
wsDir = 'F:\\short\\' + "$BUILD_TAG".replaceAll(/(.+)maven-(.+)-plugin(.*)/) { "m-${it[2]}-p${it[3]}" }
stageDir = "j${jdk}m${maven}" + plan.take(1)
}
ws( dir : "$wsDir" )
{
stage("Build ${stageId}") {
if (taskContext.failingFast != null) {
cleanWs()
echo "[FAIL FAST] ${taskContext.failingFast} has failed. Skipping ${stageId}."
} else try {
def localRepo = "../.maven_repositories/${env.EXECUTOR_NUMBER}"
println "Local Repo (${stageId}): ${localRepo}"
println "Jdk $jdkName, mvnName $mvnName"
cmd += " -Dmaven.repo.local=../.maven_repositories/${env.EXECUTOR_NUMBER}"
cmd += " -Dinvoker.writeJunitReport=true -B"
withEnv(["JAVA_HOME=${ tool "$jdkName" }",
"PATH+MAVEN=${ tool "$jdkName" }/bin:${tool "$mvnName"}/bin",
"MAVEN_OPTS=-Xms2g -Xmx4g -Djava.awt.headless=true"]) {
dir (stageDir) {
checkout scm
if (isUnix()) {
sh 'df -hT'
sh cmd.join(' ')
} else {
bat 'wmic logicaldisk get size,freespace,caption'
bat cmd.join(' ')
}
}
}
} catch (Throwable e) {
archiveDirs(taskContext.archives, stageDir)
if (!taskContext.failFast) {
throw e
} else if (taskContext.failingFast == null) {
taskContext.failingFast = stageId
echo "[FAIL FAST] This is the first failure and likely root cause"
throw e
} else {
echo "[FAIL FAST] ${taskContext.failingFast} had first failure, ignoring ${e.message}"
}
} finally {
junit testResults: '**/target/surefire-reports/*.xml,**/target/failsafe-reports/*.xml,**/target/invoker-reports/TEST*.xml', allowEmptyResults: true
cleanWs()
}
}
}
}
}
}
def archiveDirs(archives, stageDir) {
if (archives != null) {
dir(stageDir) {
archives.each { archivePrefix, pathToContent ->
zip(zipFile: "${archivePrefix}-${stageDir}.zip", dir: pathToContent, archive: true)
}
}
}
}