Skip to content

Commit a883985

Browse files
Merge pull request #33 from marklogic/feature/CLD-502
CLD-502: Create Jenkinsfile and update Makefile/tests to work with newly created pipeline
2 parents df75e11 + 467a2e5 commit a883985

File tree

10 files changed

+507
-95
lines changed

10 files changed

+507
-95
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
.vscode
22
values.yaml
3+
test/test_results

.golangci.yaml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
linters:
2+
disable-all: true
3+
enable:
4+
- goimports
5+
- revive
6+
issues:
7+
exclude-use-default: false
8+
linters-settings:
9+
revive:
10+
rules:
11+
- name: blank-imports
12+
- name: context-as-argument
13+
- name: context-keys-type
14+
- name: dot-imports
15+
- name: error-return
16+
- name: error-strings
17+
- name: error-naming
18+
- name: exported
19+
- name: if-return
20+
- name: increment-decrement
21+
- name: var-naming
22+
- name: var-declaration
23+
- name: package-comments
24+
- name: range
25+
- name: receiver-naming
26+
- name: time-naming
27+
- name: unexported-return
28+
- name: indent-error-flow
29+
- name: errorf
30+
- name: empty-block
31+
- name: superfluous-else
32+
- name: unused-parameter
33+
- name: unreachable-code
34+
- name: redefines-builtin-id

Jenkinsfile

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
/* groovylint-disable CompileStatic, LineLength, VariableTypeRequired */
2+
// This Jenkinsfile defines internal MarkLogic build pipeline.
3+
4+
//Shared library definitions: https://github.com/marklogic/MarkLogic-Build-Libs/tree/1.0-declarative/vars
5+
@Library('[email protected]')
6+
import groovy.json.JsonSlurperClassic
7+
8+
9+
gitCredID = '550650ab-ee92-4d31-a3f4-91a11d5388a3'
10+
JIRA_ID = ''
11+
JIRA_ID_PATTERN = /CLD-\d{3,4}/
12+
LINT_OUTPUT = ''
13+
SCAN_OUTPUT = ''
14+
IMAGE_INFO = 0
15+
16+
// Define local funtions
17+
void preBuildCheck() {
18+
// Initialize parameters as env variables as workaround for https://issues.jenkins-ci.org/browse/JENKINS-41929
19+
evaluate """${ def script = ''; params.each { k, v -> script += "env.${k } = '''${v}'''\n" }; return script}"""
20+
21+
JIRA_ID = extractJiraID()
22+
echo 'Jira ticket number: ' + JIRA_ID
23+
24+
if (env.GIT_URL) {
25+
githubAPIUrl = GIT_URL.replace('.git', '').replace('github.com', 'api.github.com/repos')
26+
echo 'githubAPIUrl: ' + githubAPIUrl
27+
} else {
28+
echo 'Warning: GIT_URL is not defined'
29+
}
30+
31+
if (env.CHANGE_ID) {
32+
if (prDraftCheck()) { sh 'exit 1' }
33+
if (getReviewState().equalsIgnoreCase('CHANGES_REQUESTED')) {
34+
println(reviewState)
35+
sh 'exit 1'
36+
}
37+
}
38+
}
39+
40+
@NonCPS
41+
def extractJiraID() {
42+
// Extract Jira ID from one of the environment variables
43+
def match
44+
if (env.CHANGE_TITLE) {
45+
match = env.CHANGE_TITLE =~ JIRA_ID_PATTERN
46+
}
47+
else if (env.BRANCH_NAME) {
48+
match = env.BRANCH_NAME =~ JIRA_ID_PATTERN
49+
}
50+
else if (env.GIT_BRANCH) {
51+
match = env.GIT_BRANCH =~ JIRA_ID_PATTERN
52+
}
53+
else {
54+
echo 'Warning: Jira ticket number not detected.'
55+
return ''
56+
}
57+
try {
58+
return match[0]
59+
} catch (any) {
60+
echo 'Warning: Jira ticket number not detected.'
61+
return ''
62+
}
63+
}
64+
65+
def prDraftCheck() {
66+
withCredentials([usernameColonPassword(credentialsId: gitCredID, variable: 'Credentials')]) {
67+
PrObj = sh(returnStdout: true, script:'''
68+
curl -s -u $Credentials -X GET ''' + githubAPIUrl + '''/pulls/$CHANGE_ID
69+
''')
70+
}
71+
def jsonObj = new JsonSlurperClassic().parseText(PrObj.toString().trim())
72+
return jsonObj.draft
73+
}
74+
75+
def getReviewState() {
76+
def reviewResponse
77+
def commitHash
78+
withCredentials([usernameColonPassword(credentialsId: gitCredID, variable: 'Credentials')]) {
79+
reviewResponse = sh(returnStdout: true, script:'''
80+
curl -s -u $Credentials -X GET ''' + githubAPIUrl + '''/pulls/$CHANGE_ID/reviews
81+
''')
82+
commitHash = sh(returnStdout: true, script:'''
83+
curl -s -u $Credentials -X GET ''' + githubAPIUrl + '''/pulls/$CHANGE_ID
84+
''')
85+
}
86+
def jsonObj = new JsonSlurperClassic().parseText(commitHash.toString().trim())
87+
def commitId = jsonObj.head.sha
88+
println(commitId)
89+
def reviewState = getReviewStateOfPR reviewResponse, 2, commitId
90+
echo reviewState
91+
return reviewState
92+
}
93+
94+
void resultNotification(message) {
95+
def author, authorEmail, emailList
96+
if (env.CHANGE_AUTHOR) {
97+
author = env.CHANGE_AUTHOR.toString().trim().toLowerCase()
98+
authorEmail = getEmailFromGITUser author
99+
emailList = params.emailList + ',' + authorEmail
100+
} else {
101+
emailList = params.emailList
102+
}
103+
jira_link = "https://project.marklogic.com/jira/browse/${JIRA_ID}"
104+
email_body = "<b>Jenkins pipeline for</b> ${env.JOB_NAME} <br><b>Build Number: </b>${env.BUILD_NUMBER} <b><br><br>Lint Output: <br></b><pre><code>${LINT_OUTPUT}</code></pre><br><br><b>Build URL: </b><br>${env.BUILD_URL}"
105+
jira_email_body = "${email_body} <br><br><b>Jira URL: </b><br>${jira_link}"
106+
107+
if (JIRA_ID) {
108+
def comment = [ body: "Jenkins pipeline build result: ${message}" ]
109+
jiraAddComment site: 'JIRA', idOrKey: JIRA_ID, failOnError: false, input: comment
110+
mail charset: 'UTF-8', mimeType: 'text/html', to: "${emailList}", body: "${jira_email_body}", subject: "${message}: ${env.JOB_NAME} #${env.BUILD_NUMBER}"
111+
} else {
112+
mail charset: 'UTF-8', mimeType: 'text/html', to: "${emailList}", body: "${email_body}", subject: "${message}: ${env.JOB_NAME} #${env.BUILD_NUMBER} - ${JIRA_ID}"
113+
}
114+
}
115+
116+
void lint() {
117+
sh '''
118+
# Added to fix 'Context loading failed error'
119+
go get ./...
120+
echo Installing golangci-lint
121+
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s v1.50.0
122+
make lint saveOutput=true path=./bin/
123+
'''
124+
125+
LINT_OUTPUT = sh(returnStdout: true, script: 'echo helm template lint output: ;cat helm-lint-output.txt ;echo all tests lint output: ;cat test-lint-output.txt').trim()
126+
127+
sh '''
128+
rm -f helm-lint-output.txt test-lint-output.txt
129+
'''
130+
}
131+
132+
void publishTestResults() {
133+
junit allowEmptyResults:true, testResults: '**/test/test_results/*.xml'
134+
publishHTML allowMissing: true, alwaysLinkToLastBuild: true, keepAll: true, reportDir: 'test/test_results', reportFiles: 'report.html', reportName: 'Kubernetes Tests Report', reportTitles: ''
135+
}
136+
137+
void pullImage() {
138+
withCredentials([usernamePassword(credentialsId: '8c2e0b38-9e97-4953-aa60-f2851bb70cc8', passwordVariable: 'docker_password', usernameVariable: 'docker_user')]) {
139+
sh """
140+
echo "\$docker_password" | docker login --username \$docker_user --password-stdin ${dockerRegistry}
141+
docker pull ${dockerRepository}:${dockerVersion}
142+
"""
143+
}
144+
}
145+
146+
pipeline {
147+
agent {
148+
label {
149+
label 'cld-kubernetes'
150+
}
151+
}
152+
options {
153+
checkoutToSubdirectory '.'
154+
buildDiscarder logRotator(artifactDaysToKeepStr: '7', artifactNumToKeepStr: '', daysToKeepStr: '30', numToKeepStr: '')
155+
skipStagesAfterUnstable()
156+
}
157+
triggers {
158+
parameterizedCron( env.BRANCH_NAME == 'develop' ? '''00 03 * * * % ML_SERVER_BRANCH=develop-10.0
159+
00 04 * * * % ML_SERVER_BRANCH=develop''' : '')
160+
}
161+
environment {
162+
timeStamp = sh(returnStdout: true, script: 'date +%Y%m%d').trim()
163+
dockerRegistry = 'ml-docker-dev.marklogic.com'
164+
dockerRepository = "${dockerRegistry}/marklogic/marklogic-server-centos"
165+
dockerVersion = "${ML_VERSION}-${timeStamp}-centos-1.0.0"
166+
}
167+
168+
parameters {
169+
string(name: 'emailList', defaultValue: emailList, description: 'List of email for build notification', trim: true)
170+
choice(name: 'ML_VERSION', choices: '10.0\n11.0\n9.0', description: 'MarkLogic version. used to pick appropriate docker image')
171+
booleanParam(name: 'KUBERNETES_TESTS', defaultValue: true, description: 'Run kubernetes tests')
172+
}
173+
174+
stages {
175+
stage('Pre-Build-Check') {
176+
steps {
177+
preBuildCheck()
178+
}
179+
}
180+
181+
stage('Pull-Image') {
182+
steps {
183+
pullImage()
184+
}
185+
}
186+
187+
stage('Lint') {
188+
steps {
189+
lint()
190+
}
191+
}
192+
193+
stage('Kubernetes-Run-Tests') {
194+
when {
195+
expression { return params.KUBERNETES_TESTS }
196+
}
197+
steps {
198+
sh """
199+
export MINIKUBE_HOME=/space;
200+
make test dockerImage=${dockerRepository}:${dockerVersion} saveOutput=true
201+
"""
202+
}
203+
}
204+
}
205+
206+
post {
207+
always {
208+
sh '''
209+
docker system prune --force --filter "until=720h"
210+
docker volume prune --force
211+
docker image prune --force --all
212+
minikube delete --all --purge
213+
'''
214+
publishTestResults()
215+
}
216+
success {
217+
resultNotification('BUILD SUCCESS ✅')
218+
}
219+
failure {
220+
resultNotification('BUILD ERROR ❌')
221+
}
222+
unstable {
223+
resultNotification('BUILD UNSTABLE ❌')
224+
}
225+
}
226+
}

makefile

Lines changed: 113 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,118 @@
1+
dockerImage?=marklogic-centos/marklogic-server-centos:10-internal
12

2-
install-go-modules:
3+
## System requirement:
4+
## - Go
5+
## - gotestsum (if you want to enable saveOutput for testing commands)
6+
## - golangci-lint
7+
## - Helm
8+
## - Minikube
9+
## - Docker
10+
## - GNU Make >= 3.8.2 (preferrably >=4.2.1)
11+
12+
#***************************************************************************
13+
# help
14+
#***************************************************************************
15+
## Get this help text
16+
.PHONY: help
17+
help:
18+
@printf "Usage\n";
19+
20+
@awk '{ \
21+
if ($$0 ~ /^.PHONY: [a-zA-Z\-\_0-9]+$$/) { \
22+
helpCommand = substr($$0, index($$0, ":") + 2); \
23+
if (helpMessage) { \
24+
printf "\033[36m%-20s\033[0m %s\n", \
25+
helpCommand, helpMessage; \
26+
helpMessage = ""; \
27+
} \
28+
} else if ($$0 ~ /^[a-zA-Z\-\_0-9.]+:/) { \
29+
helpCommand = substr($$0, 0, index($$0, ":")); \
30+
if (helpMessage) { \
31+
printf "\033[36m%-20s\033[0m %s\n", \
32+
helpCommand, helpMessage; \
33+
helpMessage = ""; \
34+
} \
35+
} else if ($$0 ~ /^##/) { \
36+
if (helpMessage) { \
37+
helpMessage = helpMessage"\n "substr($$0, 3); \
38+
} else { \
39+
helpMessage = substr($$0, 3); \
40+
} \
41+
} else { \
42+
if (helpMessage) { \
43+
print "\n "helpMessage"\n" \
44+
} \
45+
helpMessage = ""; \
46+
} \
47+
}' \
48+
$(MAKEFILE_LIST)
49+
50+
## ---------- Development Tasks ----------
51+
52+
#***************************************************************************
53+
# prepare
54+
#***************************************************************************
55+
## Install dependencies
56+
.PHONY: prepare
57+
prepare:
358
go mod tidy
459

5-
test/e2e: install-go-modules
6-
sh ./test/e2e/e2e.sh
60+
#***************************************************************************
61+
# lint
62+
#***************************************************************************
63+
## Lint the code
64+
## Options:
65+
## * [saveOutput] optional. Save the output to a text file. Example: saveOutput=true
66+
## * [path] optional. path to golangci-lint executable. Example: path=/home/builder/go/bin/
67+
.PHONY: lint
68+
lint:
69+
@echo "> Linting helm charts....."
70+
helm lint --with-subcharts charts/ $(if $(saveOutput),> helm-lint-output.txt,)
71+
72+
@echo "> Linting all tests....."
73+
$(if $(path),$(path),)golangci-lint run $(if $(saveOutput),> test-lint-output.txt,)
74+
75+
## ---------- Testing Tasks ----------
76+
77+
#***************************************************************************
78+
# e2e-test
79+
#***************************************************************************
80+
## Run all end to end tests
81+
## Options:
82+
## * [dockerImage] optional. default is marklogicdb/marklogic-db:latest. Example: dockerImage=marklogic-centos/marklogic-server-centos:10-internal
83+
## * [saveOutput] optional. Save the output to a xml file. Example: saveOutput=true
84+
## * [jenkins] optional. Jenkins specific enviroment setting, Example: jenkins=true
85+
86+
.PHONY: e2e-test
87+
e2e-test: prepare
88+
@echo "=====Installing minikube cluster"
89+
minikube start --driver=docker -n=1
90+
91+
@echo "=====Loading marklogc image $(dockerImage) to minikube cluster"
92+
minikube image load $(dockerImage)
93+
94+
@echo "=====Running e2e tests"
95+
cd test; $(if $(saveOutput),gotestsum --junitfile test_results/e2e-tests.xml ./e2e/... -count=1 -timeout 30m, go test -v -count=1 ./e2e/...)
96+
97+
@echo "=====Delete minikube cluster"
98+
minikube delete
799

8-
test/template: install-go-modules
9-
go test -v ./test/template/...
100+
#***************************************************************************
101+
# template-test
102+
#***************************************************************************
103+
## Run all template tests
104+
## * [saveOutput] optional. Save the output to a xml file. Example: saveOutput=true
105+
.PHONY: template-test
106+
template-test: prepare
107+
@echo "=====Running template tests"
108+
cd test; $(if $(saveOutput),gotestsum --junitfile test_results/testplate-tests.xml ./template/... -count=1, go test -v -count=1 ./test/template/...)
10109

11-
test: test/template test/e2e
110+
#***************************************************************************
111+
# test
112+
#***************************************************************************
113+
## Run all tests
114+
## Options:
115+
## * [dockerImage] optional. default is marklogicdb/marklogic-db:latest. Example: dockerImage=marklogic-centos/marklogic-server-centos:10-internal
116+
## * [saveOutput] optional. Save the output to a xml file. Example: saveOutput=true
117+
.PHONY: test
118+
test: template-test e2e-test

0 commit comments

Comments
 (0)