-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJenkinsfile
309 lines (267 loc) · 12.9 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
#!groovy
@Library(['github.com/cloudogu/[email protected]', 'github.com/cloudogu/[email protected]']) _
import com.cloudogu.ces.dogubuildlib.*
import com.cloudogu.ces.cesbuildlib.*
node('vagrant') {
Git git = new Git(this)
GitFlow gitflow = new GitFlow(this, git)
doguName="swaggerui"
timestamps{
properties([
// Keep only the last x builds to preserve space
buildDiscarder(logRotator(numToKeepStr: '10')),
// Don't run concurrent builds for a branch, because they use the same workspace directory
disableConcurrentBuilds(),
parameters([
booleanParam(defaultValue: false, description: 'Test dogu upgrade from latest release or optionally from defined version below', name: 'TestDoguUpgrade'),
booleanParam(defaultValue: true, description: 'Enables cypress to record video of the integration tests.', name: 'EnableVideoRecording'),
booleanParam(defaultValue: true, description: 'Enables cypress to take screenshots of failing integration tests.', name: 'EnableScreenshotRecording'),
string(defaultValue: '', description: 'Old Dogu version for the upgrade test (optional; e.g. 4.1.0-3)', name: 'OldDoguVersionForUpgradeTest'),
choice(name: 'TrivySeverityLevels', choices: [TrivySeverityLevel.CRITICAL, TrivySeverityLevel.HIGH_AND_ABOVE, TrivySeverityLevel.MEDIUM_AND_ABOVE, TrivySeverityLevel.ALL], description: 'The levels to scan with trivy', defaultValue: TrivySeverityLevel.CRITICAL),
choice(name: 'TrivyStrategy', choices: [TrivyScanStrategy.UNSTABLE, TrivyScanStrategy.FAIL, TrivyScanStrategy.IGNORE], description: 'Define whether the build should be unstable, fail or whether the error should be ignored if any vulnerability was found.', defaultValue: TrivyScanStrategy.UNSTABLE),
])
])
EcoSystem ecoSystem = new EcoSystem(this, "gcloud-ces-operations-internal-packer", "jenkins-gcloud-ces-operations-internal")
stage('Checkout') {
checkout scm
sh 'git submodule update --init'
}
stage('Lint') {
lintDockerfile()
shellCheck("./resources/startup.sh")
}
try {
stage('Provision') {
// change namespace to prerelease_namespace if in develop-branch
if (gitflow.isPreReleaseBranch()) {
sh "make prerelease_namespace"
}
ecoSystem.provision("/dogu")
}
stage('Setup') {
ecoSystem.loginBackend('cesmarvin-setup')
ecoSystem.setup()
}
stage('Wait for dependencies') {
timeout(15) {
ecoSystem.waitForDogu("nginx")
}
}
stage('Build') {
ecoSystem.build("/dogu")
}
stage('Trivy scan') {
ecoSystem.copyDoguImageToJenkinsWorker("/dogu")
Trivy trivy = new Trivy(this)
trivy.scanDogu(".", params.TrivySeverityLevels, params.TrivyStrategy)
trivy.saveFormattedTrivyReport(TrivyScanFormat.TABLE)
trivy.saveFormattedTrivyReport(TrivyScanFormat.JSON)
trivy.saveFormattedTrivyReport(TrivyScanFormat.HTML)
}
stage('Verify') {
ecoSystem.verify("/dogu")
}
stage('Wait for swagger dogu') {
timeout(15) {
ecoSystem.waitForDogu("swaggerui")
}
}
stage('Integration Tests') {
echo "run integration tests."
ecoSystem.runCypressIntegrationTests([
cypressImage : "cypress/included:13.15.2",
enableVideo : params.EnableVideoRecording,
enableScreenshots: params.EnableScreenshotRecording,
])
}
if (params.TestDoguUpgrade != null && params.TestDoguUpgrade) {
stage('Upgrade dogu') {
// Remove new dogu that has been built and tested above
ecoSystem.purgeDogu(doguName)
if (params.OldDoguVersionForUpgradeTest != '' && !params.OldDoguVersionForUpgradeTest.contains('v')) {
println "Installing user defined version of dogu: " + params.OldDoguVersionForUpgradeTest
ecoSystem.installDogu("official/" + doguName + " " + params.OldDoguVersionForUpgradeTest)
} else {
println "Installing latest released version of dogu..."
ecoSystem.installDogu("official/" + doguName)
}
installTestPlugin(ecoSystem, testPluginName)
ecoSystem.startDogu(doguName)
ecoSystem.waitForDogu(doguName)
ecoSystem.upgradeDogu(ecoSystem)
// Wait for upgraded dogu to get healthy
ecoSystem.waitForDogu(doguName)
ecoSystem.waitUntilAvailable(doguName)
}
stage('Integration Tests - After Upgrade') {
// Run integration tests again to verify that the upgrade was successful
runIntegrationTests(ecoSystem)
}
}
if (isReleaseBranch()) {
stage('Finish Release') {
String releaseVersion = getReleaseVersion();
echo "Your release version is: ${releaseVersion}"
// Check if tag already exists
if (tagExists("${releaseVersion}")){
error("You cannot build this version, because it already exists.")
}
// Make sure all branches are fetched
sh "git config 'remote.origin.fetch' '+refs/heads/*:refs/remotes/origin/*'"
gitWithCredentials("fetch --all")
// Make sure there are no changes on develop
if (developHasChanged(env.BRANCH_NAME)){
error("There are changes on develop branch that are not merged into release. Please merge and restart process.")
}
// Make sure any branch we need exists locally
sh "git checkout ${env.BRANCH_NAME}"
gitWithCredentials("pull origin ${env.BRANCH_NAME}")
sh "git checkout develop"
gitWithCredentials("pull origin develop")
sh "git checkout master"
gitWithCredentials("pull origin master")
// Merge release branch into master
sh "git merge --no-ff ${env.BRANCH_NAME}"
// Create tag. Use -f because the created tag will persist when build has failed.
gitWithCredentials("tag -f -m 'release version ${releaseVersion}' ${releaseVersion}")
// Merge release branch into develop
sh "git checkout develop"
sh "git merge --no-ff ${env.BRANCH_NAME}"
// Delete release branch
sh "git branch -d ${env.BRANCH_NAME}"
// Checkout tag
sh "git checkout ${releaseVersion}"
}
stage ('Push changes to Github'){
// Push changes and tags
gitWithCredentials("push origin master")
gitWithCredentials("push origin develop")
gitWithCredentials("push origin --tags")
gitWithCredentials("push origin --delete ${env.BRANCH_NAME}")
}
stage('Push Dogu to registry') {
ecoSystem.push("/dogu")
}
//Create release on Github
changelog = ""
try{
stage ('Get Changelog'){
changelog = getChangelog(releaseVersion)
}
} catch(Exception e){
echo "Failed to read changes in changelog due to error: ${e}"
echo "Please manually update github release."
}
try{
stage ('Add Github-Release'){
echo "The description of github release will be: >>>${changelog}<<<"
addGithubRelease(releaseVersion, changelog, git)
}
} catch(Exception e) {
echo "Release failed due to error: ${e}"
}
} else if (gitflow.isPreReleaseBranch()) {
// push to registry in prerelease_namespace
stage('Push Prerelease Dogu to registry') {
ecoSystem.pushPreRelease("/dogu")
}
}
} finally {
stage('Clean') {
ecoSystem.destroy()
}
}
}
}
def runIntegrationTests(EcoSystem ecoSystem) {
ecoSystem.runCypressIntegrationTests([
cypressImage : "cypress/included:13.15.2",
enableVideo : params.EnableVideoRecording,
enableScreenshots : params.EnableScreenshotRecording
])
}
String getChangelog(String releaseVersion){
start = getChangelogStartIndex(releaseVersion)
end = getChangelogEndIndex(start)
output = sh (
script: "sed '${start},${end}!d' CHANGELOG.md",
returnStdout: true
).trim()
return output.replace("\"", "").replace("'", "").replace("\\", "").replace("\n", "\\n")
}
int getChangelogStartIndex(String releaseVersion){
startLineString = "## \\[${releaseVersion}\\]"
script = "grep -n \"${startLineString}\" CHANGELOG.md | head -1 | sed s/\"^\\([0-9]*\\)[:].*\$\"/\"\\1\"/g"
output = sh (
script: script,
returnStdout: true
).trim()
return (output as int) + 1
}
String getChangelogEndIndex(int start){
script = "tail -n +${start+1} CHANGELOG.md |grep -n \"^## \\[.*\\]\" | sed s/\"^\\([0-9]*\\)[:].*\$\"/\"\\1\"/g | head -1"
output = sh (
script: script,
returnStdout: true
).trim()
if ((output as String).length() > 0){
return ((output as int) + start - 1) as String
}
return "\$"
}
String getRepositoryName(Git git){
scmUrl = git.getRepositoryUrl()
start = scmUrl.lastIndexOf("/")
repoName = scmUrl.substring(start+1).replace(".git", "")
return repoName
}
void addGithubRelease(String releaseVersion, String changes, Git git){
name = getRepositoryName(git);
echo "Creating github release..."
withCredentials([usernamePassword(credentialsId: 'cesmarvin', usernameVariable: 'GIT_AUTH_USR', passwordVariable: 'GIT_AUTH_PSW')]) {
body = "'{\"tag_name\": \"${releaseVersion}\", \"target_commitish\": \"master\", \"name\": \"${releaseVersion}\", \"body\":\"${changes}\"}'"
apiUrl = "https://api.github.com/repos/cloudogu/${name}/releases"
flags = "--request POST --data ${body} --header \"Content-Type: application/json\""
script = "curl -u ${GIT_AUTH_USR}:${GIT_AUTH_PSW} ${flags} ${apiUrl}"
output = sh (
script: script,
returnStdout: true
).trim()
echo output
}
echo "Github release created..."
}
boolean isReleaseBranch() {
return env.BRANCH_NAME.startsWith("release/");
}
String getReleaseVersion() {
return env.BRANCH_NAME.substring("release/".length());
}
void gitWithCredentials(String command){
withCredentials([usernamePassword(credentialsId: 'cesmarvin', usernameVariable: 'GIT_AUTH_USR', passwordVariable: 'GIT_AUTH_PSW')]) {
sh (
script: "git -c credential.helper=\"!f() { echo username='\$GIT_AUTH_USR'; echo password='\$GIT_AUTH_PSW'; }; f\" " + command,
returnStdout: true
)
}
}
boolean tagExists(String tag){
withCredentials([usernamePassword(credentialsId: 'cesmarvin', usernameVariable: 'GIT_AUTH_USR', passwordVariable: 'GIT_AUTH_PSW')]) {
tagFound = sh (
script: "git -c credential.helper=\"!f() { echo username='\$GIT_AUTH_USR'; echo password='\$GIT_AUTH_PSW'; }; f\" ls-remote origin refs/tags/${tag}",
returnStdout: true
).trim()
if (tagFound.length() > 0) return true
return false
}
}
boolean developHasChanged(String releaseBranchName){
withCredentials([usernamePassword(credentialsId: 'cesmarvin', usernameVariable: 'GIT_AUTH_USR', passwordVariable: 'GIT_AUTH_PSW')]) {
diff = sh (
script: "git log origin/${releaseBranchName}..origin/develop --oneline",
returnStdout: true
).trim()
if (diff.length() > 0) return true
return false
}
}