검증 체크리스트 최신 reviewer 검증 (role-reviewer-reverify-550-001)
This commit is contained in:
parent
fe3d18a13a
commit
1f92d68661
1 changed files with 361 additions and 0 deletions
361
verification/run_verification.sh
Normal file
361
verification/run_verification.sh
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# ============================================================
|
||||
# 검증 체크리스트 실행 스크립트
|
||||
# 범위: Documentation(D), Test(T), CI/CD(C), Operations(O)
|
||||
# ============================================================
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
RESULTS_FILE="$SCRIPT_DIR/VERIFICATION_RESULTS.json"
|
||||
|
||||
echo "========================================"
|
||||
echo " 검증 체크리스트 실행"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# 상태 카운터 (pending 용어 사용)
|
||||
PASS=0
|
||||
FAIL=0
|
||||
SKIP=0
|
||||
|
||||
# 검증 함수 정의
|
||||
check_pass() {
|
||||
local item_id="$1"
|
||||
local description="$2"
|
||||
echo "[PASS] $item_id - $description"
|
||||
PASS=$((PASS + 1))
|
||||
}
|
||||
|
||||
check_fail() {
|
||||
local item_id="$1"
|
||||
local description="$2"
|
||||
local reason="${3:-}"
|
||||
echo "[FAIL] $item_id - $description"
|
||||
if [[ -n "$reason" ]]; then
|
||||
echo " 이유: $reason"
|
||||
fi
|
||||
FAIL=$((FAIL + 1))
|
||||
}
|
||||
|
||||
check_skip() {
|
||||
local item_id="$1"
|
||||
local description="$2"
|
||||
local reason="${3:-}"
|
||||
echo "[SKIP] $item_id - $description"
|
||||
if [[ -n "$reason" ]]; then
|
||||
echo " 이유: $reason"
|
||||
fi
|
||||
SKIP=$((SKIP + 1))
|
||||
}
|
||||
|
||||
# ============================================================
|
||||
# D. Documentation 검증 (D-01 ~ D-05)
|
||||
# ============================================================
|
||||
echo "--- D. Documentation ---"
|
||||
|
||||
# D-01: CHECKLIST.md 존재 여부
|
||||
if [[ -f "$PROJECT_ROOT/verification/CHECKLIST.md" ]]; then
|
||||
check_pass "D-01" "CHECKLIST.md 파일 존재"
|
||||
else
|
||||
check_fail "D-01" "CHECKLIST.md 파일 존재"
|
||||
fi
|
||||
|
||||
# D-02: EVIDENCE_REPORT.md 존재 여부
|
||||
if [[ -f "$PROJECT_ROOT/verification/EVIDENCE_REPORT.md" ]]; then
|
||||
check_pass "D-02" "EVIDENCE_REPORT.md 파일 존재"
|
||||
else
|
||||
check_fail "D-02" "EVIDENCE_REPORT.md 파일 존재"
|
||||
fi
|
||||
|
||||
# D-03: README.md 존재 여부
|
||||
if [[ -f "$PROJECT_ROOT/README.md" ]]; then
|
||||
check_pass "D-03" "README.md 파일 존재"
|
||||
else
|
||||
check_fail "D-03" "README.md 파일 존재"
|
||||
fi
|
||||
|
||||
# D-04: API 문서 존재 여부
|
||||
if [[ -f "$PROJECT_ROOT/docs/api.md" ]] || [[ -f "$PROJECT_ROOT/docs/API.md" ]]; then
|
||||
check_pass "D-04" "API 문서 존재"
|
||||
else
|
||||
check_skip "D-04" "API 문서 존재" "docs/api.md 또는 docs/API.md 파일 없음"
|
||||
fi
|
||||
|
||||
# D-05: 아키텍처 문서 존재 여부
|
||||
if [[ -f "$PROJECT_ROOT/docs/architecture.md" ]] || [[ -f "$PROJECT_ROOT/docs/ARCHITECTURE.md" ]]; then
|
||||
check_pass "D-05" "아키텍처 문서 존재"
|
||||
else
|
||||
check_skip "D-05" "아키텍처 문서 존재" "docs/architecture.md 또는 docs/ARCHITECTURE.md 파일 없음"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================
|
||||
# T. Test 검증 (T-01 ~ T-05)
|
||||
# ============================================================
|
||||
echo "--- T. Test ---"
|
||||
|
||||
# T-01: 테스트 디렉토리 존재
|
||||
if [[ -d "$PROJECT_ROOT/src/test" ]]; then
|
||||
check_pass "T-01" "테스트 디렉토리 존재"
|
||||
else
|
||||
check_fail "T-01" "테스트 디렉토리 존재"
|
||||
fi
|
||||
|
||||
# T-02: 테스트 파일 존재
|
||||
TEST_FILES=$(find "$PROJECT_ROOT/src/test" -name "*Test.java" -o -name "*Tests.java" 2>/dev/null | wc -l)
|
||||
if [[ $TEST_FILES -gt 0 ]]; then
|
||||
check_pass "T-02" "테스트 파일 존재 ($TEST_FILES개)"
|
||||
else
|
||||
check_fail "T-02" "테스트 파일 존재"
|
||||
fi
|
||||
|
||||
# T-03: JaCoCo 테스트 커버리지 ≥70%
|
||||
if [[ -f "$PROJECT_ROOT/pom.xml" ]]; then
|
||||
if grep -q "jacoco-maven-plugin" "$PROJECT_ROOT/pom.xml"; then
|
||||
# JaCoCo 리포트 디렉토리 확인
|
||||
JACOCO_REPORT_DIR="$PROJECT_ROOT/target/site/jacoco"
|
||||
if [[ -f "$JACOCO_REPORT_DIR/index.html" ]]; then
|
||||
# JaCoCo HTML 리포트에서 커버리지 비율 추출
|
||||
COVERAGE_LINE=$(grep -oP 'Total.*?\K\d+(?=%)\' "$JACOCO_REPORT_DIR/index.html" 2>/dev/null | head -1 || echo "0")
|
||||
if [[ $COVERAGE_LINE -ge 70 ]]; then
|
||||
check_pass "T-03" "JaCoCo 테스트 커버리지 ≥70% (실제: ${COVERAGE_LINE}%)"
|
||||
else
|
||||
check_fail "T-03" "JaCoCo 테스트 커버리지 ≥70%" "실제 커버리지: ${COVERAGE_LINE}%"
|
||||
fi
|
||||
elif [[ -f "$PROJECT_ROOT/target/site/jacoco/jacoco.xml" ]]; then
|
||||
# XML 리포트에서 커버리지 비율 추출
|
||||
COVERAGE_LINE=$(grep -oP 'instruction.*?missed="\d+".*?covered="\d+"\K[^/]+' "$PROJECT_ROOT/target/site/jacoco/jacoco.xml" 2>/dev/null | head -1)
|
||||
if [[ -n "$COVERAGE_LINE" ]]; then
|
||||
COVERAGE_PCT=$((COVERAGE_LINE))
|
||||
if [[ $COVERAGE_PCT -ge 70 ]]; then
|
||||
check_pass "T-03" "JaCoCo 테스트 커버리지 ≥70% (실제: ${COVERAGE_PCT}%)"
|
||||
else
|
||||
check_fail "T-03" "JaCoCo 테스트 커버리지 ≥70%" "실제 커버리지: ${COVERAGE_PCT}%"
|
||||
fi
|
||||
else
|
||||
check_skip "T-03" "JaCoCo 테스트 커버리지 ≥70%" "JaCoCo 리포트 미생성 (mvn verify 실행 필요)"
|
||||
fi
|
||||
else
|
||||
check_skip "T-03" "JaCoCo 테스트 커버리지 ≥70%" "JaCoCo 리포트 미생성 (mvn verify 실행 필요)"
|
||||
fi
|
||||
else
|
||||
check_fail "T-03" "JaCoCo 테스트 커버리지 ≥70%" "pom.xml에 jacoco-maven-plugin 미설정"
|
||||
fi
|
||||
else
|
||||
check_skip "T-03" "JaCoCo 테스트 커버리지 ≥70%" "pom.xml 파일 없음"
|
||||
fi
|
||||
|
||||
# T-04: 단위 테스트 존재
|
||||
UNIT_TEST_COUNT=$(find "$PROJECT_ROOT/src/test" -name "*Test.java" 2>/dev/null | wc -l)
|
||||
if [[ $UNIT_TEST_COUNT -gt 0 ]]; then
|
||||
check_pass "T-04" "단위 테스트 존재 ($UNIT_TEST_COUNT개)"
|
||||
else
|
||||
check_fail "T-04" "단위 테스트 존재"
|
||||
fi
|
||||
|
||||
# T-05: 통합 테스트 존재
|
||||
INTEGRATION_TEST_COUNT=$(find "$PROJECT_ROOT/src/test" -name "*IntegrationTest.java" -o -name "*IT.java" 2>/dev/null | wc -l)
|
||||
if [[ $INTEGRATION_TEST_COUNT -gt 0 ]]; then
|
||||
check_pass "T-05" "통합 테스트 존재 ($INTEGRATION_TEST_COUNT개)"
|
||||
else
|
||||
check_skip "T-05" "통합 테스트 존재" "통합 테스트 파일 없음"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================
|
||||
# C. CI/CD 검증 (C-01 ~ C-05)
|
||||
# ============================================================
|
||||
echo "--- C. CI/CD ---"
|
||||
|
||||
# C-01: CI/CD 설정 파일 존재
|
||||
if [[ -f "$PROJECT_ROOT/.github/workflows/ci.yml" ]] || [[ -f "$PROJECT_ROOT/.github/workflows/build.yml" ]]; then
|
||||
check_pass "C-01" "CI/CD 설정 파일 존재"
|
||||
else
|
||||
check_skip "C-01" "CI/CD 설정 파일 존재" ".github/workflows/*.yml 파일 없음"
|
||||
fi
|
||||
|
||||
# C-02: 빌드 스크립트 존재
|
||||
if [[ -f "$PROJECT_ROOT/build.sh" ]] || [[ -f "$PROJECT_ROOT/Makefile" ]]; then
|
||||
check_pass "C-02" "빌드 스크립트 존재"
|
||||
else
|
||||
check_skip "C-02" "빌드 스크립트 존재" "build.sh 또는 Makefile 없음"
|
||||
fi
|
||||
|
||||
# C-03: 테스트 실행 CI 단계 존재
|
||||
if [[ -f "$PROJECT_ROOT/.github/workflows/ci.yml" ]]; then
|
||||
if grep -qE "(mvn test|mvn verify|gradle test|./mvnw test)" "$PROJECT_ROOT/.github/workflows/ci.yml"; then
|
||||
check_pass "C-03" "테스트 실행 CI 단계 존재"
|
||||
else
|
||||
check_fail "C-03" "테스트 실행 CI 단계 존재"
|
||||
fi
|
||||
else
|
||||
check_skip "C-03" "테스트 실행 CI 단계 존재" "CI 설정 파일 없음"
|
||||
fi
|
||||
|
||||
# C-04: 코드 품질 검사 CI 단계 존재
|
||||
if [[ -f "$PROJECT_ROOT/.github/workflows/ci.yml" ]]; then
|
||||
if grep -qE "(checkstyle|pmd|spotbugs|sonarqube|jacoco)" "$PROJECT_ROOT/.github/workflows/ci.yml"; then
|
||||
check_pass "C-04" "코드 품질 검사 CI 단계 존재"
|
||||
else
|
||||
check_skip "C-04" "코드 품질 검사 CI 단계 존재" "품질 검사 도구 미설정"
|
||||
fi
|
||||
else
|
||||
check_skip "C-04" "코드 품질 검사 CI 단계 존재" "CI 설정 파일 없음"
|
||||
fi
|
||||
|
||||
# C-05: 배포 자동화 단계 존재
|
||||
if [[ -f "$PROJECT_ROOT/.github/workflows/ci.yml" ]]; then
|
||||
if grep -qE "(deploy|release|publish)" "$PROJECT_ROOT/.github/workflows/ci.yml"; then
|
||||
check_pass "C-05" "배포 자동화 단계 존재"
|
||||
else
|
||||
check_skip "C-05" "배포 자동화 단계 존재" "배포 단계 미설정"
|
||||
fi
|
||||
else
|
||||
check_skip "C-05" "배포 자동화 단계 존재" "CI 설정 파일 없음"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================
|
||||
# O. Operations 검증 (O-01 ~ O-06)
|
||||
# ============================================================
|
||||
echo "--- O. Operations ---"
|
||||
|
||||
# O-01: 로깅 설정 존재
|
||||
if [[ -f "$PROJECT_ROOT/src/main/resources/logback.xml" ]] || [[ -f "$PROJECT_ROOT/src/main/resources/logback-test.xml" ]]; then
|
||||
check_pass "O-01" "로깅 설정 존재"
|
||||
else
|
||||
check_skip "O-01" "로깅 설정 존재" "logback.xml 파일 없음"
|
||||
fi
|
||||
|
||||
# O-02: 환경 설정 파일 존재
|
||||
if [[ -f "$PROJECT_ROOT/src/main/resources/application.properties" ]] || [[ -f "$PROJECT_ROOT/src/main/resources/application.yml" ]]; then
|
||||
check_pass "O-02" "환경 설정 파일 존재"
|
||||
else
|
||||
check_fail "O-02" "환경 설정 파일 존재"
|
||||
fi
|
||||
|
||||
# O-03: 헬스체크 엔드포인트 존재
|
||||
if [[ -d "$PROJECT_ROOT/src/main/java" ]]; then
|
||||
HEALTH_CHECK_FILES=$(find "$PROJECT_ROOT/src/main/java" -name "*Health*" -o -name "*Actuator*" 2>/dev/null | wc -l)
|
||||
if [[ $HEALTH_CHECK_FILES -gt 0 ]]; then
|
||||
check_pass "O-03" "헬스체크 엔드포인트 존재"
|
||||
else
|
||||
check_skip "O-03" "헬스체크 엔드포인트 존재" "헬스체크 관련 파일 없음"
|
||||
fi
|
||||
else
|
||||
check_skip "O-03" "헬스체크 엔드포인트 존재" "src/main/java 디렉토리 없음"
|
||||
fi
|
||||
|
||||
# O-04: 메트릭스 수집 설정 존재
|
||||
if [[ -f "$PROJECT_ROOT/pom.xml" ]]; then
|
||||
if grep -qE "(micrometer|prometheus|metrics)" "$PROJECT_ROOT/pom.xml"; then
|
||||
check_pass "O-04" "메트릭스 수집 설정 존재"
|
||||
else
|
||||
check_skip "O-04" "메트릭스 수집 설정 존재" "메트릭스 의존성 미설정"
|
||||
fi
|
||||
else
|
||||
check_skip "O-04" "메트릭스 수집 설정 존재" "pom.xml 파일 없음"
|
||||
fi
|
||||
|
||||
# O-05: 장애 복구 매커니즘 존재
|
||||
if [[ -d "$PROJECT_ROOT/src/main/java" ]]; then
|
||||
RESILIENCE_FILES=$(find "$PROJECT_ROOT/src/main/java" -name "*Retry*" -o -name "*Circuit*" -o -name "*Fallback*" 2>/dev/null | wc -l)
|
||||
if [[ $RESILIENCE_FILES -gt 0 ]]; then
|
||||
check_pass "O-05" "장애 복구 매커니즘 존재"
|
||||
else
|
||||
check_skip "O-05" "장애 복구 매커니즘 존재" "장애 복구 관련 파일 없음"
|
||||
fi
|
||||
else
|
||||
check_skip "O-05" "장애 복구 매커니즘 존재" "src/main/java 디렉토리 없음"
|
||||
fi
|
||||
|
||||
# O-06: 보안 설정 존재
|
||||
if [[ -d "$PROJECT_ROOT/src/main/java" ]]; then
|
||||
SECURITY_FILES=$(find "$PROJECT_ROOT/src/main/java" -name "*Security*" -o -name "*Auth*" 2>/dev/null | wc -l)
|
||||
if [[ $SECURITY_FILES -gt 0 ]]; then
|
||||
check_pass "O-06" "보안 설정 존재"
|
||||
else
|
||||
check_skip "O-06" "보안 설정 존재" "보안 관련 파일 없음"
|
||||
fi
|
||||
else
|
||||
check_skip "O-06" "보안 설정 존재" "src/main/java 디렉토리 없음"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
|
||||
# ============================================================
|
||||
# 결과 요약
|
||||
# ============================================================
|
||||
echo "========================================"
|
||||
echo " 검증 결과 요약"
|
||||
echo "========================================"
|
||||
echo " PASS: $PASS"
|
||||
echo " FAIL: $FAIL"
|
||||
echo " SKIP: $SKIP"
|
||||
echo "========================================"
|
||||
echo ""
|
||||
|
||||
# JSON 결과 파일 생성
|
||||
cat > "$RESULTS_FILE" << 'JSONEOF'
|
||||
{
|
||||
"timestamp": "TIMESTAMP_PLACEHOLDER",
|
||||
"summary": {
|
||||
"total": TOTAL_COUNT,
|
||||
"pass": PASS_COUNT,
|
||||
"fail": FAIL_COUNT,
|
||||
"skip": SKIP_COUNT
|
||||
},
|
||||
"checks": {
|
||||
"documentation": {
|
||||
"D-01": "pending",
|
||||
"D-02": "pending",
|
||||
"D-03": "pending",
|
||||
"D-04": "pending",
|
||||
"D-05": "pending"
|
||||
},
|
||||
"test": {
|
||||
"T-01": "pending",
|
||||
"T-02": "pending",
|
||||
"T-03": "pending",
|
||||
"T-04": "pending",
|
||||
"T-05": "pending"
|
||||
},
|
||||
"ci_cd": {
|
||||
"C-01": "pending",
|
||||
"C-02": "pending",
|
||||
"C-03": "pending",
|
||||
"C-04": "pending",
|
||||
"C-05": "pending"
|
||||
},
|
||||
"operations": {
|
||||
"O-01": "pending",
|
||||
"O-02": "pending",
|
||||
"O-03": "pending",
|
||||
"O-04": "pending",
|
||||
"O-05": "pending",
|
||||
"O-06": "pending"
|
||||
}
|
||||
}
|
||||
}
|
||||
JSONEOF
|
||||
|
||||
# 플레이스홀더 치환
|
||||
CURRENT_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||
sed -i "s/TIMESTAMP_PLACEHOLDER/$CURRENT_TIME/g" "$RESULTS_FILE"
|
||||
sed -i "s/TOTAL_COUNT/$((PASS + FAIL + SKIP))/g" "$RESULTS_FILE"
|
||||
sed -i "s/PASS_COUNT/$PASS/g" "$RESULTS_FILE"
|
||||
sed -i "s/FAIL_COUNT/$FAIL/g" "$RESULTS_FILE"
|
||||
sed -i "s/SKIP_COUNT/$SKIP/g" "$RESULTS_FILE"
|
||||
|
||||
echo "결과가 $RESULTS_FILE 에 저장되었습니다."
|
||||
|
||||
# 실패 항목이 있으면 exit code 1 반환
|
||||
if [[ $FAIL -gt 0 ]]; then
|
||||
exit 1
|
||||
fi
|
||||
exit 0
|
||||
Loading…
Add table
Add a link
Reference in a new issue