forked from malacourse/ParksMap
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathJenkinsfile
403 lines (358 loc) · 19.4 KB
/
Jenkinsfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
node('maven') {
try {
def checkoutFolder = "/tmp/workspace/$env.JOB_NAME"
def parksmapFolder = "$checkoutFolder/parksmap"
def nationalparksFolder = "$checkoutFolder/nationalparks"
def mlbparksFolder = "$checkoutFolder/mlbparks"
def openshiftCicdProjectName = 'demo-cicd'
def deploymentSuffix = ''
def openshiftBaseProjectName = 'parksmap' + deploymentSuffix
def openshiftDevProjectName = openshiftBaseProjectName + '-dev'
def openshiftTestProjectName = openshiftBaseProjectName + '-test'
def openshiftLiveProjectName = openshiftBaseProjectName + '-live'
// get annotated version to make sure every build has a different one
def appVersion = null
def settingsFilename = null
def mavenServerUrl = 'http://nexus.' + openshiftCicdProjectName + '.svc:8081/'
def mavenMirrorUrl = mavenServerUrl + 'repository/maven-all-public/'
def hostedMavenUrl = mavenServerUrl + 'repository/maven-releases/'
def openshiftDockgerRegistryUrl = 'docker-registry.default.svc:5000/'
def openshiftRegistryUrl = openshiftDockgerRegistryUrl + openshiftCicdProjectName + '/'
def nexusUsername = 'admin'
def nexusPassword = 'admin123'
def sonarUrl = 'http://sonarqube.' + openshiftCicdProjectName + '.svc:9000'
def sonarToken = '29c8f656bcf05f4f134273e697e856ed8536f83f'
def dockerServerUrl = 'nexus.' + openshiftCicdProjectName + '.svc:8082/'
def dockerRegistryUrl = dockerServerUrl + "$openshiftBaseProjectName-env/"
def parksmapDockerRegistryUrl = null
def nationalparksDockerRegistryUrl = null
def mlbparksDockerRegistryUrl = null
def parksmapBinaryArtifact = null
def nationalparksBinaryArtifact = null
def mlbparksBinaryArtifact = null
def imageStreamsPreffix = "$env.JOB_NAME-$env.BUILD_NUMBER"
// Start session with the service account jenkins which is the one configured by default for this builder
openshift.withCluster() {
stage('Checkout code') {
// Set explicitely the checkout folder for further references
dir(checkoutFolder) {
// checkout the source code using the git information provided by the github webhook
// This syntax allows to checkout also all annotated tags so get can get a different version each time.
checkout([
$class: 'GitSCM',
branches: scm.branches,
doGenerateSubmoduleConfigurations: scm.doGenerateSubmoduleConfigurations,
extensions: [[$class: 'CloneOption', noTags: false, shallow: false, depth: 0, reference: '']],
userRemoteConfigs: scm.userRemoteConfigs,
])
}
}
stage('Create settings file') {
settingsFilename = prepareEnvironment(checkoutFolder, mavenMirrorUrl, nexusUsername, nexusPassword)
}
stage('Get new version') {
appVersion = getAppVersion(parksmapFolder)
}
stage("Parks Map - set v$appVersion") {
setAppVersion(parksmapFolder, appVersion, settingsFilename)
parksmapDockerRegistryUrl = dockerRegistryUrl + 'parksmap:' + appVersion
nationalparksDockerRegistryUrl = dockerRegistryUrl + 'nationalparks:' + appVersion
mlbparksDockerRegistryUrl = dockerRegistryUrl + 'mlbparks:' + appVersion
}
stage('Parks Map - Building') {
build(parksmapFolder, settingsFilename)
parksmapBinaryArtifact = getBinaryArtifact(parksmapFolder, 'jar')
}
stage('Parks Map - Running unit tests') {
runUnitTests(parksmapFolder, settingsFilename, sonarUrl, sonarToken)
}
stage("National Parks - set v$appVersion") {
setAppVersion(nationalparksFolder, appVersion, settingsFilename)
}
stage('National Parks - Building') {
build(nationalparksFolder, settingsFilename)
nationalparksBinaryArtifact = getBinaryArtifact(nationalparksFolder, 'jar')
}
stage('National Parks - Running unit tests') {
runUnitTests(nationalparksFolder, settingsFilename, sonarUrl, sonarToken)
}
stage("MLB Parks - set v$appVersion") {
setAppVersion(mlbparksFolder, appVersion, settingsFilename)
}
stage('MLB Parks - Building') {
build(mlbparksFolder, settingsFilename)
mlbparksBinaryArtifact = getBinaryArtifact(mlbparksFolder, 'war')
}
stage('MLB Parks - Running unit tests') {
runUnitTests(mlbparksFolder, settingsFilename, sonarUrl, sonarToken)
}
stage('Parks Map - push jar to Nexus') {
uploadArtifactToNexus(parksmapFolder, settingsFilename, hostedMavenUrl, parksmapBinaryArtifact)
}
stage('National Parls - push jar to Nexus') {
uploadArtifactToNexus(nationalparksFolder, settingsFilename, hostedMavenUrl, nationalparksBinaryArtifact)
}
stage('MLB Parks - push war to Nexus') {
uploadArtifactToNexus(mlbparksFolder, settingsFilename, hostedMavenUrl, mlbparksBinaryArtifact)
}
def parksmapImageStream = null
def nationalparksImageStream = null
def mlbparksImageStream = null
openshift.withProject( openshiftCicdProjectName ) {
try {
stage('Parks Map - binary build') {
def baseImage = getBaseImageName('jar')
parksmapImageStream = "$imageStreamsPreffix-parksmap"
doBinaryBuild(parksmapImageStream, baseImage, parksmapBinaryArtifact, appVersion)
}
stage('National Parls - binary build') {
def baseImage = getBaseImageName('jar')
nationalparksImageStream = "$imageStreamsPreffix-nationalparks"
doBinaryBuild(nationalparksImageStream, baseImage, nationalparksBinaryArtifact, appVersion)
}
stage('MLB Parks - binary build') {
def baseImage = getBaseImageName('war')
mlbparksImageStream = "$imageStreamsPreffix-mlbparks"
doBinaryBuild(mlbparksImageStream, baseImage, mlbparksBinaryArtifact, appVersion)
}
// Execute all three next commands in another node with support for skopeo
node('skopeo') {
stage('Parks Map - push docker image to Nexus') {
uploadOcpImageToNexus(openshiftRegistryUrl + parksmapImageStream + ':' + appVersion, parksmapDockerRegistryUrl, "$nexusUsername:$nexusPassword")
}
stage('National Parls - push docker image to Nexus') {
uploadOcpImageToNexus(openshiftRegistryUrl + nationalparksImageStream + ':' + appVersion, nationalparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
}
stage('MLB Parks - push docker image to Nexus') {
uploadOcpImageToNexus(openshiftRegistryUrl + mlbparksImageStream + ':' + appVersion, mlbparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
}
}
}
finally {
stage('Cleaning up local resources') {
// Clean up local image streams and build configurations if they exist
deleteObjects( "bc/$parksmapImageStream" )
deleteObjects( "is/$parksmapImageStream" )
deleteObjects( "bc/$nationalparksImageStream" )
deleteObjects( "is/$nationalparksImageStream" )
deleteObjects( "bc/$mlbparksImageStream" )
deleteObjects( "is/$mlbparksImageStream" )
}
}
}
stage('Deploy to DEV') {
// Ask for manual approval before going to DEV
input message: "Promote v$appVersion to $openshiftDevProjectName (DEV)?", ok: "Promote"
// Pull the image into DEV
node('skopeo') {
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftDevProjectName + '/parksmap:' + appVersion, parksmapDockerRegistryUrl, "$nexusUsername:$nexusPassword")
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftDevProjectName + '/nationalparks:' + appVersion, nationalparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftDevProjectName + '/mlbparks:' + appVersion, mlbparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
}
// Single deployment into DEV
doSingleDeployment(openshiftDevProjectName, deploymentSuffix, openshiftDockgerRegistryUrl + openshiftDevProjectName + '/parksmap:' + appVersion, openshiftDockgerRegistryUrl + openshiftDevProjectName + '/nationalparks:' + appVersion, openshiftDockgerRegistryUrl + openshiftDevProjectName + '/mlbparks:' + appVersion)
}
stage('Running integration tests') {
// Run integration tests in DEV
openshift.withProject( openshiftDevProjectName ) {
def parksmapUrl = 'http://' + openshift.selector('route', 'parksmap').object().spec.host
def nationalparksUrl = 'http://' + openshift.selector('route', 'nationalparks').object().spec.host
def mlbparksUrl = 'http://' + openshift.selector('route', 'mlbparks').object().spec.host
runIntegrationTests(parksmapFolder, settingsFilename, sonarUrl, sonarToken, parksmapUrl, nationalparksUrl, mlbparksUrl)
}
}
stage('Deploy to TEST') {
// Ask for manual approval before going to TEST
input message: "Promote v$appVersion to $openshiftTestProjectName (TEST)?", ok: "Promote"
// Pull the image into TEST
node('skopeo') {
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftTestProjectName + '/parksmap:' + appVersion, parksmapDockerRegistryUrl, "$nexusUsername:$nexusPassword")
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftTestProjectName + '/nationalparks:' + appVersion, nationalparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftTestProjectName + '/mlbparks:' + appVersion, mlbparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
}
// Single deployment into TEST
doSingleDeployment(openshiftTestProjectName, deploymentSuffix, openshiftDockgerRegistryUrl + openshiftTestProjectName + '/parksmap:' + appVersion, openshiftDockgerRegistryUrl + openshiftTestProjectName + '/nationalparks:' + appVersion, openshiftDockgerRegistryUrl + openshiftTestProjectName + '/mlbparks:' + appVersion)
}
stage('Running smoke tests') {
// Run integration tests in TEST
openshift.withProject( openshiftTestProjectName ) {
def parksmapUrl = 'http://' + openshift.selector('route', 'parksmap').object().spec.host
def nationalparksUrl = 'http://' + openshift.selector('route', 'nationalparks').object().spec.host
def mlbparksUrl = 'http://' + openshift.selector('route', 'mlbparks').object().spec.host
runIntegrationTests(parksmapFolder, settingsFilename, sonarUrl, sonarToken, parksmapUrl, nationalparksUrl, mlbparksUrl)
}
}
stage('Deploy to LIVE') {
// Ask for manual approval before going to LIVE
input message: "Promote v$appVersion to $openshiftLiveProjectName (LIVE)?", ok: "Promote"
// Pull the image into LIVE
node('skopeo') {
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftLiveProjectName + '/parksmap:' + appVersion, parksmapDockerRegistryUrl, "$nexusUsername:$nexusPassword")
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftLiveProjectName + '/nationalparks:' + appVersion, nationalparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
pullImageFromNexusToOcp(openshiftDockgerRegistryUrl + openshiftLiveProjectName + '/mlbparks:' + appVersion, mlbparksDockerRegistryUrl, "$nexusUsername:$nexusPassword")
}
// Blue/Green deployment into LIVE
doBlueGreenDeployment(openshiftLiveProjectName, deploymentSuffix, openshiftDockgerRegistryUrl + openshiftLiveProjectName + '/parksmap:' + appVersion, openshiftDockgerRegistryUrl + openshiftLiveProjectName + '/nationalparks:' + appVersion, openshiftDockgerRegistryUrl + openshiftLiveProjectName + '/mlbparks:' + appVersion)
}
stage('Running smoke tests') {
// Run integration tests in LIVE
openshift.withProject( openshiftLiveProjectName ) {
def parksmapUrl = 'http://' + openshift.selector('route', 'parksmap').object().spec.host
def nationalparksUrl = 'http://' + openshift.selector('route', 'nationalparks').object().spec.host
def mlbparksUrl = 'http://' + openshift.selector('route', 'mlbparks').object().spec.host
runIntegrationTests(parksmapFolder, settingsFilename, sonarUrl, sonarToken, parksmapUrl, nationalparksUrl, mlbparksUrl)
}
}
}
}
finally {
// Place any notification to an external system we need to do in case of success or failure
}
}
def getAppVersion(def appFolder) {
// Gets the app version from the git repo, not the pom file or any other resources from the application itself.
dir(appFolder) {
def appVersion = sh script: "git describe 2> /dev/null || echo '0.0.0-no-tags'", returnStdout: true
return appVersion.trim()
}
}
def prepareEnvironment(def folder, def mavenMirrorUrl, def nexusUsername, def nexusPassword) {
def filename = 'temp_settings.xml'
def authSection = "<servers><server><id>nexus-maven-mirror</id><username>$nexusUsername</username><password>$nexusPassword</password></server></servers>"
dir (folder) {
sh """
echo "<?xml version='1.0'?><settings>$authSection<mirrors><mirror><id>nexus-maven-mirror</id><name>Nexus Maven Mirror</name><url>$mavenMirrorUrl</url><mirrorOf>*</mirrorOf></mirror></mirrors></settings>" > $filename
"""
return "$folder/$filename"
}
}
def setAppVersion(def appFolder, def appVersion, def settingsFilename) {
dir (appFolder) {
sh """
mvn -s $settingsFilename versions:set versions:commit -DnewVersion="$appVersion"
"""
}
}
def build(def appFolder, def settingsFilename) {
dir (appFolder) {
sh """
mvn -s $settingsFilename package -DskipTests
"""
}
}
def runUnitTests(def appFolder, def settingsFilename, def sonarUrl, def sonarToken) {
dir (appFolder) {
try {
sh """
mvn -s $settingsFilename test
"""
}
finally {
junit 'target/*reports/**/*.xml'
sh """
mvn -s $settingsFilename sonar:sonar -Dsonar.host.url=$sonarUrl -Dsonar.login=$sonarToken -Dsonar.jacoco.reportPaths=target/coverage-reports/jacoco-ut.exec
"""
jacoco(execPattern: 'target/**/*.exec')
}
}
}
def runIntegrationTests(def appFolder, def settingsFilename, def sonarUrl, def sonarToken, def parksmapUrl, def nationalparksUrl, def mlbparksUrl) {
dir (appFolder) {
try {
sh """
mvn -s $settingsFilename clean verify -Dnationalparks.base.url="$nationalparksUrl" -Dmlbparks.base.url="$mlbparksUrl" -Dparksmap.base.url="$parksmapUrl"
"""
}
finally {
// junit 'target/*reports/**/*.xml'
sh """
mvn -s $settingsFilename sonar:sonar -Dsonar.host.url=$sonarUrl -Dsonar.login=$sonarToken -Dsonar.jacoco.reportPaths=target/coverage-reports/jacoco-it.exec
"""
}
}
}
def getBinaryArtifact(def appFolder, def artifactExtension) {
return sh(script: "ls $appFolder/target/*.$artifactExtension", returnStdout: true).trim()
}
def getBaseImageName(def artifactExtension) {
return (artifactExtension == 'jar') ? 'openjdk18-openshift:1.3' : 'eap71-openshift:1.2'
}
def uploadArtifactToNexus(def appFolder, def settingsFilename, def repositoryUrl, def artifactFilename) {
dir(appFolder) {
sh """
mvn -s $settingsFilename deploy:deploy-file -DgeneratePom=false -DpomFile=pom.xml -DrepositoryId=nexus-maven-mirror -Durl=$repositoryUrl -Dfile=$artifactFilename
"""
}
}
def doBinaryBuild(def imageStream, def baseImage, def binaryArtifact, def appVersion) {
// Creation of the build config
openshift.newBuild("--allow-missing-imagestream-tags=true", "--binary=true", "-i '$baseImage'", "--name='$imageStream'", "--to='$imageStream:$appVersion'")
// Start the binary build
openshift.raw("start-build", "$imageStream", "--from-file='$binaryArtifact'", "--follow")
}
def uploadOcpImageToNexus(def openshiftStreamTag, def nexusImageStreamTag, def nexusCredentials) {
def srcCredentials = 'jenkins:' + sh(script: "oc whoami -t", returnStdout: true).trim()
sh """
set +x
skopeo copy --src-tls-verify=false --dest-tls-verify=false --src-creds=$srcCredentials --dest-creds='$nexusCredentials' docker://$openshiftStreamTag docker://$nexusImageStreamTag
"""
}
def deleteObjects( def selectorString ) {
openshift.selector( selectorString ).withEach {
it.delete( "--cascade=true", "--ignore-not-found=true", "--force=true", "--grace-period=0" )
}
}
def pullImageFromNexusToOcp(def openshiftStreamTag, def nexusImageStreamTag, def nexusCredentials) {
def destCredentials = 'jenkins:' + sh(script: "oc whoami -t", returnStdout: true).trim()
sh """
set +x
skopeo copy --src-tls-verify=false --dest-tls-verify=false --src-creds='$nexusCredentials' --dest-creds=$destCredentials docker://$nexusImageStreamTag docker://$openshiftStreamTag
"""
}
def patchDeploymentAndRollout(def dcName, def containerName, def imageStreamTag) {
openshift.raw("set", "triggers", "dc/$dcName", "--remove-all")
openshift.raw("set", "image", "dc/$dcName", "$containerName=$imageStreamTag")
def dc = openshift.selector('dc', dcName)
// Set image
dc.rollout().latest()
def latestDeploymentVersion = dc.object().status.latestVersion
def rc = openshift.selector('rc', "$dcName-${latestDeploymentVersion}")
rc.untilEach(1){
def rcMap = it.object()
return (rcMap.status.replicas.equals(rcMap.status.readyReplicas))
}
}
def doSingleDeployment(def projectName, def deploymentSuffix, def parksmapImageStramTag, def nationalparksImageStreamTag, def mlbparksImageStreamTag) {
openshift.withProject( projectName ) {
def parksmapDcName = "parksmap$deploymentSuffix"
def nationalparksDcName = "nationalparks$deploymentSuffix"
def mlbparksDcName = "mlbparks$deploymentSuffix"
def parksmapContainerName = "parksmap"
def nationalparksContainerName = "nationalparks"
def mlbparksContainerName = "mlbparks"
patchDeploymentAndRollout(nationalparksDcName, nationalparksContainerName, nationalparksImageStreamTag)
patchDeploymentAndRollout(mlbparksDcName, mlbparksContainerName, mlbparksImageStreamTag)
patchDeploymentAndRollout(parksmapDcName, parksmapContainerName, parksmapImageStramTag)
}
}
def patchService(def serviceName, def targetDeployment) {
def svc = openshift.selector('svc', serviceName).object()
svc.spec.selector.deploymentConfig = targetDeployment
openshift.apply(svc)
}
def patchRoute(def routeName, def serviceName) {
def route = openshift.selector('route', routeName).object()
route.spec.to.name = serviceName
openshift.apply(route)
}
def doBlueGreenDeployment(def projectName, def deploymentSuffix, def parksmapImageStramTag, def nationalparksImageStreamTag, def mlbparksImageStreamTag) {
openshift.withProject( projectName ) {
//Use any of them because they will all changed at the same time and, if not, they will be sync in the next deployment.
def svc = openshift.selector('svc', 'nationalparks' + deploymentSuffix).object()
def targetDeployment = svc.spec.selector.deploymentConfig.endsWith('green') ? 'blue' : 'green'
doSingleDeployment(projectName, "$deploymentSuffix-$targetDeployment", parksmapImageStramTag, nationalparksImageStreamTag, mlbparksImageStreamTag)
patchService('nationalparks' + deploymentSuffix, 'nationalparks' + deploymentSuffix + '-' + targetDeployment)
patchService('mlbparks' + deploymentSuffix, 'mlbparks' + deploymentSuffix + '-' + targetDeployment)
patchRoute('parksmap' + deploymentSuffix, 'parksmap' + deploymentSuffix + '-' + targetDeployment)
}
}