diff --git a/Jenkins/Jenkinsfile-CD b/Jenkins/Jenkinsfile-CD new file mode 100644 index 0000000000..17d6130344 --- /dev/null +++ b/Jenkins/Jenkinsfile-CD @@ -0,0 +1,62 @@ +pipeline { + agent any + + parameters { + string(name: 'eureka-services', defaultValue: 'main') + string(name: 'admin-server', defaultValue: 'main') + string(name: 'zipkin', defaultValue: 'main') + string(name: 'api-gateway', defaultValue: 'main') + string(name: 'customers-services', defaultValue: 'main') + string(name: 'genai-services', defaultValue: 'main') + string(name: 'vets-services', defaultValue: 'main') + string(name: 'visits-services', defaultValue: 'main') + } + + environment { + REPO_URL = 'https://github.com/vominh-source/spring-petclinic-microservices.git' + IMAGE_NAME = '22127475/devops-project02' + } + + + + stages { + stage('Deploy services') { + steps { + script { + services = [ + [name: 'eureka-services', branch: params.eureka-services], + [name: 'admin-server', branch: params.admin-server], + [name: 'zipkin', branch: params.zipkin], + [name: 'api-gateway', branch: params.api-gateway] + [name: 'customers-services', branch: params.customers-services], + [name: 'visits-services', branch: params.visits-services], + [name: 'vets-services', branch: params.vets-services], + [name: 'genai-services', branch: params.genai-services] + ] + + tags = [] + for (service in services) { + tags.append(tag.branch == 'main' ? 'latest' : sh(script: "git ls-remote ${REPO_URL} refs/heads/${services.branch} | cut -f1", returnStdout: true).trim()) + + echo "tags: ${tags[-1]}" + } + } + } + } + + stage('Pull images') { + steps { + script { + for (tag in tags) + sh "docker image pull ${IMAGE_NAME}:${tag}" + echo "pulled image: ${IMAGE_NAME}:${tag}" + } + } + } + + + + } + + +} diff --git a/Jenkins/Jenkinsfile-CI b/Jenkins/Jenkinsfile-CI new file mode 100644 index 0000000000..c24a0fc8c0 --- /dev/null +++ b/Jenkins/Jenkinsfile-CI @@ -0,0 +1,94 @@ +// Jenkinsfile +pipeline { + agent any + // { + // label '!built-in' + // } + + + options { + timeout(time: 90, unit: 'MINUTES') + buildDiscarder(logRotator(numToKeepStr: '10')) + disableConcurrentBuilds() + } + + environment { + DOCKERHUB_CREDENTIALS_ID = 'dockerhub' + DOCKER_REGISTRY = '22127146' + } + + stages { + stage('Prepare Workspace') { + steps { + echo 'Cleaning workspace...' + cleanWs() + checkout scm + } + } + + stage('Initialize') { + steps { + script { + // Lấy commit ID + if (env.GIT_COMMIT) { + env.COMMIT_ID = env.GIT_COMMIT + } else { + //env.COMMIT_ID = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim() + env.COMMIT_ID = bat(script: 'git rev-parse --short HEAD', returnStdout: true).trim() + } + // In thông tin + env.BRANCH_NAME = env.BRANCH_NAME + echo "Building branch: ${env.BRANCH_NAME}" + echo "Commit ID: ${env.COMMIT_ID}" + echo "Docker Hub Credentials ID: ${env.DOCKERHUB_CREDENTIALS_ID}" + echo "Docker Registry (for image prefix): ${env.DOCKER_REGISTRY}" + } + } + } + + stage('Build and Push Images to Docker Hub') { + steps { + script{ + docker.withRegistry("https://index.docker.io/v1/", env.DOCKERHUB_CREDENTIALS_ID){ + try{ + + def commit_id = env.COMMIT_ID + + if (env.BRANCH_NAME == 'main') { + commit_id = 'latest' + } + + def mvnCommand = "./mvnw.cmd clean install -P buildDocker -DskipTests "+ + "-Ddocker.image.prefix=${env.DOCKER_REGISTRY} "+ + "-Ddocker.image.tag.commit=${commit_id} "+ + "-Dcontainer.build.extraarg=\"--push\"" + + echo "Executing Maven command on Windows to build images: ${mvnCommand}" + //sh mvnCommand // Thực thi lệnh build + bat mvnCommand + + echo "Maven build completed successfully." + } + catch (e) { + echo "Error building images via Maven: ${e.getMessage()}" + error(message: "Failed to build images via Maven") + } + } + } + } + } + } + + post { + always { + echo 'CI Pipeline finished.' + } + success { + // Cập nhật thông báo thành công + echo "Successfully built, tagged (${env.COMMIT_ID}), and pushed images for branch ${env.BRANCH_NAME}" + } + failure { + echo "Pipeline failed for commit ${env.COMMIT_ID} on branch ${env.BRANCH_NAME}" + } + } +} diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..6d4f44291a --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,144 @@ +pipeline { + agent any + + stages { + stage('Checkout') { + steps { + checkout scm + } + } + + stage('Determine Build') { + steps { + script { + // Lấy danh sách các file đã thay đổi + env.CHANGED_FILES = sh(returnStdout: true, script: 'git diff --name-only HEAD^ HEAD').trim() + // Xác định service nào cần build/test + def servicesToBuild = determineService(env.CHANGED_FILES.readLines()) + + // Kiểm tra xem có thay đổi nào nằm ngoài các thư mục service không + def changedOutsideServices = env.CHANGED_FILES.readLines().any { filePath -> + !servicesToBuild.any { service -> filePath.contains(service) } + } + + if (changedOutsideServices) { + env.SERVICES_TO_BUILD = "all" // Build tất cả nếu có thay đổi bên ngoài + } else { + env.SERVICES_TO_BUILD = servicesToBuild // Sử dụng kết quả từ hàm determineServices + } + + echo "Services to build: ${env.SERVICES_TO_BUILD}" // In ra để kiểm tra + } + } + } + + stage('Test') { + when { + expression { env.SERVICES_TO_BUILD != null } + } + steps { + script { + if (env.SERVICES_TO_BUILD instanceof String && env.SERVICES_TO_BUILD != 'all') { + // Test 1 service + echo "Testing service: ${env.SERVICES_TO_BUILD}" + sh "./mvnw -f ${env.SERVICES_TO_BUILD}/pom.xml test" + + // JUnit report + junit( + testResults: "${env.SERVICES_TO_BUILD}/target/surefire-reports/*.xml", + allowEmptyResults: true + ) + + } else if (env.SERVICES_TO_BUILD == 'all'){ + // Test all services + echo "Testing all services" + sh "./mvnw test" + + // JUnit report + junit( + testResults: "**/target/surefire-reports/*.xml", + allowEmptyResults: true + ) + + } + } + } + } + + stage('Code Coverage') { + when { + expression { env.SERVICES_TO_BUILD != null } + } + steps { + script { + if (env.SERVICES_TO_BUILD instanceof String && env.SERVICES_TO_BUILD != 'all') { + // Code coverage cho 1 service + echo "Generating code coverage for service: ${env.SERVICES_TO_BUILD}" + sh "./mvnw -f ${env.SERVICES_TO_BUILD}/pom.xml org.jacoco:jacoco-maven-plugin:report" + recordCoverage( + tools: [[parser: 'JACOCO', pattern: "${env.SERVICES_TO_BUILD}/target/site/jacoco/**/*.xml"]] + ) + } else if(env.SERVICES_TO_BUILD == 'all'){ + // Test all services + echo "Generating code coverage for all services" + sh "./mvnw org.jacoco:jacoco-maven-plugin:report" + recordCoverage( + tools: [[parser: 'JACOCO', pattern: "**/target/site/jacoco/**/*.xml"]] + ) + + } + } + } + } + + stage('Build') { + when { + expression { env.SERVICES_TO_BUILD != null } + } + steps { + script { + if (env.SERVICES_TO_BUILD instanceof String && env.SERVICES_TO_BUILD != 'all') { + // Build 1 service + echo "Building service: ${env.SERVICES_TO_BUILD}" + sh "./mvnw -f ${env.SERVICES_TO_BUILD}/pom.xml clean install -DskipTests" + archiveArtifacts artifacts: "${env.SERVICES_TO_BUILD}/target/*.jar" + + } else if (env.SERVICES_TO_BUILD == 'all'){ + // Build all services + echo "Building all services" + sh "./mvnw clean install -DskipTests" + archiveArtifacts artifacts: "**/target/*.jar" + + } + } + } + } + } + + post { + always { + echo "Finished pipeline" + } + } +} + +// Function to determine which services to build/test +def determineService(changedFiles) { + println "Changed Files: ${changedFiles}" + def services = [ + 'spring-petclinic-customers-service', + 'spring-petclinic-vets-service', + 'spring-petclinic-visits-service', + 'spring-petclinic-api-gateway', + 'spring-petclinic-admin-server' + ] + // Không cần danh sách servicesToBuild nữa, vì chỉ cần tìm một + + for (service in services) { + if (changedFiles.any { it.contains(service) }) { + return service // Trả về ngay khi tìm thấy service đầu tiên + } + } + + return null // Trả về null nếu không tìm thấy +} diff --git a/README.md b/README.md index 34fe9a69d9..88a5044dea 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Distributed version of the Spring PetClinic Sample Application built with Spring Cloud and Spring AI +# Update for webhook [![Build Status](https://github.com/spring-petclinic/spring-petclinic-microservices/actions/workflows/maven-build.yml/badge.svg)](https://github.com/spring-petclinic/spring-petclinic-microservices/actions/workflows/maven-build.yml) [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) diff --git a/pom.xml b/pom.xml index 27b99d2a4a..11ee731023 100644 --- a/pom.xml +++ b/pom.xml @@ -151,6 +151,25 @@ + + org.jacoco + jacoco-maven-plugin + 0.8.10 + + + + prepare-agent + + + + report + verify + + report + + + + @@ -186,7 +205,7 @@ ${container.platform} ${container.build.extraarg} -t - ${docker.image.prefix}/${project.artifactId} + ${docker.image.prefix}/${project.artifactId}:${docker.image.tag.commit} ${project.build.directory}