@@ -22,8 +22,7 @@ void PreBuildCheck() {
22
22
githubAPIUrl = GIT_URL . replace(' .git' , ' ' ). replace(' github.com' , ' api.github.com/repos' )
23
23
echo ' githubAPIUrl: ' + githubAPIUrl
24
24
} else {
25
- echo ' ERROR: GIT_URL is not defined'
26
- sh ' exit 1'
25
+ echo ' Warning: GIT_URL is not defined'
27
26
}
28
27
29
28
if (env. CHANGE_ID ) {
@@ -52,21 +51,21 @@ def ExtractJiraID() {
52
51
match = env. GIT_BRANCH =~ JIRA_ID_PATTERN
53
52
}
54
53
else {
55
- echo ' ERROR : Jira ticket number not detected.'
54
+ echo ' Warning : Jira ticket number not detected.'
56
55
return ' '
57
56
}
58
57
try {
59
58
return match[0 ]
60
59
} catch (any) {
61
- echo ' ERROR : Jira ticket number not detected.'
60
+ echo ' Warning : Jira ticket number not detected.'
62
61
return ' '
63
62
}
64
63
}
65
64
66
65
def PRDraftCheck () {
67
66
withCredentials([usernameColonPassword(credentialsId : gitCredID, variable : ' Credentials' )]) {
68
67
PrObj = sh(returnStdout : true , script :'''
69
- curl -u $Credentials -X GET ''' + githubAPIUrl + ''' /pulls/$CHANGE_ID
68
+ curl -s - u $Credentials -X GET ''' + githubAPIUrl + ''' /pulls/$CHANGE_ID
70
69
''' )
71
70
}
72
71
def jsonObj = new JsonSlurperClassic (). parseText(PrObj . toString(). trim())
@@ -78,10 +77,10 @@ def getReviewState() {
78
77
def commitHash
79
78
withCredentials([usernameColonPassword(credentialsId : gitCredID, variable : ' Credentials' )]) {
80
79
reviewResponse = sh(returnStdout : true , script :'''
81
- curl -u $Credentials -X GET ''' + githubAPIUrl + ''' /pulls/$CHANGE_ID/reviews
80
+ curl -s - u $Credentials -X GET ''' + githubAPIUrl + ''' /pulls/$CHANGE_ID/reviews
82
81
''' )
83
82
commitHash = sh(returnStdout : true , script :'''
84
- curl -u $Credentials -X GET ''' + githubAPIUrl + ''' /pulls/$CHANGE_ID
83
+ curl -s - u $Credentials -X GET ''' + githubAPIUrl + ''' /pulls/$CHANGE_ID
85
84
''' )
86
85
}
87
86
def jsonObj = new JsonSlurperClassic (). parseText(commitHash. toString(). trim())
@@ -118,10 +117,13 @@ def ResultNotification(message) {
118
117
emailList = params. emailList
119
118
}
120
119
121
- mail charset : ' UTF-8' , mimeType : ' text/html' , to : " ${ emailList} " , body : " <b>Jenkins pipeline for ${ env.JOB_NAME} <br>Build Number: ${ env.BUILD_NUMBER} <br>${ env.BUILD_URL} </b>" , subject : " ${ message} : ${ env.JOB_NAME} #${ env.BUILD_NUMBER} "
122
120
if (JIRA_ID ) {
123
121
def comment = [ body : " Jenkins pipeline build result: ${ message} " ]
124
122
jiraAddComment site : ' JIRA' , idOrKey : JIRA_ID , input : comment
123
+ mail charset : ' UTF-8' , mimeType : ' text/html' , to : " ${ emailList} " , body : " <b>Jenkins pipeline for ${ env.JOB_NAME} <br>Build Number: ${ env.BUILD_NUMBER} <br>${ env.BUILD_URL} <br>https://project.marklogic.com/jira/browse/${ JIRA_ID} </b>" , subject : " ${ message} : ${ env.JOB_NAME} #${ env.BUILD_NUMBER} "
124
+ } else {
125
+ mail charset : ' UTF-8' , mimeType : ' text/html' , to : " ${ emailList} " , body : " <b>Jenkins pipeline for ${ env.JOB_NAME} <br>Build Number: ${ env.BUILD_NUMBER} <br>${ env.BUILD_URL} </b>" , subject : " ${ message} : ${ env.JOB_NAME} #${ env.BUILD_NUMBER} "
126
+
125
127
}
126
128
}
127
129
@@ -189,26 +191,132 @@ def CopyRPMs() {
189
191
}
190
192
}
191
193
192
- def RunStructureTests () {
194
+ def StructureTests () {
193
195
sh """
194
196
cd test
195
197
#insert current version
196
198
sed -i -e 's/VERSION_PLACEHOLDER/${ mlVersion} -${ env.platformString} -${ env.dockerVersion} /' ./structure-test.yml
197
- curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 && chmod +x container-structure-test-linux-amd64 && mv container-structure-test-linux-amd64 container-structure-test
199
+ curl -s - LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 && chmod +x container-structure-test-linux-amd64 && mv container-structure-test-linux-amd64 container-structure-test
198
200
./container-structure-test test --config ./structure-test.yml --image marklogic-centos/marklogic-server-centos:${ mlVersion} -${ env.platformString} -${ env.dockerVersion} --output junit | tee container-structure-test.xml
199
201
#fix junit output
200
202
sed -i -e 's/<\\ /testsuites>//' -e 's/<testsuite>//' -e 's/<testsuites/<testsuite name="container-structure-test"/' ./container-structure-test.xml
201
203
"""
202
204
junit testResults : ' **/container-structure-test.xml'
203
205
}
204
206
205
- def RunServerRegressionTests () {
207
+ def ServerRegressionTests () {
206
208
// TODO: run this conditionally for develop and master branches only
207
209
echo ' Server regression tests would execute here'
208
210
// The following can be uncommented to show an interactive prompt for manual regresstion tests
209
211
// input "Server regression tests need to be executed manually. "
210
212
}
211
213
214
+ def DockerRunTests () {
215
+ echo " ----------------- Docker Tests -----------------"
216
+ // Define test parameters
217
+ def testImage= " marklogic-centos/marklogic-server-centos:${ mlVersion} -${ env.platformString} -${ env.dockerVersion} "
218
+ def defaultParams= ' -it -d -p 8000:8000 -p 8001:8001 -p 8002:8002 -p7997:7997'
219
+ def curlCommand= ' curl -sL'
220
+ def curlCommandAuth= ' curl -sL --anyauth -u test_admin:test_admin_pass'
221
+ def composePath= ' ./docker-compose/'
222
+ def jUnitReport = " docker-test-results.xml"
223
+ def testCases = readJSON file : ' ./test/docker-test-cases.json'
224
+
225
+ // validate JSON data
226
+ assert testCases instanceof Map
227
+
228
+ // create credential files for compose
229
+ writeFile(file : " ${ composePath} mldb_admin_username.txt" , text : " test_admin" )
230
+ writeFile(file : " ${ composePath} mldb_admin_password.txt" , text : " test_admin_pass" )
231
+
232
+ def testResults = ' '
233
+ def totalTests = 0
234
+ def totalErrors = 0
235
+ def cmdOutput
236
+ def composeFile
237
+ def testCont
238
+
239
+ // Run test cases
240
+ testCases. each { key , value ->
241
+
242
+ echo " Running " + key+ " : " + value. description
243
+ // if .yml config is provided in params, start compose. otherwise docker run is used
244
+ if ( value. params. toString(). contains(" .yml" )) {
245
+ // update image label in yml file
246
+ composeFile = readFile(composePath + value. params)
247
+ composeFile = composeFile. replaceFirst(/ image: .*/ , " image: " + testImage)
248
+ writeFile( file : composePath + value. params, text : composeFile)
249
+ // start docker compose
250
+ sh( returnStdout : true , script : " docker compose -f ${ composePath}${ value.params} up -d" )
251
+ } else {
252
+ // insert valid license data in parameters
253
+ value. params = value. params. toString(). replaceAll(" LICENSE_PLACEHOLDER" , " LICENSEE='MarkLogic - Version 9 QA Test License' -e LICENSE_KEY=\" ${ env.QA_LICENSE_KEY} \" " )
254
+ // start docker container
255
+ testCont = sh( returnStdout : true , script : " docker run ${ defaultParams} ${ value.params} ${ testImage} " )
256
+ }
257
+
258
+ // TODO find a good way to skip the test on error from invalid params
259
+ // TODO: Find a way to check for server status instead of a wait. (log: Database Modules is online)
260
+ sleep(60 )
261
+
262
+ echo " -Unauthenticated requests"
263
+ value. expected. unauthenticated. each { test , verify ->
264
+ // TODO if key is 'log' then check for log message
265
+ try {
266
+ cmdOutput = sh( returnStdout : true , script : " ${ curlCommand} http://localhost:${ test} " )
267
+ } catch (e) {
268
+ cmdOutput = ' Curl retured error: ' + e. message
269
+ }
270
+ testResults = testResults + ' <testcase name="' + value. description+ ' on ' + key+ ' without credentials"'
271
+ totalTests + = 1
272
+ echo " --Port ${ test} : "
273
+ if ( cmdOutput. contains(verify) ) {
274
+ echo " PASS"
275
+ testResults = testResults + ' />'
276
+ } else {
277
+ echo " FAIL"
278
+ testResults = testResults + ' ><failure type="Text mismatch">' + cmdOutput+ ' </failure></testcase>'
279
+ totalErrors + = 1
280
+ }
281
+ sleep(1 )
282
+ }
283
+ echo " -Authenticated requests"
284
+ value. expected. authenticated. each { test , verify ->
285
+ try {
286
+ cmdOutput = sh( returnStdout : true , script : " ${ curlCommandAuth} http://localhost:${ test} " )
287
+ } catch (e) {
288
+ cmdOutput = ' Curl retured error: ' + e. message
289
+ }
290
+ testResults = testResults + ' <testcase name="' + value. description+ ' on ' + key+ ' with credentials"'
291
+ totalTests + = 1
292
+ echo " --Port ${ test} : "
293
+ if ( cmdOutput. contains(verify) ) {
294
+ echo " PASS"
295
+ testResults = testResults + ' />'
296
+ } else {
297
+ echo " FAIL"
298
+ testResults = testResults + ' ><failure type="Text mismatch">' + cmdOutput+ ' </failure></testcase>'
299
+ totalErrors + = 1
300
+ }
301
+ sleep(1 )
302
+ }
303
+ echo " -Deleting resources"
304
+ if ( value. params. toString(). contains(" .yml" )) {
305
+ sh( returnStdout : true , script : " docker compose -f ${ composePath}${ value.params} down" )
306
+ } else {
307
+ sh( returnStdout : true , script : " docker rm -f ${ testCont} " )
308
+ }
309
+ sh( returnStdout : true , script : " docker volume prune -f" )
310
+ }
311
+ // Generate JUnit XML file for Jenkins report
312
+ // TODO: find a better way to generate junit file
313
+ def jUnitXML = ' <testsuite name="Docker Run Tests" tests="' + totalTests+ ' " failures="' + totalErrors+ ' ">'
314
+ jUnitXML = jUnitXML + testResults + " </testsuite>"
315
+ writeFile( file : jUnitReport, text : jUnitXML )
316
+ junit testResults : jUnitReport
317
+ echo " -------------- End of Docker Tests --------------"
318
+ }
319
+
212
320
def PublishToInternalRegistry () {
213
321
withCredentials([usernamePassword(credentialsId : ' 8c2e0b38-9e97-4953-aa60-f2851bb70cc8' , passwordVariable : ' docker_password' , usernameVariable : ' docker_user' )]) {
214
322
sh """
@@ -222,7 +330,7 @@ def PublishToInternalRegistry() {
222
330
pipeline {
223
331
agent {
224
332
label {
225
- label ' docker-vitaly '
333
+ label ' cld-docker '
226
334
}
227
335
}
228
336
options {
@@ -236,6 +344,7 @@ pipeline {
236
344
buildServerPlatform = ' linux64-rh7'
237
345
buildServerPath = getServerPath(params. ML_SERVER_BRANCH )
238
346
dockerRegistry = ' https://ml-docker-dev.marklogic.com'
347
+ QA_LICENSE_KEY = credentials(' QA_LICENSE_KEY' )
239
348
}
240
349
241
350
parameters {
@@ -246,6 +355,9 @@ pipeline {
246
355
string(name : ' ML_RPM' , defaultValue : ' ' , description : ' RPM to be used for Image creation. \n If left blank nightly ML rpm will be used.\n Please provide Jenkins accessible path e.g. /project/engineering or /project/qa' , trim : true )
247
356
string(name : ' ML_CONVERTERS' , defaultValue : ' ' , description : ' The Converters RPM to be included in the image creation \n If left blank the nightly ML Converters Package will be used.' , trim : true )
248
357
booleanParam(name : ' PUBLISH_IMAGE' , defaultValue : false , description : ' Publish image to internal registry' )
358
+ booleanParam(name : ' TEST_STRUCTURE' , defaultValue : true , description : ' Run container structure tests' )
359
+ booleanParam(name : ' DOCKER_TESTS' , defaultValue : true , description : ' Run server regression tests' )
360
+ booleanParam(name : ' SERVER_REGRESSION' , defaultValue : true , description : ' Run server regression tests' )
249
361
}
250
362
251
363
stages {
@@ -267,21 +379,39 @@ pipeline {
267
379
}
268
380
}
269
381
270
- stage(' Image-Test' ) {
382
+ stage(' Structure-Tests' ) {
383
+ when {
384
+ expression { return params. TEST_STRUCTURE }
385
+ }
271
386
steps {
272
- RunStructureTests ()
387
+ StructureTests ()
388
+ }
389
+ }
390
+
391
+ stage(' Docker-Run-Tests' ) {
392
+ when {
393
+ expression { return params. DOCKER_TESTS }
394
+ }
395
+ steps {
396
+ DockerRunTests ()
273
397
}
274
398
}
275
399
276
400
stage(' Run-Server-Regression-Tests' ) {
401
+ when {
402
+ expression { return params. SERVER_REGRESSION }
403
+ }
277
404
steps {
278
- RunServerRegressionTests ()
405
+ ServerRegressionTests ()
279
406
}
280
407
}
281
408
282
409
stage(' Publish-Image' ) {
283
410
when {
284
- expression { return params. PUBLISH_IMAGE }
411
+ anyOf {
412
+ branch ' develop'
413
+ expression { return params. PUBLISH_IMAGE }
414
+ }
285
415
}
286
416
steps {
287
417
PublishToInternalRegistry ()
@@ -294,6 +424,8 @@ pipeline {
294
424
sh '''
295
425
cd src/centos
296
426
rm -rf *.rpm
427
+ docker system prune --force --filter "until=720h"
428
+ docker volume prune --force
297
429
'''
298
430
}
299
431
success {
@@ -306,4 +438,4 @@ pipeline {
306
438
ResultNotification (' BUILD UNSTABLE ❌' )
307
439
}
308
440
}
309
- }
441
+ }
0 commit comments