// // Created by Patrick Verboom on 04.11.2024. // Copyright © 2024 heyday Marketing GmbH. All rights reserved. // def defaultRocketChatChannel = "#builds" def rocketChatColor = "#e813c8" def rocketChatEmoji = ":skunk:" def numOfArtifactsToKeep = env.GIT_BRANCH == "main" ? "10" : "5" def result = [] pipeline { agent { label "macOS" } tools { maven 'Maven Latest' jdk 'OpenJDK-21.0.5' } environment { PATH = "$PATH:/Users/Shared/jenkins/flutter/bin" } options { // keeps only the atifacts of the last 15 builds buildDiscarder( logRotator( artifactDaysToKeepStr: '', artifactNumToKeepStr: numOfArtifactsToKeep, daysToKeepStr: '', numToKeepStr: numOfArtifactsToKeep ) ) } stages { stage ('Initialize') { steps { script { def msg = "Pipeline ${env.JOB_NAME} ${env.BUILD_NUMBER} has started. \n More info at: ${env.BUILD_URL} " try { echo msg rocketSend channel: defaultRocketChatChannel, message: "jenkins-${env.JOB_NAME}-${env.BUILD_NUMBER}", emoji: rocketChatEmoji, attachments: [[$class: 'MessageAttachment', color: rocketChatColor, text: msg, title: 'Build started']] } catch (Exception e) { echo "Exception occurred sending : " + e.toString() + "\nmessage: " + msg throw e } } sh ''' echo "PATH = ${PATH}" echo "M2_HOME = ${M2_HOME}" printenv ''' } } stage ('Build Frontend') { steps { echo "running Frontend build for branch ${env.BRANCH_NAME}" dir("hartmann-foto-documentation-frontend"){ //flutter build web --dart-define=FLUTTER_WEB_CANVASKIT_URL=OURBASEURL/canvaskit/ sh 'flutter pub get' //sh 'dart run build_runner build' sh 'flutter build web --no-tree-shake-icons' dir("build/web"){ sh "cp -R . ../../../hartmann-foto-documentation-web/src/main/webapp/." } } } post { always { script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} frontend build has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add( ["Stage: Build ${currentBuild.currentResult}", msg] ) } } } } stage ('Test Frontend') { steps { echo "running Frontend test for branch ${env.BRANCH_NAME}" dir("hartmann-foto-documentation-frontend"){ // Run tests with JSON output for Jenkins parsing sh ''' flutter test --coverage --reporter=json --file-reporter=json:test_results.json --reporter=expanded || true dart test_runner.dart test_results.json test_results.xml ''' } } post { success { archiveArtifacts artifacts: 'hartmann-foto-documentation-frontend/coverage/lcov.info', fingerprint: true } always { // Publish test results to Jenkins junit 'hartmann-foto-documentation-frontend/test_results.xml' // Archive test artifacts archiveArtifacts artifacts: 'hartmann-foto-documentation-frontend/test_results.json, hartmann-foto-documentation-frontend/test_results.xml', allowEmptyArchive: true script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} frontend test has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add( ["Stage: Build ${currentBuild.currentResult}", msg] ) } } } } stage ('Build') { steps { echo "running build for branch ${env.BRANCH_NAME}" //sh 'mvn dependency:purge-local-repository clean -U -f hartmann-foto-documentation/pom.xml ' sh 'mvn deploy -U -f pom.xml' } post { success { //junit '**/target/surefire-reports/*.xml' archiveArtifacts artifacts: '**/target/*.war, **/target/*.zip', fingerprint: true } always { script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} build has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add( ["Stage: Build ${currentBuild.currentResult}", msg] ) } } } } stage ('Tests') { steps { sh 'mvn deploy -P docker -f hartmann-foto-documentation-docker/pom.xml' } post { success { junit '**/target/surefire-reports/*.xml' } always { script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} tests has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add( ["Stage: Test ${currentBuild.currentResult}", msg]) } } } } stage ('Code Coverage') { steps { sh 'mvn jacoco:report-aggregate -P docker -f pom.xml' sh 'cp hartmann-foto-documentation-docker/target/site/jacoco-aggregate/jacoco.xml hartmann-foto-documentation-app/target/site/jacoco-aggregate/jacoco.xml' } post { always { script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} Code coverage has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add( ["Stage: Test ${currentBuild.currentResult}", msg]) } } } } stage ('SonarQube analysis') { steps { withSonarQubeEnv('heyday sonar') { script { def key = "${env.BRANCH_NAME.replaceAll("/", "_")}" def projectKey = "\"marketing.heyday.hartmann:hartmann-foto-documentation:${key}\"" echo "running sonar for branch ${projectKey}" sh "mvn org.sonarsource.scanner.maven:sonar-maven-plugin:5.3.0.6276:sonar -f pom.xml -Dsonar.projectKey=${projectKey}" } } } post { always { script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} sonar has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add(["Stage: Sonar ${currentBuild.currentResult}", msg]) } } } } stage ('Release') { when { branch 'main' } steps { sh "mvn -B -U -X -e -Dmaven.test.skip=true -Djava.awt.headless=true release:prepare release:perform -DbambooBuildNumber=${env.BUILD_NUMBER} -Dmaven.javadoc.skip=true -f pom.xml " } post { success { archiveArtifacts artifacts: '**/target/*.war, **/target/*.zip', fingerprint: true } always { script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} release has finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add(["Stage: Release ${currentBuild.currentResult}",msg]) } } } } } post { always { script { def msg = "Build ${env.JOB_NAME} ${env.BUILD_NUMBER} Pipeline finished. Result: ${currentBuild.currentResult}. Took ${currentBuild.duration}.\n More info at: ${env.BUILD_URL} " result.add(["Stage: Pipeline ${currentBuild.currentResult}", msg]) try { //echo msg def attachements = [] for (elem in result) { attachements+=([$class: 'MessageAttachment', color: rocketChatColor, text: elem.get(1), title: elem.get(0)]) } rocketSend channel: defaultRocketChatChannel, message: "jenkins-${env.JOB_NAME}-${env.BUILD_NUMBER}", emoji: rocketChatEmoji, attachments: attachements } catch (Exception e) { echo "Exception occurred sending : " + e.toString() + "\nmessage: " + msg throw e } } } unsuccessful { emailext body: "${currentBuild.currentResult}: Job ${env.JOB_NAME} build ${env.BUILD_NUMBER}\n More info at: ${env.BUILD_URL}", recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], subject: "Failed Jenkins Build ${currentBuild.currentResult}: Job ${env.JOB_NAME}" } fixed { emailext body: "${currentBuild.currentResult}: Job ${env.JOB_NAME} build ${env.BUILD_NUMBER}\n More info at: ${env.BUILD_URL}", recipientProviders: [[$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']], subject: "Success Jenkins Build ${currentBuild.currentResult}: Job ${env.JOB_NAME}" } } }