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: {
},
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)
},
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'
}
}
}
}
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 namespace, String values, String imageTag) {
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=${imageTag} --namespace ${namespace}" + ' --repo https://nexus.ozg-sh.de/repository/ozg-base-apps --username ${USER} --password ${PASSWORD} --wait --wait-for-jobs'
createKeycloakGroups(namespace)
generateKeycloakUserYaml(namespace)
applyKeycloakUser(namespace)
}
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"
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)
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)
def groupJson = sh (script: "cat goofy-client/apps/goofy-e2e/src/fixtures/group/${group}", returnStdout: true)
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 namespace) {
dir(namespace){
def kcUserFiles = sh (script: "ls", returnStdout: true)
kcUserFiles.split("\\n").each { user ->
sh "kubectl apply -f ${user}"
}
}
}
Void removeKeycloakUser(String namespace) {
dir(namespace){
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 shScript = """curl -H 'Content-Type: application/json' \
-H 'Authorization: bearer ${getKeycloakAccessToken()}' \
'https://sso.dev.ozg-sh.de/auth/admin/realms/${realm}/users'
"""
def users = readJSON text: sh(script: shScript, returnStdout: true)
for(user in users) {
}
}
}
String getKeycloakAccessToken() {
withCredentials([usernamePassword(credentialsId: 'keycloak-login', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) {
def token = readJSON text: 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 token.access_token