From 18febbf40802d52680861482640b99caf9d5dc08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Wed, 18 Jun 2025 21:34:35 +0900 Subject: [PATCH 01/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20=EC=BB=A4=EB=B2=84=EB=A6=AC?= =?UTF-8?q?=EC=A7=80=20=ED=99=95=EC=9D=B8=EC=9A=A9=20Jacoco=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20|=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 11 ++++++++++- build.gradle | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 722b3ff6..5a66379e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -57,7 +57,7 @@ set -o allexport source "$ENV_FILE" set +o allexport -./gradlew test --no-daemon +./gradlew test jacocoTestReport --no-daemon ''' } } @@ -66,6 +66,15 @@ set +o allexport publishChecks name: GH_CHECK_NAME, conclusion: 'SUCCESS', detailsURL: env.BUILD_URL + + jacoco execPattern: '**/build/jacoco/test.exec', + classPattern: '**/build/classes/java/main', + sourcePattern: '**/src/main/java', + inclusionPattern: '**/*.class', + exclusionPattern: '**/*Test*', + changeBuildStatus: true + + archiveArtifacts artifacts: '**/build/reports/jacoco/test/html/**', fingerprint: true } failure { publishChecks name: GH_CHECK_NAME, diff --git a/build.gradle b/build.gradle index c7bc8034..f5369cfc 100644 --- a/build.gradle +++ b/build.gradle @@ -2,6 +2,7 @@ plugins { id 'java' id 'org.springframework.boot' version '3.4.4' id 'io.spring.dependency-management' version '1.1.7' + id 'jacoco' } group = 'com.factoreal' @@ -97,7 +98,21 @@ dependencies { implementation 'io.micrometer:micrometer-registry-prometheus' } +// ✅ JaCoCo 테스트 커버리지 리포트 생성 설정 +jacoco { + toolVersion = "0.8.11" +} +jacocoTestReport { + dependsOn test // 테스트가 실행된 후 리포트 생성 + reports { + xml.required = true + html.required = true + html.outputLocation = layout.buildDirectory.dir('jacocoHtml') // HTML 리포트 디렉토리 + } +} +// ✅ 테스트 태스크에 커버리지 연결 tasks.named('test') { useJUnitPlatform() -} + finalizedBy tasks.jacocoTestReport // 테스트 후 커버리지 리포트 생성 +} \ No newline at end of file From 3395385a8de80b2698b876c6973bdd46e36d49c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Wed, 18 Jun 2025 21:58:51 +0900 Subject: [PATCH 02/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20=EC=BB=A4=EB=B2=84=EB=A6=AC?= =?UTF-8?q?=EC=A7=80=20=ED=99=95=EC=9D=B8=EC=9A=A9=20Jacoco=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20|=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 5a66379e..df4e5c4a 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -67,14 +67,14 @@ set +o allexport conclusion: 'SUCCESS', detailsURL: env.BUILD_URL - jacoco execPattern: '**/build/jacoco/test.exec', - classPattern: '**/build/classes/java/main', - sourcePattern: '**/src/main/java', + jacoco execPattern: 'build/jacoco/test.exec', + classPattern: 'build/classes/java/main', + sourcePattern: 'src/main/java', inclusionPattern: '**/*.class', exclusionPattern: '**/*Test*', changeBuildStatus: true - archiveArtifacts artifacts: '**/build/reports/jacoco/test/html/**', fingerprint: true + archiveArtifacts artifacts: 'build/reports/jacoco/test/html/**', fingerprint: true } failure { publishChecks name: GH_CHECK_NAME, From 48006b7803f8511224b6200c29d1dbeeacd40527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Wed, 18 Jun 2025 23:20:02 +0900 Subject: [PATCH 03/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20=EC=BB=A4=EB=B2=84=EB=A6=AC?= =?UTF-8?q?=EC=A7=80=20=ED=99=95=EC=9D=B8=EC=9A=A9=20Jacoco=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20|=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f5369cfc..2eb3e808 100644 --- a/build.gradle +++ b/build.gradle @@ -108,7 +108,7 @@ jacocoTestReport { reports { xml.required = true html.required = true - html.outputLocation = layout.buildDirectory.dir('jacocoHtml') // HTML 리포트 디렉토리 + csv.required = true } } // ✅ 테스트 태스크에 커버리지 연결 From e39331a26c2f2ad1f41dfdfd1ce44662a5b14283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Wed, 18 Jun 2025 23:49:10 +0900 Subject: [PATCH 04/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20service=20layer=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A7=8C=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95=20|?= =?UTF-8?q?=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/build.gradle b/build.gradle index 2eb3e808..9f70dc80 100644 --- a/build.gradle +++ b/build.gradle @@ -110,6 +110,20 @@ jacocoTestReport { html.required = true csv.required = true } + afterEvaluate { + classDirectories.setFrom( + files(classDirectories.files.collect { + fileTree(dir: it, include: [ + 'com/factoreal/backend/domain/**/application/**', + 'com/factoreal/backend/messaging/**' + ], + excludes: [ + 'com/factoreal/backend/messaging/common/**', + 'com/factoreal/backend/messaging/config/**', + ]) + }) + ) + } } // ✅ 테스트 태스크에 커버리지 연결 tasks.named('test') { From de628bd20c18679f460ddb9ad8c9356ffafe6571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Thu, 19 Jun 2025 10:57:03 +0900 Subject: [PATCH 05/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20service=20layer=20=EB=8B=A8?= =?UTF-8?q?=EC=9C=84=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A7=8C=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=ED=95=98=EB=8F=84=EB=A1=9D=20=EC=84=A4=EC=A0=95=20|?= =?UTF-8?q?=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 9f70dc80..28ae2506 100644 --- a/build.gradle +++ b/build.gradle @@ -120,6 +120,9 @@ jacocoTestReport { excludes: [ 'com/factoreal/backend/messaging/common/**', 'com/factoreal/backend/messaging/config/**', + '**/dao/**', + '**/dto/**', + '**/entity/**', ]) }) ) From bdcd9763844a0ca148887472d3ad193b3993535d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Thu, 19 Jun 2025 11:03:58 +0900 Subject: [PATCH 06/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20PR=20=EC=BD=94=EB=A9=98?= =?UTF-8?q?=ED=8A=B8=EC=97=90=20Jacoco=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EA=B2=B0=EA=B3=BC=20=ED=8F=AC=ED=95=A8=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=84=A4=EC=A0=95=20|=20=EA=B9=80=EC=9A=B0?= =?UTF-8?q?=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index df4e5c4a..ec03be9e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -190,6 +190,36 @@ argocd --server $ARGOCD_SERVER --insecure --grpc-web \ } } } + /* 4) PR 코맨트에 ─ 커버리지 테스트 요약 작성 */ + stage('Report Coverage to PR') { + when { + changeRequest() + } + steps { + script { + def coverageFile = readFile('build/reports/jacoco/test/jacocoTestReport.csv') + def lineCoverage = coverageFile.readLines().find { it.contains('LINE') } + def branchCoverage = coverageFile.readLines().find { it.contains('BRANCH') } + + def coverageSummary = """ + ### ✅ Test Coverage Report + + - **Line**: ${lineCoverage} + - **Branch**: ${branchCoverage} + + [View Full Report](${env.BUILD_URL}artifact/build/reports/jacoco/test/html/index.html) + """ + + // GitHub API로 PR 코멘트 작성 + sh """ + curl -s -H "Authorization: token ${GITHUB_TOKEN}" \\ + -X POST -d '{ "body": """${coverageSummary.replace("\"", "\\\"")}""" }' \\ + https://api.github.com/repos/${env.REPO_NAME}/issues/${env.CHANGE_ID}/comments + """ + } + } + } + /* 4) main 전용 ─ 이미지 빌드 & ECR Push (EC2) */ stage('Docker Build & Push (main only)') { From 9af7a249e08de2f8a13ef5b0d54eb5a6bb9b86ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Thu, 19 Jun 2025 11:12:29 +0900 Subject: [PATCH 07/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20gradle=20jacocoTestReport?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20=ED=9B=84=20=ED=8F=B4=EB=8D=94=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20|=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Jenkinsfile b/Jenkinsfile index ec03be9e..e3f25215 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -219,6 +219,11 @@ argocd --server $ARGOCD_SERVER --insecure --grpc-web \ } } } + stage('Check Jacoco CSV File') { + steps { + sh 'ls -l build/reports/jacoco/test/' + } + } /* 4) main 전용 ─ 이미지 빌드 & ECR Push (EC2) */ From 67c0ffebd25d73b4a464fe6064ca5aaff1fc536d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Thu, 19 Jun 2025 11:21:18 +0900 Subject: [PATCH 08/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20gradle=20jacocoTestReport?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20=ED=9B=84=20=ED=8F=B4=EB=8D=94=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20|=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index e3f25215..eba18ea4 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -190,6 +190,11 @@ argocd --server $ARGOCD_SERVER --insecure --grpc-web \ } } } + stage('Check Jacoco CSV File') { + steps { + sh 'ls -l build/reports/jacoco/test/' + } + } /* 4) PR 코맨트에 ─ 커버리지 테스트 요약 작성 */ stage('Report Coverage to PR') { when { @@ -219,11 +224,7 @@ argocd --server $ARGOCD_SERVER --insecure --grpc-web \ } } } - stage('Check Jacoco CSV File') { - steps { - sh 'ls -l build/reports/jacoco/test/' - } - } + /* 4) main 전용 ─ 이미지 빌드 & ECR Push (EC2) */ From fc97ec2c9e88c935a1ccea556389fc46fae15808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Thu, 19 Jun 2025 12:44:47 +0900 Subject: [PATCH 09/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20gradle=20jacocoTestReport?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20=ED=9B=84=20=ED=8F=B4=EB=8D=94=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20|=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Jenkinsfile b/Jenkinsfile index eba18ea4..dbd1e6d2 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -36,7 +36,30 @@ pipeline { } } - /* 1) 공통 테스트 */ + // ✅ PR 전용 테스트 단계 + stage('Test for PR') { + when { + changeRequest() + } + steps { + withCredentials([file(credentialsId: 'backend-env', variable: 'ENV_FILE')]) { + sh ''' +set -o allexport +source "$ENV_FILE" +set +o allexport + +./gradlew test jacocoTestReport --no-daemon +''' + } + } + post { + success { + archiveArtifacts artifacts: 'build/reports/jacoco/test/**', fingerprint: true + } + } + } + + // ✅ PR이 아닐 때만 실행되는 테스트 (develop/main 제외) stage('Test') { when { allOf { From c298e05b850873a38880625a040c1e9c86103dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B4=91=EB=B6=80=EC=9E=85=EB=8B=88=EB=8B=A4?= Date: Thu, 19 Jun 2025 13:15:11 +0900 Subject: [PATCH 10/10] =?UTF-8?q?hotfix=20|=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= =?UTF-8?q?=20|=20=EC=97=86=EC=9D=8C=20|=20gradle=20jacocoTestReport?= =?UTF-8?q?=EC=8B=A4=ED=96=89=20=ED=9B=84=20=ED=8F=B4=EB=8D=94=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20|=20=EA=B9=80=EC=9A=B0=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Jenkinsfile | 65 +++++++++++++++++++++++------------------------------ 1 file changed, 28 insertions(+), 37 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index dbd1e6d2..87e7858e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -98,6 +98,33 @@ set +o allexport changeBuildStatus: true archiveArtifacts artifacts: 'build/reports/jacoco/test/html/**', fingerprint: true + script { + // CSV 경로 + def csvPath = 'build/reports/jacoco/test/jacocoTestReport.csv' + + if (fileExists(csvPath)) { + def coverageFile = readFile(csvPath) + // LINE 포함된 줄을 찾고 퍼센트 숫자 추출 (예: LINE,COVERED,xxx,85.23) + def lineCoverageLine = coverageFile.readLines().find { it.startsWith("LINE,") } + def lineCoveragePercent = "알 수 없음" + + if (lineCoverageLine) { + def parts = lineCoverageLine.split(',') + // CSV 포맷에 따라 퍼센티지 위치 다를 수 있으니 확인 필요 + if(parts.size() >= 4) { + lineCoveragePercent = parts[3] + "%" + } + } + + // 슬랙으로 커버리지 결과 전송 + slackSend channel: env.SLACK_CHANNEL, + tokenCredentialId: env.SLACK_CRED_ID, + color: '#36a64f', + message: ":white_check_mark: *BE 테스트 성공* - Jacoco 라인 커버리지: ${lineCoveragePercent}" + } else { + echo "Jacoco CSV 리포트 파일이 존재하지 않습니다: ${csvPath}" + } + } } failure { publishChecks name: GH_CHECK_NAME, @@ -213,42 +240,6 @@ argocd --server $ARGOCD_SERVER --insecure --grpc-web \ } } } - stage('Check Jacoco CSV File') { - steps { - sh 'ls -l build/reports/jacoco/test/' - } - } - /* 4) PR 코맨트에 ─ 커버리지 테스트 요약 작성 */ - stage('Report Coverage to PR') { - when { - changeRequest() - } - steps { - script { - def coverageFile = readFile('build/reports/jacoco/test/jacocoTestReport.csv') - def lineCoverage = coverageFile.readLines().find { it.contains('LINE') } - def branchCoverage = coverageFile.readLines().find { it.contains('BRANCH') } - - def coverageSummary = """ - ### ✅ Test Coverage Report - - - **Line**: ${lineCoverage} - - **Branch**: ${branchCoverage} - - [View Full Report](${env.BUILD_URL}artifact/build/reports/jacoco/test/html/index.html) - """ - - // GitHub API로 PR 코멘트 작성 - sh """ - curl -s -H "Authorization: token ${GITHUB_TOKEN}" \\ - -X POST -d '{ "body": """${coverageSummary.replace("\"", "\\\"")}""" }' \\ - https://api.github.com/repos/${env.REPO_NAME}/issues/${env.CHANGE_ID}/comments - """ - } - } - } - - /* 4) main 전용 ─ 이미지 빌드 & ECR Push (EC2) */ stage('Docker Build & Push (main only)') { @@ -276,7 +267,7 @@ docker push ${ECR_REGISTRY}/${IMAGE_REPO_NAME}:${env.GIT_COMMIT} post { success { slackSend channel: env.SLACK_CHANNEL, - tokenCredentialId: env.SLACK_CRED_ID, + tokenCredentialId: env.SBELACK_CRED_ID, color: '#36a64f', message: """:white_check_mark: *BE main branch CI 성공* 파이프라인: <${env.BUILD_URL}|열기>