2021-07-06 06:55:10 -04:00
|
|
|
/*
|
|
|
|
* Hibernate, Relational Persistence for Idiomatic Java
|
|
|
|
*
|
|
|
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
|
|
|
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
import groovy.transform.Field
|
2022-04-11 09:41:56 -04:00
|
|
|
import io.jenkins.blueocean.rest.impl.pipeline.PipelineNodeGraphVisitor
|
|
|
|
import io.jenkins.blueocean.rest.impl.pipeline.FlowNodeWrapper
|
|
|
|
import org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper
|
2021-07-06 06:55:10 -04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* See https://github.com/hibernate/hibernate-jenkins-pipeline-helpers
|
|
|
|
*/
|
|
|
|
@Library('hibernate-jenkins-pipeline-helpers@1.5') _
|
|
|
|
import org.hibernate.jenkins.pipeline.helpers.job.JobHelper
|
|
|
|
|
2022-06-09 08:17:49 -04:00
|
|
|
@Field final String DEFAULT_JDK_VERSION = '11'
|
2022-06-09 08:25:35 -04:00
|
|
|
@Field final String DEFAULT_JDK_TOOL = "OpenJDK ${DEFAULT_JDK_VERSION} Latest"
|
2021-07-06 06:55:10 -04:00
|
|
|
@Field final String NODE_PATTERN_BASE = 'Worker&&Containers'
|
|
|
|
@Field List<BuildEnvironment> environments
|
|
|
|
|
|
|
|
this.helper = new JobHelper(this)
|
|
|
|
|
|
|
|
helper.runWithNotification {
|
|
|
|
stage('Configure') {
|
|
|
|
this.environments = [
|
2022-06-09 08:17:49 -04:00
|
|
|
// new BuildEnvironment( dbName: 'h2' ),
|
|
|
|
// new BuildEnvironment( dbName: 'hsqldb' ),
|
|
|
|
// new BuildEnvironment( dbName: 'derby' ),
|
2022-09-20 03:26:06 -04:00
|
|
|
// new BuildEnvironment( dbName: 'mysql' ),
|
2022-06-09 08:17:49 -04:00
|
|
|
// new BuildEnvironment( dbName: 'mariadb' ),
|
2022-09-20 03:26:06 -04:00
|
|
|
// new BuildEnvironment( dbName: 'postgresql' ),
|
2022-10-19 13:25:16 -04:00
|
|
|
// new BuildEnvironment( dbName: 'edb' ),
|
2022-06-09 08:17:49 -04:00
|
|
|
// new BuildEnvironment( dbName: 'oracle' ),
|
|
|
|
// new BuildEnvironment( dbName: 'db2' ),
|
|
|
|
// new BuildEnvironment( dbName: 'mssql' ),
|
|
|
|
// new BuildEnvironment( dbName: 'sybase' ),
|
2022-10-21 10:06:45 -04:00
|
|
|
// Don't build with HANA by default, but only do it nightly until we receive a 3rd instance
|
|
|
|
// new BuildEnvironment( dbName: 'hana_cloud', dbLockableResource: 'hana-cloud', dbLockResourceAsHost: true ),
|
2022-10-11 08:35:57 -04:00
|
|
|
new BuildEnvironment( node: 's390x' ),
|
2022-10-21 10:22:50 -04:00
|
|
|
new BuildEnvironment( dbName: 'tidb', node: 'tidb',
|
2022-10-11 08:35:57 -04:00
|
|
|
notificationRecipients: 'tidb_hibernate@pingcap.com' ),
|
2022-06-09 08:25:35 -04:00
|
|
|
new BuildEnvironment( testJdkVersion: '17' ),
|
2023-01-18 04:08:17 -05:00
|
|
|
// We want to enable preview features when testing newer builds of OpenJDK:
|
2022-06-09 08:41:39 -04:00
|
|
|
// even if we don't use these features, just enabling them can cause side effects
|
|
|
|
// and it's useful to test that.
|
2023-01-18 04:07:53 -05:00
|
|
|
new BuildEnvironment( testJdkVersion: '20', testJdkLauncherArgs: '--enable-preview' ),
|
2023-06-13 06:04:56 -04:00
|
|
|
new BuildEnvironment( testJdkVersion: '21', testJdkLauncherArgs: '--enable-preview' ),
|
|
|
|
new BuildEnvironment( testJdkVersion: '22', testJdkLauncherArgs: '--enable-preview' )
|
2021-07-06 06:55:10 -04:00
|
|
|
];
|
|
|
|
|
2022-09-23 11:43:11 -04:00
|
|
|
if ( env.CHANGE_ID ) {
|
|
|
|
if ( pullRequest.labels.contains( 'cockroachdb' ) ) {
|
2023-01-10 12:13:14 -05:00
|
|
|
this.environments.add( new BuildEnvironment( dbName: 'cockroachdb', node: 'cockroachdb', longRunning: true ) )
|
2022-09-23 11:43:11 -04:00
|
|
|
}
|
2022-10-21 10:06:45 -04:00
|
|
|
if ( pullRequest.labels.contains( 'hana' ) ) {
|
|
|
|
this.environments.add( new BuildEnvironment( dbName: 'hana_cloud', dbLockableResource: 'hana-cloud', dbLockResourceAsHost: true ) )
|
|
|
|
}
|
2023-08-07 09:54:44 -04:00
|
|
|
if ( pullRequest.labels.contains( 'sybase' ) ) {
|
|
|
|
this.environments.add( new BuildEnvironment( dbName: 'sybase_jconn' ) )
|
|
|
|
}
|
2022-09-23 11:43:11 -04:00
|
|
|
}
|
|
|
|
|
2021-07-06 06:55:10 -04:00
|
|
|
helper.configure {
|
|
|
|
file 'job-configuration.yaml'
|
|
|
|
// We don't require the following, but the build helper plugin apparently does
|
|
|
|
jdk {
|
2022-10-11 08:49:17 -04:00
|
|
|
defaultTool DEFAULT_JDK_TOOL
|
2021-07-06 06:55:10 -04:00
|
|
|
}
|
|
|
|
maven {
|
|
|
|
defaultTool 'Apache Maven 3.8'
|
|
|
|
}
|
|
|
|
}
|
|
|
|
properties([
|
|
|
|
buildDiscarder(
|
2022-02-07 12:16:07 -05:00
|
|
|
logRotator(daysToKeepStr: '30', numToKeepStr: '10')
|
2021-07-06 06:55:10 -04:00
|
|
|
),
|
2022-02-04 04:25:58 -05:00
|
|
|
// If two builds are about the same branch or pull request,
|
|
|
|
// the older one will be aborted when the newer one starts.
|
|
|
|
disableConcurrentBuilds(abortPrevious: true),
|
2021-07-06 06:55:10 -04:00
|
|
|
helper.generateNotificationProperty()
|
|
|
|
])
|
|
|
|
}
|
|
|
|
|
2022-03-25 10:36:38 -04:00
|
|
|
// Avoid running the pipeline on branch indexing
|
|
|
|
if (currentBuild.getBuildCauses().toString().contains('BranchIndexingCause')) {
|
|
|
|
print "INFO: Build skipped due to trigger being Branch Indexing"
|
|
|
|
currentBuild.result = 'ABORTED'
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2021-07-06 06:55:10 -04:00
|
|
|
stage('Build') {
|
|
|
|
Map<String, Closure> executions = [:]
|
2022-04-08 04:39:36 -04:00
|
|
|
Map<String, Map<String, String>> state = [:]
|
2021-07-06 06:55:10 -04:00
|
|
|
environments.each { BuildEnvironment buildEnv ->
|
2022-04-06 12:52:56 -04:00
|
|
|
// Don't build environments for newer JDKs when this is a PR
|
2022-06-09 08:25:35 -04:00
|
|
|
if ( helper.scmSource.pullRequest && buildEnv.testJdkVersion ) {
|
2022-06-09 08:17:49 -04:00
|
|
|
return
|
2022-04-06 12:52:56 -04:00
|
|
|
}
|
2022-04-08 05:13:30 -04:00
|
|
|
state[buildEnv.tag] = [:]
|
2021-07-06 06:55:10 -04:00
|
|
|
executions.put(buildEnv.tag, {
|
2022-06-09 08:17:49 -04:00
|
|
|
runBuildOnNode(buildEnv.node ?: NODE_PATTERN_BASE) {
|
|
|
|
def testJavaHome
|
|
|
|
if ( buildEnv.testJdkVersion ) {
|
|
|
|
testJavaHome = tool(name: "OpenJDK ${buildEnv.testJdkVersion} Latest", type: 'jdk')
|
|
|
|
}
|
2022-10-11 08:49:17 -04:00
|
|
|
def javaHome = tool(name: DEFAULT_JDK_TOOL, type: 'jdk')
|
2021-10-20 06:15:44 -04:00
|
|
|
// Use withEnv instead of setting env directly, as that is global!
|
|
|
|
// See https://github.com/jenkinsci/pipeline-plugin/blob/master/TUTORIAL.md
|
2022-06-09 08:17:49 -04:00
|
|
|
withEnv(["JAVA_HOME=${javaHome}", "PATH+JAVA=${javaHome}/bin"]) {
|
2022-06-09 08:41:39 -04:00
|
|
|
state[buildEnv.tag]['additionalOptions'] = ''
|
2022-06-09 08:17:49 -04:00
|
|
|
if ( testJavaHome ) {
|
2022-06-09 08:41:39 -04:00
|
|
|
state[buildEnv.tag]['additionalOptions'] = state[buildEnv.tag]['additionalOptions'] +
|
|
|
|
" -Ptest.jdk.version=${buildEnv.testJdkVersion} -Porg.gradle.java.installations.paths=${javaHome},${testJavaHome}"
|
2022-04-07 15:17:01 -04:00
|
|
|
}
|
2022-06-09 08:41:39 -04:00
|
|
|
if ( buildEnv.testJdkLauncherArgs ) {
|
|
|
|
state[buildEnv.tag]['additionalOptions'] = state[buildEnv.tag]['additionalOptions'] +
|
2022-06-09 11:24:52 -04:00
|
|
|
" -Ptest.jdk.launcher.args=${buildEnv.testJdkLauncherArgs}"
|
2022-04-08 04:39:36 -04:00
|
|
|
}
|
|
|
|
state[buildEnv.tag]['containerName'] = null;
|
2021-10-20 06:15:44 -04:00
|
|
|
stage('Checkout') {
|
|
|
|
checkout scm
|
2021-07-06 06:55:10 -04:00
|
|
|
}
|
2021-10-20 06:15:44 -04:00
|
|
|
try {
|
|
|
|
stage('Start database') {
|
|
|
|
switch (buildEnv.dbName) {
|
2022-11-03 10:15:01 -04:00
|
|
|
case "edb":
|
2023-09-04 10:51:59 -04:00
|
|
|
docker.image('quay.io/enterprisedb/edb-postgres-advanced:15.4-3.3-postgis').pull()
|
2022-11-03 10:15:01 -04:00
|
|
|
sh "./docker_db.sh edb"
|
|
|
|
state[buildEnv.tag]['containerName'] = "edb"
|
|
|
|
break;
|
2023-08-07 09:54:44 -04:00
|
|
|
case "sybase_jconn":
|
|
|
|
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
|
|
|
docker.image('nguoianphu/docker-sybase').pull()
|
|
|
|
}
|
|
|
|
sh "./docker_db.sh sybase"
|
|
|
|
state[buildEnv.tag]['containerName'] = "sybase"
|
|
|
|
break;
|
2022-11-03 10:15:01 -04:00
|
|
|
case "cockroachdb":
|
|
|
|
docker.withRegistry('https://index.docker.io/v1/', 'hibernateci.hub.docker.com') {
|
2023-09-04 10:51:59 -04:00
|
|
|
docker.image('cockroachdb/cockroach:v23.1.8').pull()
|
2022-11-03 10:15:01 -04:00
|
|
|
}
|
|
|
|
sh "./docker_db.sh cockroachdb"
|
|
|
|
state[buildEnv.tag]['containerName'] = "cockroach"
|
|
|
|
break;
|
2021-10-20 06:15:44 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
stage('Test') {
|
2022-10-11 08:35:57 -04:00
|
|
|
String cmd = "./ci/build.sh ${buildEnv.additionalOptions ?: ''} ${state[buildEnv.tag]['additionalOptions'] ?: ''}"
|
|
|
|
withEnv(["RDBMS=${buildEnv.dbName}"]) {
|
|
|
|
try {
|
|
|
|
if (buildEnv.dbLockableResource == null) {
|
2023-08-07 09:54:44 -04:00
|
|
|
withCredentials([file(credentialsId: 'sybase-jconnect-driver', variable: 'jconnect_driver')]) {
|
2023-08-14 09:32:10 -04:00
|
|
|
sh 'cp -f $jconnect_driver ./drivers/jconn4.jar'
|
2023-08-07 09:54:44 -04:00
|
|
|
timeout( [time: buildEnv.longRunning ? 480 : 120, unit: 'MINUTES'] ) {
|
|
|
|
sh cmd
|
|
|
|
}
|
2022-10-11 08:35:57 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2022-10-21 10:06:45 -04:00
|
|
|
lock(label: buildEnv.dbLockableResource, quantity: 1, variable: 'LOCKED_RESOURCE') {
|
2022-10-21 04:28:17 -04:00
|
|
|
if ( buildEnv.dbLockResourceAsHost ) {
|
|
|
|
cmd += " -DdbHost=${LOCKED_RESOURCE}"
|
|
|
|
}
|
2022-11-03 10:15:01 -04:00
|
|
|
timeout( [time: buildEnv.longRunning ? 480 : 120, unit: 'MINUTES'] ) {
|
2022-10-11 08:35:57 -04:00
|
|
|
sh cmd
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
finally {
|
|
|
|
junit '**/target/test-results/test/*.xml,**/target/test-results/testKitTest/*.xml'
|
|
|
|
}
|
2021-10-20 06:15:44 -04:00
|
|
|
}
|
2021-07-06 06:55:10 -04:00
|
|
|
}
|
|
|
|
}
|
2021-10-20 06:15:44 -04:00
|
|
|
finally {
|
2022-04-08 04:39:36 -04:00
|
|
|
if ( state[buildEnv.tag]['containerName'] != null ) {
|
|
|
|
sh "docker rm -f ${state[buildEnv.tag]['containerName']}"
|
2021-10-20 06:15:44 -04:00
|
|
|
}
|
2021-10-25 04:17:36 -04:00
|
|
|
// Skip this for PRs
|
|
|
|
if ( !env.CHANGE_ID && buildEnv.notificationRecipients != null ) {
|
2022-04-08 04:39:36 -04:00
|
|
|
handleNotifications(currentBuild, buildEnv)
|
2021-10-20 06:15:44 -04:00
|
|
|
}
|
2021-07-06 06:55:10 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
parallel(executions)
|
|
|
|
}
|
|
|
|
|
|
|
|
} // End of helper.runWithNotification
|
|
|
|
|
|
|
|
// Job-specific helpers
|
|
|
|
|
2022-06-09 08:17:49 -04:00
|
|
|
class BuildEnvironment {
|
|
|
|
String testJdkVersion
|
2022-06-09 08:41:39 -04:00
|
|
|
String testJdkLauncherArgs
|
2022-06-09 08:17:49 -04:00
|
|
|
String dbName = 'h2'
|
|
|
|
String node
|
2022-10-11 08:35:57 -04:00
|
|
|
String dbLockableResource
|
2022-10-21 04:28:17 -04:00
|
|
|
boolean dbLockResourceAsHost
|
2022-10-11 08:35:57 -04:00
|
|
|
String additionalOptions
|
2022-06-09 08:17:49 -04:00
|
|
|
String notificationRecipients
|
2022-09-23 11:43:11 -04:00
|
|
|
boolean longRunning
|
2022-04-07 15:17:01 -04:00
|
|
|
|
2021-07-06 06:55:10 -04:00
|
|
|
String toString() { getTag() }
|
2022-10-11 08:35:57 -04:00
|
|
|
String getTag() { "${node ? node + "_" : ''}${testJdkVersion ? 'jdk_' + testJdkVersion + '_' : '' }${dbName}" }
|
2023-09-04 10:51:59 -04:00
|
|
|
String getRdbms() { dbName.contains("_") ? dbName.substring(0, dbName.indexOf('_')) : dbName }
|
2021-07-06 06:55:10 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void runBuildOnNode(String label, Closure body) {
|
|
|
|
node( label ) {
|
|
|
|
pruneDockerContainers()
|
|
|
|
try {
|
2022-09-21 05:23:07 -04:00
|
|
|
body()
|
2021-07-06 06:55:10 -04:00
|
|
|
}
|
|
|
|
finally {
|
2021-08-05 05:33:43 -04:00
|
|
|
// If this is a PR, we clean the workspace at the end
|
|
|
|
if ( env.CHANGE_BRANCH != null ) {
|
|
|
|
cleanWs()
|
|
|
|
}
|
2021-07-06 06:55:10 -04:00
|
|
|
pruneDockerContainers()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void pruneDockerContainers() {
|
2021-10-12 08:58:19 -04:00
|
|
|
if ( !sh( script: 'command -v docker || true', returnStdout: true ).trim().isEmpty() ) {
|
2021-07-06 06:55:10 -04:00
|
|
|
sh 'docker container prune -f || true'
|
|
|
|
sh 'docker image prune -f || true'
|
|
|
|
sh 'docker network prune -f || true'
|
|
|
|
sh 'docker volume prune -f || true'
|
|
|
|
}
|
2021-10-12 08:58:19 -04:00
|
|
|
}
|
2022-04-08 04:39:36 -04:00
|
|
|
|
|
|
|
void handleNotifications(currentBuild, buildEnv) {
|
2022-04-11 09:41:56 -04:00
|
|
|
def currentResult = getParallelResult(currentBuild, buildEnv.tag)
|
|
|
|
boolean success = currentResult == 'SUCCESS' || currentResult == 'UNKNOWN'
|
|
|
|
def previousResult = currentBuild.previousBuild == null ? null : getParallelResult(currentBuild.previousBuild, buildEnv.tag)
|
2022-04-08 04:39:36 -04:00
|
|
|
|
|
|
|
// Ignore success after success
|
2022-04-11 09:41:56 -04:00
|
|
|
if ( !( success && previousResult == 'SUCCESS' ) ) {
|
2022-04-08 04:39:36 -04:00
|
|
|
def subject
|
|
|
|
def body
|
|
|
|
if ( success ) {
|
|
|
|
if ( previousResult != 'SUCCESS' && previousResult != null ) {
|
|
|
|
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Fixed"
|
|
|
|
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Fixed:</p>
|
|
|
|
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Success"
|
|
|
|
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Success:</p>
|
|
|
|
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
|
|
|
}
|
|
|
|
}
|
2022-08-31 02:31:23 -04:00
|
|
|
else if (currentBuild.rawBuild.getActions(jenkins.model.InterruptedBuildAction.class).isEmpty()) {
|
|
|
|
// If there are interrupted build actions, this means the build was cancelled, probably superseded
|
|
|
|
// Thanks to https://issues.jenkins.io/browse/JENKINS-43339 for the "hack" to determine this
|
|
|
|
if ( currentResult == 'FAILURE' ) {
|
|
|
|
if ( previousResult != null && previousResult == "FAILURE" ) {
|
|
|
|
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Still failing"
|
|
|
|
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Still failing:</p>
|
|
|
|
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Failure"
|
|
|
|
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - Failure:</p>
|
|
|
|
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
|
|
|
}
|
2022-04-08 04:39:36 -04:00
|
|
|
}
|
|
|
|
else {
|
2022-08-31 02:31:23 -04:00
|
|
|
subject = "${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - ${currentResult}"
|
|
|
|
body = """<p>${env.JOB_NAME} - Build ${env.BUILD_NUMBER} - ${currentResult}:</p>
|
2022-04-08 04:39:36 -04:00
|
|
|
<p>Check console output at <a href='${env.BUILD_URL}'>${env.BUILD_URL}</a> to view the results.</p>"""
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
emailext(
|
|
|
|
subject: subject,
|
|
|
|
body: body,
|
|
|
|
to: buildEnv.notificationRecipients
|
|
|
|
)
|
|
|
|
}
|
2022-04-11 09:41:56 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
@NonCPS
|
|
|
|
String getParallelResult( RunWrapper build, String parallelBranchName ) {
|
|
|
|
def visitor = new PipelineNodeGraphVisitor( build.rawBuild )
|
|
|
|
def branch = visitor.pipelineNodes.find{ it.type == FlowNodeWrapper.NodeType.PARALLEL && parallelBranchName == it.displayName }
|
2022-04-12 05:15:26 -04:00
|
|
|
if ( branch == null ) {
|
|
|
|
echo "Couldn't find parallel branch name '$parallelBranchName'. Available parallel branch names:"
|
|
|
|
visitor.pipelineNodes.findAll{ it.type == FlowNodeWrapper.NodeType.PARALLEL }.each{
|
|
|
|
echo " - ${it.displayName}"
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
2022-04-11 09:41:56 -04:00
|
|
|
return branch.status.result
|
2021-07-06 06:55:10 -04:00
|
|
|
}
|