11@Library (' shared-libraries' ) _
22
3- def getJavaHomePath () {
4- if (env. JAVA_VERSION == " JAVA21" ) {
5- return " /home/builder/java/jdk-21.0.1"
6- } else {
7- return " /home/builder/java/jdk-17.0.2"
8- }
3+ def getJavaHomePath (isArm = false ) {
4+ if (isArm) {
5+ def version = (env. JAVA_VERSION == " JAVA21" ) ? " 21" : " 17"
6+ def path = " /usr/lib/jvm/java-${ version} -amazon-corretto.aarch64"
7+ return path
8+ } else {
9+ if (env. JAVA_VERSION == " JAVA21" ) {
10+ return " /home/builder/java/jdk-21.0.1"
11+ } else {
12+ return " /home/builder/java/jdk-17.0.2"
13+ }
14+ }
15+ }
16+
17+ def getPlatform (isArm = false ) {
18+ return isArm ? " linux/arm64" : " linux/amd64"
19+ }
20+
21+ def setConverters (isArm = false ) {
22+ return isArm ? " false" : " true"
923}
1024
1125def setupDockerMarkLogic (String image ) {
12- cleanupDocker()
13- sh label : ' mlsetup' , script : ''' #!/bin/bash
14- echo "Removing any running MarkLogic server and clean up MarkLogic data directory"
15- sudo /usr/local/sbin/mladmin remove
16- sudo /usr/local/sbin/mladmin cleandata
17- cd java-client-api
18- docker compose down -v || true
19- docker volume prune -f
20- echo "Using image: "''' + image + '''
21- docker pull ''' + image + '''
22- MARKLOGIC_IMAGE=''' + image + ''' MARKLOGIC_LOGS_VOLUME=marklogicLogs docker compose up -d --build
23- export JAVA_HOME=$JAVA_HOME_DIR
24- export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
25- export PATH=$JAVA_HOME/bin:$PATH
26- ./gradlew -i mlWaitTillReady
27- sleep 3
28- ./gradlew -i mlWaitTillReady
29- ./gradlew mlTestConnections
30- ./gradlew -i mlDeploy mlReloadSchemas
31- '''
26+ cleanupDocker()
27+ sh label : ' mlsetup' , script : ''' #!/bin/bash
28+ echo "Removing any running MarkLogic server and clean up MarkLogic data directory"
29+ sudo /usr/local/sbin/mladmin remove
30+ sudo /usr/local/sbin/mladmin cleandata
31+ cd java-client-api
32+ export PLATFORM=$PLATFORM
33+ export MARKLOGIC_INSTALL_CONVERTERS=$MARKLOGIC_INSTALL_CONVERTERS
34+ docker compose down -v || true
35+ docker volume prune -f
36+
37+ echo "Using image: "''' + image + '''
38+ docker pull ''' + image + '''
39+
40+ MARKLOGIC_IMAGE=''' + image + ''' MARKLOGIC_LOGS_VOLUME=marklogicLogs \
41+ docker compose up -d --build
42+ echo "Waiting for MarkLogic server to initialize."
43+ export JAVA_HOME=$JAVA_HOME_DIR
44+ export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
45+ export PATH=$GRADLE_USER_HOME:$JAVA_HOME/bin:$PATH
46+ ./gradlew -i mlWaitTillReady
47+ ./gradlew mlTestConnections
48+ ./gradlew -i mlDeploy mlReloadSchemas
49+ '''
3250}
3351
3452def runTests (String image ) {
3553 setupDockerMarkLogic(image)
36-
3754 sh label : ' run marklogic-client-api tests' , script : ''' #!/bin/bash
3855 export JAVA_HOME=$JAVA_HOME_DIR
3956 export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
@@ -45,7 +62,7 @@ def runTests(String image) {
4562 rm -rf ~/.m2/repository/com/squareup/okhttp3/
4663
4764 echo "Ensure all subprojects can be built first."
48- ./gradlew clean build -x test
65+ ./gradlew clean build -x test
4966
5067 ./gradlew marklogic-client-api:test || true
5168 '''
@@ -100,9 +117,9 @@ def runTestsWithReverseProxy(String image) {
100117 rm -rf ~/.m2/repository/com/squareup/okhttp3/
101118
102119 echo "Ensure all subprojects can be built first."
103- ./gradlew clean build -x test
120+ ./gradlew clean build -x test
104121
105- echo "Running marklogic-client-api tests with reverse proxy."
122+ echo "Running marklogic-client-api tests with reverse proxy."
106123 ./gradlew -PtestUseReverseProxyServer=true runReverseProxyServer marklogic-client-api:test || true
107124 '''
108125
@@ -180,37 +197,38 @@ pipeline {
180197 GRADLE_DIR = " .gradle"
181198 DMC_USER = credentials(' MLBUILD_USER' )
182199 DMC_PASSWORD = credentials(' MLBUILD_PASSWORD' )
200+ PLATFORM = getPlatform()
201+ MARKLOGIC_INSTALL_CONVERTERS = setConverters()
183202 }
184203
185204 stages {
186-
187205 stage(' pull-request-tests' ) {
188206 when {
189- not {
190- expression { return params. regressions }
207+ expression {
208+ return ! params. regressions
191209 }
192210 }
193211 steps {
194212 setupDockerMarkLogic(" ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi:latest-12" )
195213 sh label : ' run marklogic-client-api tests' , script : ''' #!/bin/bash
196- export JAVA_HOME=$JAVA_HOME_DIR
197- export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
198- export PATH=$GRADLE_USER_HOME:$JAVA_HOME/bin:$PATH
199- cd java-client-api
214+ export JAVA_HOME=$JAVA_HOME_DIR
215+ export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
216+ export PATH=$GRADLE_USER_HOME:$JAVA_HOME/bin:$PATH
217+ cd java-client-api
200218
201- echo "Temporary fix for mysterious issue with okhttp3 being corrupted in local Maven cache."
202- ls -la ~/.m2/repository/com/squareup
219+ echo "Temporary fix for mysterious issue with okhttp3 being corrupted in local Maven cache."
220+ ls -la ~/.m2/repository/com/squareup
203221 rm -rf ~/.m2/repository/com/squareup/okhttp3/
204222
205- echo "Ensure all subprojects can be built first."
206- ./gradlew clean build -x test
223+ echo "Ensure all subprojects can be built first."
224+ ./gradlew clean build -x test
207225
208- echo "Run a sufficient number of tests to verify the PR."
226+ echo "Run a sufficient number of tests to verify the PR."
209227 ./gradlew marklogic-client-api:test --tests ReadDocumentPageTest || true
210228
211229 echo "Run a test with the reverse proxy server to ensure it's fine."
212230 ./gradlew -PtestUseReverseProxyServer=true runReverseProxyServer marklogic-client-api-functionaltests:test --tests SearchWithPageLengthTest || true
213- '''
231+ '''
214232 }
215233 post {
216234 always {
@@ -225,18 +243,20 @@ pipeline {
225243 when {
226244 branch ' develop'
227245 not {
228- expression { return params. regressions }
246+ anyOf {
247+ expression { return params. regressions }
248+ }
229249 }
230250 }
231251 steps {
232252 sh label : ' publish' , script : ''' #!/bin/bash
233- export JAVA_HOME=$JAVA_HOME_DIR
234- export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
235- export PATH=$GRADLE_USER_HOME:$JAVA_HOME/bin:$PATH
236- cp ~/.gradle/gradle.properties $GRADLE_USER_HOME;
237- cd java-client-api
238- ./gradlew publish
239- '''
253+ export JAVA_HOME=$JAVA_HOME_DIR
254+ export GRADLE_USER_HOME=$WORKSPACE/$GRADLE_DIR
255+ export PATH=$GRADLE_USER_HOME:$JAVA_HOME/bin:$PATH
256+ cp ~/.gradle/gradle.properties $GRADLE_USER_HOME;
257+ cd java-client-api
258+ ./gradlew publish
259+ '''
240260 }
241261 }
242262
@@ -259,7 +279,7 @@ pipeline {
259279
260280 stage(stageName) {
261281 try {
262- runTests(fullImage)
282+ runTests(fullImage, false )
263283 } finally {
264284 junit ' **/build/**/TEST*.xml'
265285 updateWorkspacePermissions()
@@ -270,5 +290,175 @@ pipeline {
270290 }
271291 }
272292 }
293+
294+ stage(' provisionInfrastructure' ){
295+ when {
296+ branch ' develop'
297+ expression { return ! params. regressions }
298+ }
299+ agent {label ' javaClientLinuxPool' }
300+
301+ steps{
302+ script {
303+ withCredentials([
304+ string(credentialsId : ' aws-region-us-west' , variable : ' AWS_REGION' ),
305+ string(credentialsId : ' aws-role-headless-testing' , variable : ' AWS_ROLE' ),
306+ string(credentialsId : ' aws-role-account-headless' , variable : ' AWS_ROLE_ACCOUNT' )
307+ ]) {
308+ def deploymentResult = deployAWSInstance([
309+ instanceName : " java-client-instance-${ BUILD_NUMBER} " ,
310+ region : env. AWS_REGION ,
311+ credentialsId : ' headlessDbUserEC2' ,
312+ role : env. AWS_ROLE ,
313+ roleAccount : env. AWS_ROLE_ACCOUNT ,
314+ branch : ' master'
315+ ])
316+
317+ echo " ✅ Instance deployed: ${ deploymentResult.privateIp} "
318+ echo " ✅ Terraform directory: ${ deploymentResult.terraformDir} "
319+ echo " ✅ Workspace: ${ deploymentResult.workspace} "
320+ echo " ✅ Status: ${ deploymentResult.status} "
321+
322+ // Store deployment info for cleanup
323+ env. DEPLOYMENT_INSTANCE_NAME = deploymentResult. instanceName
324+ env. DEPLOYMENT_REGION = deploymentResult. region
325+ env. DEPLOYMENT_TERRAFORM_DIR = deploymentResult. terraformDir
326+ env. EC2_PRIVATE_IP = deploymentResult. privateIp
327+
328+ def nodeName = " java-client-agent-${ BUILD_NUMBER} "
329+ def remoteFS = " /space/jenkins_home"
330+ def labels = " java-client-agent-${ BUILD_NUMBER} "
331+ def instanceIp = env. EC2_PRIVATE_IP
332+
333+ // Attach volumes
334+ def volumeResult = attachInstanceVolumes([
335+ instanceIp : instanceIp,
336+ remoteFS : remoteFS,
337+ branch : ' master'
338+ ])
339+
340+ echo " ✅ Volume attachment completed: ${ volumeResult.volumeAttached} "
341+ echo " ✅ Java installed: ${ volumeResult.javaInstalled} "
342+
343+ // Install dependencies AND run init scripts
344+ def depsResult = installDependenciesAndInitScripts([
345+ instanceIp : instanceIp,
346+ packageFile : ' Packagedependencies' ,
347+ packageDir : ' terraform-templates/java-client-api' ,
348+ initScriptsDir : ' terraform-templates/java-client-api/scripts' ,
349+ initScriptsFile : ' terraform-templates/java-client-api/initscripts'
350+ ])
351+
352+ echo " ✅ Dependencies installed: ${ depsResult.dependenciesInstalled} "
353+ if (depsResult. initScriptsExecuted) {
354+ echo " ✅ Init scripts executed: ${ depsResult.initScriptsCount} scripts"
355+ } else {
356+ echo " ℹ️ No init scripts configured or executed"
357+ }
358+
359+ // Use shared library to create Jenkins agent
360+ def agentResult = createJenkinsAgent([
361+ nodeName : nodeName,
362+ instanceIp : instanceIp,
363+ remoteFS : remoteFS,
364+ labels : labels,
365+ timeoutMinutes : 5 ,
366+ credentialsId : ' qa-builder-aws'
367+ ])
368+
369+ echo " ✅ Jenkins agent created: ${ agentResult.nodeName} "
370+ echo " ✅ Agent status: ${ agentResult.status} "
371+ }
372+ }
373+ }
374+ }
375+
376+ stage(' regressions-11 arm infrastructure' ) {
377+ when {
378+ beforeAgent true
379+ branch ' develop'
380+ expression { return ! params. regressions }
381+ expression { return env. EC2_PRIVATE_IP != null }
382+ }
383+ agent { label " java-client-agent-${ BUILD_NUMBER} " }
384+ environment {
385+ JAVA_HOME_DIR = getJavaHomePath(true )
386+ PLATFORM = getPlatform(true )
387+ MARKLOGIC_INSTALL_CONVERTERS = setConverters(true )
388+ }
389+ steps {
390+ checkout([$class : ' GitSCM' ,
391+ branches : scm. branches,
392+ doGenerateSubmoduleConfigurations : false ,
393+ extensions : [[$class : ' RelativeTargetDirectory' , relativeTargetDir : ' java-client-api' ]],
394+ submoduleCfg : [],
395+ userRemoteConfigs : scm. userRemoteConfigs])
396+
397+ runTests(" ml-docker-db-dev-tierpoint.bed-artifactory.bedford.progress.com/marklogic/marklogic-server-ubi9-arm:latest-11" )
398+ }
399+ post {
400+ always {
401+ archiveArtifacts artifacts : ' java-client-api/**/build/reports/**/*.html'
402+ junit ' **/build/**/TEST*.xml'
403+ updateWorkspacePermissions()
404+ tearDownDocker()
405+ }
406+ }
407+ }
408+ }
409+
410+ post{
411+ always {
412+ script {
413+ echo " 🧹 Starting cleanup process..."
414+
415+ try {
416+ // Cleanup Terraform infrastructure
417+ if (env. EC2_PRIVATE_IP ) {
418+ echo " 🗑️ Cleaning up Terraform resources..."
419+ node(' javaClientLinuxPool' ) {
420+ try {
421+ // `sleep 60` allows AWS resources to stabilize before Terraform destroys them, preventing "resource in use" errors
422+ sleep 60
423+ unstash " terraform-${ BUILD_NUMBER} "
424+ withCredentials([
425+ string(credentialsId : ' aws-region-us-west' , variable : ' AWS_REGION' ),
426+ string(credentialsId : ' aws-role-headless-testing' , variable : ' AWS_ROLE' ),
427+ string(credentialsId : ' aws-role-account-headless' , variable : ' AWS_ROLE_ACCOUNT' )
428+ ]) {
429+ withAWS(credentials : ' headlessDbUserEC2' , region : env. AWS_REGION , role : env. AWS_ROLE , roleAccount : env. AWS_ROLE_ACCOUNT , duration : 3600 ) {
430+ sh ''' #!/bin/bash
431+ export PATH=/home/builder/terraform:$PATH
432+ cd ${WORKSPACE}/${DEPLOYMENT_TERRAFORM_DIR}
433+ terraform workspace select dev
434+ terraform destroy -auto-approve
435+ '''
436+ }
437+ }
438+ echo " ✅ Terraform resources destroyed successfully."
439+ // Cleanup Jenkins agent using shared library function
440+ def nodeName = " java-client-agent-${ BUILD_NUMBER} "
441+ echo " 🗑️ Cleaning up Jenkins agent: ${ nodeName} "
442+ try {
443+ def cleanupResult = cleanupJenkinsAgent(nodeName)
444+ echo " ✅ Cleanup result: ${ cleanupResult.status} for node: ${ cleanupResult.nodeName} "
445+ } catch (Exception jenkinsCleanupException) {
446+ echo " ⚠️ Warning: Jenkins agent cleanup failed: ${ jenkinsCleanupException.message} "
447+ }
448+ echo " ✅ Pipeline cleanup completed successfully."
449+ } catch (Exception terraformException) {
450+ echo " ⚠️ Warning: Terraform cleanup failed: ${ terraformException.message} "
451+ }
452+ }
453+ } else {
454+ echo " ℹ️ No EC2 instance IP found, skipping Terraform cleanup"
455+ }
456+ } catch (Exception cleanupException) {
457+ echo " ⚠️ Warning: Cleanup encountered an error: ${ cleanupException.message} "
458+ echo " 📋 Continuing with pipeline completion despite cleanup issues..."
459+ }
460+ }
461+ }
273462 }
274463}
464+
0 commit comments