Newer
Older
environment {
BLUE_OCEAN_URL = "https://jenkins.ozg-sh.de/blue/organizations/jenkins/goofy/detail/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/pipeline"
RELEASE_REGEX = /\d+.\d+.\d+/
SNAPSHOT_REGEX = /\d+.\d+.\d+-SNAPSHOT/
options {
timeout(time: 1, unit: 'HOURS')
disableConcurrentBuilds()
FAILED_STAGE = env.STAGE_NAME
IMAGE_TAG = 'latest'
}
container("k8s") {
configFileProvider([configFile(fileId: 'jenkins-kuby-kubeconfig', variable: 'KUBE_CONFIG')]) {
sh 'mkdir ~/.kube'
sh 'cp ${KUBE_CONFIG} ~/.kube/config'
}
sh 'helm version'
}
container('nodejs') {
dir('goofy-client') {
sh 'npm install --no-optional'
}
}
}
}
stage('E2E') {
failFast false
parallel {
stage('E2E-EA') {
when {
branch 'ozg-1784'
}
steps {
script {
def stageName = env.STAGE_NAME
def namespace = generateNamespaceName(stageName)
checkIfNamespaceExists(namespace)
parallel(
startGoofy: {
startGoofy(namespace, stageName, 'ea-values.yaml')
},
startPluto: {
startPluto(namespace, 'ea-values.yaml')
}
)
if(runTests(stageName, 'einheitlicher-ansprechpartner') != '0') {
E2E_FAILED = true
}
}
post {
always {
publishHTML (target: [
allowMissing: false,
alwaysLinkToLastBuild: false,
keepAll: true,
reportDir: 'goofy-client/apps/goofy-e2e/reports/einheitlicher-ansprechpartner',
reportFiles: 'report.html',
reportName: "Goofy E2E-Tests EA"
])
}
}
}
stage('E2E-main') {
when {
branch 'ozg-1784'
}
steps {
script {
def stageName = env.STAGE_NAME
def namespace = generateNamespaceName(stageName)
parallel(
startGoofy: {
startGoofy(namespace, stageName, 'values.yaml')
},
startPluto: {
startPluto(namespace, 'values.yaml')
if(runTests(stageName, 'main-tests') != '0') {
E2E_FAILED = true
}
shutdownEnvironment(namespace)
}
}
post {
always {
publishHTML (target: [
allowMissing: false,
alwaysLinkToLastBuild: false,
keepAll: true,
reportDir: 'goofy-client/apps/goofy-e2e/reports/main-tests',
reportFiles: 'report.html',
reportName: "Goofy E2E-Tests main"
])
}
post {
always {
script {
if (E2E_FAILED) {
currentBuild.result = 'FAILURE'
}
}
}
}
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
Void checkIfNamespaceExists(String namespace) {
container("k8s") {
def namespaceList = sh (script: 'kubectl get namespaces', returnStdout: true)
if(namespaceList.contains(namespace)) {
error("Namespace: ${namespace} existiert bereits")
}
}
}
Void startPluto(String namespace, String values) {
container("k8s") {
dir('goofy-client/apps/goofy-e2e/deployment-values/pluto') {
withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) {
sh "helm upgrade --install --create-namespace pluto pluto -f ${values} --namespace ${namespace}" + ' --repo https://nexus.ozg-sh.de/repository/ozg-base-apps --username ${USER} --password ${PASSWORD} --wait --wait-for-jobs'
}
}
sh "kubectl rollout status statefulset/pluto-database -n ${namespace}"
}
}
Void startGoofy(String stageName, String namespace, String values) {
container("k8s") {
dir('goofy-client/apps/goofy-e2e/deployment-values/goofy') {
withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) {
sh "helm upgrade --install --create-namespace goofy goofy -f ${values} --set image.tag=${IMAGE_TAG} --namespace ${namespace}" + ' --repo https://nexus.ozg-sh.de/repository/ozg-base-apps --username ${USER} --password ${PASSWORD} --wait --wait-for-jobs'
}
}
createKeycloakGroups(stageName)
generateKeycloakUserYaml(stageName)
applyKeycloakUser(stageName)
}
Void runTests(String stageName, String reportFolder) {
container("cypress") {
def configFile = generateCypressConfig(stageName, reportFolder)
dir("goofy-client") {
sh "npm run cypress:version"
return sh (script: "npm run cypress:ci-run --CONFIG_FILE=${configFile} --REPORT_FOLDER=${reportFolder}", returnStatus: true)
}
}
}
Void shutdownEnvironment(String namespace) {
container("k8s") {
sh "helm uninstall goofy --namespace ${namespace} --wait"
sh "helm uninstall pluto --namespace ${namespace} --wait"
removeKeycloakUser(stageName)
sh "kubectl delete namespace ${namespace}"
}
}
String makeUrlConform(String input) {
return input.replaceAll(/[^a-zA-Z0-9]+/, "").toLowerCase()
def branchName = makeUrlConform(env.BRANCH_NAME)
def stageName = makeUrlConform(stage)
Void generateKeycloakUserYaml(String stage) {
def namespace = generateNamespaceName(stage)
def e2eUserFiles = sh (script: 'ls goofy-client/apps/goofy-e2e/src/fixtures/user', returnStdout: true)
def newUserYaml = readYaml file: "goofy-client/apps/goofy-e2e/deployment-values/goofy/user/user.yaml"
def userJson = readJSON file: 'goofy-client/apps/goofy-e2e/src/fixtures/user/'+user
newUserYaml.metadata.name = namespace + "-" + userJson.name
newUserYaml.metadata.labels.realm = namespace
newUserYaml.spec.realmSelector.matchLabels.realm = namespace
newUserYaml.spec.user.username = userJson.name
newUserYaml.spec.user.credentials = [[type: 'password', value: userJson.password]]
if(userJson.firstName) {
newUserYaml.spec.user.firstName = userJson.firstName
}
if(userJson.lastName) {
newUserYaml.spec.user.lastName = userJson.lastName
}
if(userJson.realmRoles) {
newUserYaml.spec.user.realmRoles += userJson.realmRoles
}
if(userJson.groups) {
newUserYaml.spec.user.groups = userJson.groups
}
dir (namespace) {
writeYaml file: userJson.name+".yaml", data: newUserYaml
}
}
}
Void createKeycloakGroups(String realm) {
def groupFiles = sh (script: 'ls goofy-client/apps/goofy-e2e/src/fixtures/group', returnStdout: true)
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
groupFiles.split("\\n").each { group ->
def groupJson = readJSON file: 'goofy-client/apps/goofy-e2e/src/fixtures/group/'+group
sh """curl -X POST 'https://sso.dev.ozg-sh.de/auth/admin/realms/${realm}/groups' \
-H 'Content-Type: application/json' \
-H 'Authorization: bearer ${getKeycloakAccessToken()}' \
--data-raw '${groupJson}'
"""
}
}
Void applyKeycloakUser(String stage) {
dir(generateNamespaceName(stage)){
def kcUserFiles = sh (script: "ls", returnStdout: true)
kcUserFiles.split("\\n").each { user ->
sh "kubectl apply -f ${user}"
}
}
}
Void removeKeycloakUser(String stage) {
dir(generateNamespaceName(stage)){
def kcUserFiles = sh (script: "ls", returnStdout: true)
kcUserFiles.split("\\n").each { user ->
sh "kubectl delete -f ${user}"
}
}
}
String generateCypressConfig(String stage, String testFolder) {
def namespace = generateNamespaceName(stage)
def configName = "cypress-ci-"+testFolder+".json"
dir('goofy-client/apps/goofy-e2e/'){
def config = readJSON file: 'cypress-ci.json'
config.baseUrl = "https://${makeUrlConform(env.BRANCH_NAME)}${makeUrlConform(stage)}.dev.ozg-sh.de" as String
config.env.dbUrl = "mongodb+srv://pluto-database-user:XnHhfznNWg65NNd@pluto-database-svc.${namespace}.svc.cluster.local/admin?ssl=false" as String
config.env.keycloakRealm = namespace as String
config.env.keycloakClient = namespace + "-goofy" as String
config.env.sabineUuid = getKeycloakUuid(namespace, 'sabine') as String
config.integrationFolder = "./src/integration/${testFolder}" as String
config.videosFolder = "./reports/${testFolder}/videos" as String
config.screenshotsFolder = "./reports/${testFolder}/screenshots" as String
config.reporterOptions.reportDir = "./reports/${testFolder}/mochawesome-report" as String
writeJSON file: configName, json: config
return configName
}
String getKeycloakUuid(realm, userName) {
def users = sh (script: """curl -X POST 'https://sso.dev.ozg-sh.de/auth/admin/realms/${realm}/users' \
-H 'Content-Type: application/json' \
-H 'Authorization: bearer ${getKeycloakAccessToken()}'
""", returnStdout: true)
users.each { user ->
if (user.username == userName) {
return user.id
}
}
}
String getKeycloakAccessToken() {
withCredentials([usernamePassword(credentialsId: 'keycloak-login', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) {
def token = sh (script: 'curl -d "client_id=admin-cli" -d "username=$USER" -d "password=$PASSWORD" -d "grant_type=password" "https://sso.dev.ozg-sh.de/auth/realms/master/protocol/openid-connect/token"', returnStdout: true)
return access_token = token.split('"')[3]
}