From 71a393d152c703100d689edbf1c5fa09356b09fb Mon Sep 17 00:00:00 2001 From: OZGCloud <ozgcloud@mgm-tp.com> Date: Tue, 13 Jun 2023 09:44:05 +0200 Subject: [PATCH] add Jenkinsfile --- Jenkinsfile | 362 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 362 insertions(+) create mode 100644 Jenkinsfile diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000..9e5cc8b --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,362 @@ +pipeline { + agent { + node { + label 'jenkins-build-agent' + } + } + + environment { + BLUE_OCEAN_URL = "https://jenkins.ozg-sh.de/job/ozg-operator/job/${env.BRANCH_NAME}/${env.BUILD_NUMBER}/" + RELEASE_REGEX = /\d+.\d+.\d+/ + SNAPSHOT_REGEX = /\d+.\d+.\d+-SNAPSHOT/ + FAILED_STAGE = "" + SH_SUCCESS_STATUS_CODE = 0 + } + + options { + timeout(time: 1, unit: 'HOURS') + disableConcurrentBuilds() + buildDiscarder(logRotator(numToKeepStr: '5')) + } + + stages { + stage('Check Version') { + steps { + script { + FAILED_STAGE = env.STAGE_NAME + def rootPom = readMavenPom file: 'pom.xml' + def rootVersion = rootPom.version + + + if(env.BRANCH_NAME == 'release'){ + if ( !isReleaseVersion([rootVersion])) { + error("Keine Release Version für Branch ${env.BRANCH_NAME}.") + } + } else { + if ( !isSnapshotVersion([rootVersion])) { + error("Keine Snapshot Version für Branch ${env.BRANCH_NAME}.") + } + } + } + } + } + stage('Build OZG-Operator') { + steps { + script { + FAILED_STAGE=env.STAGE_NAME + } + configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { + sh 'mvn --version' + sh 'mvn -s $MAVEN_SETTINGS -Pnative spring-boot:build-image -Dmaven.wagon.http.retryHandler.count=3' + + script { + try { + if (env.BRANCH_NAME == 'master') { + withSonarQubeEnv('sonarqube-ozg-sh'){ + sh 'mvn -s $MAVEN_SETTINGS sonar:sonar' + } + } + } catch (Exception e) { + unstable("SonarQube failed") + } + } + } + } + post { + always{ + junit testResults: '**/target/surefire-reports/*.xml', skipPublishingChecks: true + } + } + } + + stage('Deploy to Nexus'){ + when { + anyOf { + branch 'master' + branch 'release' + } + } + steps { + script { + FAILED_STAGE = env.STAGE_NAME + } + configFileProvider([configFile(fileId: 'maven-settings', variable: 'MAVEN_SETTINGS')]) { + sh 'mvn -s $MAVEN_SETTINGS -DskipTests deploy' + } + } + } + + stage('Tag and Push Docker image') { + steps { + script { + FAILED_STAGE=env.STAGE_NAME + IMAGE_TAG = generateImageTag() + + tagAndPushDockerImage('ozg-operator', IMAGE_TAG) + + if (env.BRANCH_NAME == 'master') { + tagAndPushDockerImage('ozg-operator', 'snapshot-latest') + } + else if (env.BRANCH_NAME == 'release') { + tagAndPushDockerImage('ozg-operator', 'latest') + } + } + } + } + + stage('Test, build and deploy Helm Chart') { + steps { + script { + FAILED_STAGE=env.STAGE_NAME + HELM_CHART_VERSION = generateHelmChartVersion() + + dir('src/main/helm') { + sh "helm lint -f ../../linter-values.yaml" + + sh "helm unittest --helm3 -f '../../test/helm/*.yaml' ." + + sh "helm package --version=${HELM_CHART_VERSION} ." + + deployHelmChart("ozg-operator", HELM_CHART_VERSION) + } + } + } + } + + stage ('OWASP Dependency-Check Vulnerabilities') { + when { + anyOf { + branch 'master' + branch 'release' + } + } + steps { + dependencyCheck additionalArguments: ''' + -o "./" + -s "./" + -f "ALL" + -d /dependency-check-data + --suppression dependency-check-supressions.xml + --disableKnownExploited + --disableArchive + --prettyPrint''', odcInstallation: 'dependency-check-owasp' + + dependencyCheckPublisher pattern: 'dependency-check-report.xml' + } + } + } + post { + failure { + script { + if (env.BRANCH_NAME == 'master' || env.BRANCH_NAME == 'release') { + sendFailureMessage() + } + } + } + } +} + +Void deployHelmChart(String helmChartName, String helmChartVersion) { + withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD')]){ + if (env.BRANCH_NAME == 'release') { + result = sh script: '''curl -u $USERNAME:$PASSWORD https://nexus.ozg-sh.de/service/rest/v1/components?repository=ozg-base-apps -F file=@'''+helmChartName+'''-'''+helmChartVersion+'''.tgz''', returnStdout: true + } + else { + result = sh script: '''curl -u $USERNAME:$PASSWORD https://nexus.ozg-sh.de/service/rest/v1/components?repository=ozg-base-apps-snapshot -F file=@'''+helmChartName+'''-'''+helmChartVersion+'''.tgz''', returnStdout: true + } + + if (result != '') { + error(result) + } + } +} + +String generateHelmChartVersion() { + def chartVersion = getPomVersion('pom.xml') + + if (env.BRANCH_NAME == 'master') { + chartVersion += "-${env.GIT_COMMIT.take(7)}" + } + else if (env.BRANCH_NAME != 'release') { + chartVersion += "-${env.BRANCH_NAME}" + } + + return chartVersion.replaceAll("_", "-") +} + +Void sendFailureMessage() { + def room = '' + def data = """{"msgtype":"m.text", \ + "body":"Intelliform-Adapter: Build Failed. Stage: ${FAILED_STAGE} Build-ID: ${env.BUILD_NUMBER} Link: ${BLUE_OCEAN_URL}", \ + "format": "org.matrix.custom.html", \ + "formatted_body":"Intelliform-Adapter: Build Failed. Stage: ${FAILED_STAGE} Build-ID: <a href='${BLUE_OCEAN_URL}'>${env.BUILD_NUMBER}</a>"}""" + + if (env.BRANCH_NAME == 'master') { + room = "!iQPAvQIiRwRpNOszjw:matrix.ozg-sh.de" + } + else if (env.BRANCH_NAME == 'release') { + room = "!oWZpUGTFsxkJIYNfYg:matrix.ozg-sh.de" + } + + sh "curl -XPOST -H 'authorization: Bearer ${getElementAccessToken()}' -d '${data}' https://matrix.ozg-sh.de/_matrix/client/v3/rooms/$room/send/m.room.message" +} + +String getElementAccessToken() { + withCredentials([string(credentialsId: 'element-login-json', variable: 'LOGIN_JSON')]) { + return readJSON ( text: sh (script: '''curl -XPOST -d \"$LOGIN_JSON\" https://matrix.ozg-sh.de/_matrix/client/v3/login''', returnStdout: true)).access_token + } +} + +Void setNewDevAdapterVersion() { + setNewAfmAdapterVersion('dev') + setNewFsAdapterVersion('dev') + setNewFormcycleAdapterVersion('dev') + setNewXtaAdapterVersion('dev') +} + +Void setNewTestAdapterVersion() { + setNewAfmAdapterVersion('test') + setNewFsAdapterVersion('test') + setNewFormcycleAdapterVersion('test') +} + +Void setNewAfmAdapterVersion(String environment) { + dir("gitops") { + def envFile = "${environment}/application/values/afm-adapter-values.yaml" + def envVersions = readYaml file: envFile + + envVersions.afm_adapter.image.tag = IMAGE_TAG + envVersions.afm_adapter.helm.version = HELM_CHART_VERSION + + writeYaml file: envFile, data: envVersions, overwrite: true + } +} + +Void setNewFsAdapterVersion(String environment) { + dir("gitops") { + def envFile = "${environment}/application/values/fs-adapter-values.yaml" + def envVersions = readYaml file: envFile + + envVersions.fs_adapter.image.tag = IMAGE_TAG + envVersions.fs_adapter.helm.version = HELM_CHART_VERSION + + writeYaml file: envFile, data: envVersions, overwrite: true + } +} + +Void setNewFormcycleAdapterVersion(String environment) { + dir("gitops") { + def envFile = "${environment}/application/values/formcycle-adapter-values.yaml" + def envVersions = readYaml file: envFile + + envVersions.formcycle_adapter.image.tag = IMAGE_TAG + envVersions.formcycle_adapter.helm.version = HELM_CHART_VERSION + + writeYaml file: envFile, data: envVersions, overwrite: true + } +} + +Void setNewXtaAdapterVersion(String environment) { + dir("gitops") { + def envFile = "${environment}/application/values/xta-adapter-values.yaml" + def envVersions = readYaml file: envFile + + envVersions.xta_adapter.image.tag = IMAGE_TAG + envVersions.xta_adapter.helm.version = HELM_CHART_VERSION + + writeYaml file: envFile, data: envVersions, overwrite: true + } +} + +Void pushNewDevVersion() { + pushNewGitopsVersion('dev') +} + +Void pushNewTestVersion() { + pushNewGitopsVersion('test') +} + +Void pushNewGitopsVersion(String environment) { + dir('gitops') { + if (!hasAdapterValuesFileChanged(environment)) { + return + } + + withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) { + sh "git add ${environment}/application/values/*-adapter-values.yaml" + + sh "git commit -m 'jenkins rollout ${environment} afm-adapter fs-adapter version ${IMAGE_TAG}'" + sh 'git push https://${USER}:${TOKEN}@git.ozg-sh.de/mgm/gitops.git' + } + } +} + +Boolean hasAdapterValuesFileChanged(String environment) { + return sh (script: "git status | grep '${environment}/application/values/.*-adapter-values.yaml'", returnStatus: true) == env.SH_SUCCESS_STATUS_CODE as Integer +} + +Void configureGit() { + final email = "jenkins@ozg-sh.de" + final name = "jenkins" + + dir("gitops") { + sh "git config user.email '${email}'" + sh "git config user.name '${name}'" + } +} + +Void cloneGitopsRepo() { + withCredentials([usernamePassword(credentialsId: 'jenkins-gitea-access-token', passwordVariable: 'TOKEN', usernameVariable: 'USER')]) { + sh 'git clone https://${USER}:${TOKEN}@git.ozg-sh.de/mgm/gitops.git' + } + + configureGit() +} + +Void tagAndPushDockerImage(String imageName, String newTag){ + withCredentials([usernamePassword(credentialsId: 'jenkins-nexus-login', usernameVariable: 'USER', passwordVariable: 'PASSWORD')]) { + sh 'docker login docker.ozg-sh.de -u ${USER} -p ${PASSWORD}' + + sh "docker tag docker.ozg-sh.de/${imageName}:build-latest docker.ozg-sh.de/${imageName}:${newTag}" + sh "docker push docker.ozg-sh.de/${imageName}:${newTag}" + } +} + +String getPomVersion(String pomFile){ + def pom = readMavenPom file: pomFile + + return pom.version +} + +String generateImageTag() { + def imageTag = "${env.BRANCH_NAME}-${getPomVersion('pom.xml')}" + + if (env.BRANCH_NAME == 'master') { + imageTag += "-${env.GIT_COMMIT.take(7)}" + } + + return imageTag +} + +String getParentPomVersion(String filePath) { + def pom = readMavenPom file: filePath + return pom.parent.version +} + +Boolean isReleaseVersion(List versions) { + return matchRegexVersion(versions, RELEASE_REGEX) +} + +Boolean isSnapshotVersion(List versions) { + return matchRegexVersion(versions, SNAPSHOT_REGEX) +} + +Boolean matchRegexVersion(List versions, String regex) { + for (version in versions) { + if ( !(version ==~ regex) ) { + return false + } + } + + return true +} -- GitLab