Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 208 additions & 28 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -1,34 +1,53 @@
@Library('shared-libraries') _

def getJavaHomePath() {
if (env.JAVA_VERSION == "JAVA21") {
return "/home/builder/java/jdk-21.0.1"
} else {
return "/home/builder/java/jdk-17.0.2"
}
if (params.arm_regressions) {
def version = (env.JAVA_VERSION == "JAVA21") ? "21" : "17"
def path = "/usr/lib/jvm/java-${version}-amazon-corretto.aarch64"
return path
} else {
if (env.JAVA_VERSION == "JAVA21") {
return "/home/builder/java/jdk-21.0.1"
} else {
return "/home/builder/java/jdk-17.0.2"
}
}
}

def getPlatform() {
return params.arm_regressions ? "linux/arm64" : "linux/amd64"
}

def setConverters() {
return params.arm_regressions ? "false" :"true"
}

def setupDockerMarkLogic(String image) {
cleanupDocker()
sh label: 'mlsetup', script: '''#!/bin/bash
echo "Removing any running MarkLogic server and clean up MarkLogic data directory"
sudo /usr/local/sbin/mladmin remove
sudo /usr/local/sbin/mladmin cleandata
cd java-client-api
docker compose down -v || true
docker volume prune -f
echo "Using image: "''' + image + '''
docker pull ''' + image + '''
MARKLOGIC_IMAGE=''' + image + ''' MARKLOGIC_LOGS_VOLUME=marklogicLogs docker compose up -d --build
export JAVA_HOME=$JAVA_HOME_DIR
export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
export PATH=$JAVA_HOME/bin:$PATH
cleanupDocker()
sh label: 'mlsetup', script: '''#!/bin/bash
echo "Removing any running MarkLogic server and clean up MarkLogic data directory"
sudo /usr/local/sbin/mladmin remove
sudo /usr/local/sbin/mladmin cleandata
cd java-client-api
export PLATFORM=$PLATFORM
export SET_CONVERTERS=$SET_CONVERTERS
Comment on lines +32 to +33
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The environment variable names are identical to the variable names being assigned ($PLATFORM and $SET_CONVERTERS). This creates ambiguity about which values are being used and makes the code harder to follow. Consider renaming the shell variables to avoid shadowing, e.g., export PLATFORM=$PLATFORM_VALUE or use more descriptive names that clarify the source.

Suggested change
export PLATFORM=$PLATFORM
export SET_CONVERTERS=$SET_CONVERTERS

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing here - avoid using "SET_CONVERTERS", use "MARKLOGIC_INSTALL_CONVERTERS".

docker compose down -v || true
docker volume prune -f

echo "Using image: "''' + image + '''
docker pull ''' + image + '''

MARKLOGIC_IMAGE=''' + image + ''' MARKLOGIC_LOGS_VOLUME=marklogicLogs \
docker compose up -d --build
echo "Waiting for MarkLogic server to initialize."
sleep 60
Comment on lines +42 to +43
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The 60-second sleep is a magic number without explanation of why this duration was chosen. Consider adding a comment explaining the initialization time requirement or defining this as a named constant for better maintainability.

Copilot uses AI. Check for mistakes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this sleep command, it's no longer needed (remove the echo command too).

export JAVA_HOME=$JAVA_HOME_DIR
export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
export PATH=$GRADLE_USER_HOME:$JAVA_HOME/bin:$PATH
./gradlew -i mlWaitTillReady
sleep 3
./gradlew -i mlWaitTillReady
./gradlew mlTestConnections
./gradlew -i mlDeploy mlReloadSchemas
'''
./gradlew mlTestConnections
./gradlew -i mlDeploy mlReloadSchemas
'''
}

def runTests(String image) {
Expand Down Expand Up @@ -171,23 +190,28 @@ pipeline {

parameters {
booleanParam(name: 'regressions', defaultValue: false, description: 'indicator if build is for regressions')
booleanParam(name: 'arm_regressions', defaultValue: false, description: 'indicator if build is for ARM regressions')
string(name: 'JAVA_VERSION', defaultValue: 'JAVA17', description: 'Either JAVA17 or JAVA21')
string(name: 'MARKLOGIC_IMAGE_TAGS', defaultValue: 'marklogic-server-ubi:latest-11,marklogic-server-ubi:latest-12', description: 'Comma-delimited list of MarkLogic image tags including variant (e.g., marklogic-server-ubi:latest-11,marklogic-server-ubi-rootless:11.3.2). The registry/org (ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic) path will be prepended automatically.')
string(name: 'packagefile', defaultValue: 'Packagedependencies', description: 'package dependency file')
string(name: 'terraformBranch', defaultValue: 'master', description: 'Branch of terraform-templates repo to use')
}

environment {
JAVA_HOME_DIR = getJavaHomePath()
GRADLE_DIR = ".gradle"
DMC_USER = credentials('MLBUILD_USER')
DMC_PASSWORD = credentials('MLBUILD_PASSWORD')
PLATFORM = getPlatform()
SET_CONVERTERS = setConverters()
}

stages {

stage('pull-request-tests') {
when {
not {
expression { return params.regressions }
expression {
return !params.regressions && !params.arm_regressions
}
Comment on lines +213 to 215
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The multi-line expression formatting is inconsistent with other single-line expressions in the file (e.g., lines 253-254, 274-275). For consistency, consider formatting this as a single line: expression { return !params.regressions && !params.arm_regressions }.

Suggested change
expression {
return !params.regressions && !params.arm_regressions
}
expression { return !params.regressions && !params.arm_regressions }

Copilot uses AI. Check for mistakes.
}
steps {
Expand Down Expand Up @@ -225,7 +249,10 @@ pipeline {
when {
branch 'develop'
not {
expression { return params.regressions }
anyOf {
expression { return params.regressions }
expression { return params.arm_regressions }
}
}
}
steps {
Expand All @@ -244,7 +271,8 @@ pipeline {
when {
allOf {
branch 'develop'
expression { return params.regressions }
expression { return params.regressions }
expression { return !params.arm_regressions }
}
}

Expand All @@ -270,5 +298,157 @@ pipeline {
}
}
}

stage('provisionInfrastructure'){
when {
allOf {
branch 'develop'
expression { return params.arm_regressions }
expression { return !params.regressions }
}
}
agent {label 'javaClientLinuxPool'}

steps{
script {


def deploymentResult = deployAWSInstance([
instanceName: "java-client-instance-${BUILD_NUMBER}",
region: 'us-west-2',
credentialsId: 'headlessDbUserEC2',
role: 'role-headless-testing',
roleAccount: '343869654284',
branch: params.terraformBranch
])

echo "✅ Instance deployed: ${deploymentResult.privateIp}"
echo "✅ Terraform directory: ${deploymentResult.terraformDir}"
echo "✅ Workspace: ${deploymentResult.workspace}"
echo "✅ Status: ${deploymentResult.status}"

// Store deployment info for cleanup
env.DEPLOYMENT_INSTANCE_NAME = deploymentResult.instanceName
env.DEPLOYMENT_REGION = deploymentResult.region
env.DEPLOYMENT_TERRAFORM_DIR = deploymentResult.terraformDir
env.EC2_PRIVATE_IP = deploymentResult.privateIp

def nodeName = "java-client-agent-${BUILD_NUMBER}"
def remoteFS = "/space/jenkins_home"
def labels = "java-client-agent-${BUILD_NUMBER}"
def instanceIp = env.EC2_PRIVATE_IP

// Use shared library for volume attachment
def volumeResult = attachInstanceVolumes([
instanceIp: instanceIp,
remoteFS: remoteFS,
packageFile: params.packagefile,
setupScriptPath: 'terraform-templates/arm-server-build/setup_volume.sh',
packageDir: 'terraform-templates/java-client-api',
initScriptsDir: 'terraform-templates/java-client-api/scripts',
initScriptsFile: 'terraform-templates/java-client-api/initscripts',
branch: params.terraformBranch

])

echo "✅ Volume attachment completed: ${volumeResult.volumeAttached}"
echo "✅ Java installed: ${volumeResult.javaInstalled}"
echo "✅ Dependencies installed: ${volumeResult.dependenciesInstalled}"

// Use shared library to create Jenkins agent
def agentResult = createJenkinsAgent([
nodeName: nodeName,
instanceIp: instanceIp,
remoteFS: remoteFS,
labels: labels,
timeoutMinutes: 5,
credentialsId: 'qa-builder-aws'
])

echo "✅ Jenkins agent created: ${agentResult.nodeName}"
echo "✅ Agent status: ${agentResult.status}"
}
}
}

stage('regressions-11 arm infrastructure') {
agent { label "java-client-agent-${BUILD_NUMBER}" }
when {
allOf {
branch 'develop'
expression { return params.arm_regressions }
expression { return !params.regressions }
}
}
steps {
checkout([$class: 'GitSCM',
branches: scm.branches,
doGenerateSubmoduleConfigurations: false,
extensions: [[$class: 'RelativeTargetDirectory', relativeTargetDir: 'java-client-api']],
submoduleCfg: [],
userRemoteConfigs: scm.userRemoteConfigs])

runTests("ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9-arm:latest-11")
}
post {
always {
archiveArtifacts artifacts: 'java-client-api/**/build/reports/**/*.html'
junit '**/build/**/TEST*.xml'
updateWorkspacePermissions()
tearDownDocker()
}
}
}


}

post{
always {
script {
echo "🧹 Starting cleanup process..."

try {
// Cleanup Terraform infrastructure
if (env.EC2_PRIVATE_IP) {
echo "🗑️ Cleaning up Terraform resources..."
node('javaClientLinuxPool') {
try {
sleep 60
unstash "terraform-${BUILD_NUMBER}"
withAWS(credentials: 'headlessDbUserEC2', region: 'us-west-2', role: 'role-headless-testing', roleAccount: '343869654284', duration: 3600) {
sh '''#!/bin/bash
export PATH=/home/builder/terraform:$PATH
cd ${WORKSPACE}/${DEPLOYMENT_TERRAFORM_DIR}
terraform workspace select dev
terraform destroy -auto-approve
'''
}
echo "✅ Terraform resources destroyed successfully."
} catch (Exception terraformException) {
echo "⚠️ Warning: Terraform cleanup failed: ${terraformException.message}"
}
}
} else {
echo "ℹ️ No EC2 instance IP found, skipping Terraform cleanup"
}

// Cleanup Jenkins agent using shared library function
def nodeName = "java-client-agent-${BUILD_NUMBER}"
echo "🗑️ Cleaning up Jenkins agent: ${nodeName}"
try {
def cleanupResult = cleanupJenkinsAgent(nodeName)
echo "✅ Cleanup result: ${cleanupResult.status} for node: ${cleanupResult.nodeName}"
} catch (Exception jenkinsCleanupException) {
echo "⚠️ Warning: Jenkins agent cleanup failed: ${jenkinsCleanupException.message}"
}
echo "✅ Pipeline cleanup completed successfully."

} catch (Exception cleanupException) {
echo "⚠️ Warning: Cleanup encountered an error: ${cleanupException.message}"
echo "📋 Continuing with pipeline completion despite cleanup issues..."
}
}
}
}
}
6 changes: 3 additions & 3 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ services:

marklogic:
image: "${MARKLOGIC_IMAGE}"
platform: linux/amd64
platform: "${PLATFORM:-linux/amd64}"
environment:
- INSTALL_CONVERTERS=true
- INSTALL_CONVERTERS=${SET_CONVERTERS:-true}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename SET_CONVERTERS to MARKLOGIC_INSTALL_CONVERTERS - I don't like to introduce a new verb for something that already exists as otherwise, in the future, someone's going to wonder "What's the difference between 'installing converters' and 'setting conveters'?"

- MARKLOGIC_INIT=true
- MARKLOGIC_ADMIN_USERNAME=admin
- MARKLOGIC_ADMIN_PASSWORD=admin
Expand All @@ -21,4 +21,4 @@ services:
- "8010-8015:8010-8015" # Range of ports used by app servers, at least one of which - 8015 - is created by a test.

volumes:
marklogicLogs:
marklogicLogs:
Loading