Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .github/scripts/generate-coverage-badge.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash

set -e

REPORT_FILE="build/reports/jacoco/test/jacocoTestReport.xml"
BADGE_FILE="badges/coverage.svg"

mkdir -p badges

if [ ! -f "$REPORT_FILE" ]; then
echo "❌ Report not found: $REPORT_FILE"
exit 1
fi

# awk로 missed, covered 값 추출
read missed covered < <(awk -F'"' '/<counter type="LINE"/ {print $4, $6}' "$REPORT_FILE")

total=$((missed + covered))
percent=$(awk "BEGIN { printf \"%.2f\", ($covered / $total) * 100 }")

# 색상 결정
if (( $(echo "$percent >= 90" | bc -l) )); then
color="4c1" # brightgreen
elif (( $(echo "$percent >= 75" | bc -l) )); then
color="dfb317" # yellow
else
color="e05d44" # red
fi

# SVG badge 생성
cat > "$BADGE_FILE" <<EOF
<svg xmlns="http://www.w3.org/2000/svg" width="130" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#eee" stop-opacity=".7"/>
<stop offset="1" stop-opacity=".7"/>
</linearGradient>
<mask id="a">
<rect width="130" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#a)">
<rect width="75" height="20" fill="#555"/>
<rect x="75" width="55" height="20" fill="#$color"/>
<rect width="130" height="20" fill="url(#b)"/>
</g>
<g fill="#fff" text-anchor="middle"
font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="37.5" y="15" fill="#010101" fill-opacity=".3">coverage</text>
<text x="37.5" y="14">coverage</text>
<text x="101.5" y="15" fill="#010101" fill-opacity=".3">${percent}%</text>
<text x="101.5" y="14">${percent}%</text>
</g>
</svg>
EOF

echo "✅ Coverage badge generated: ${percent}% -> $BADGE_FILE"
87 changes: 87 additions & 0 deletions .github/workflows/pr-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
name: Spring CI for Pull Request

on:
pull_request:
branches: [ main, dev ]
types: [opened, synchronize, reopened]

permissions:
contents: write
pull-requests: write

jobs:
build-and-test:
name: Build, Test, and Coverage
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'

- name: Grant execute permission for gradlew
run: chmod +x ./gradlew

- name: Run Tests and Generate Coverage
run: ./gradlew clean test jacocoTestReport --no-daemon

- name: Upload Test Report
uses: actions/upload-artifact@v4
with:
name: test-report
path: build/reports/tests/test/

- name: Upload Coverage Report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: build/reports/jacoco/test/html/

- name: Extract JaCoCo Coverage Percentage
id: coverage
run: |
xml_file="build/reports/jacoco/test/jacocoTestReport.xml"

missed=$(awk -F'"' '/<counter type="LINE"/ {print $4}' "$xml_file")
covered=$(awk -F'"' '/<counter type="LINE"/ {print $6}' "$xml_file")

total=$((missed + covered))
percent=$(awk "BEGIN { printf \"%.2f\", ($covered / $total) * 100 }")

echo "COVERAGE=$percent" >> "$GITHUB_OUTPUT"

- name: Comment PR with Test and Coverage Result
if: always()
uses: marocchino/sticky-pull-request-comment@v2
with:
header: test-results
message: |
### ✅ 테스트 결과 for PR
**Build:** ${{ job.status }}

🧪 테스트 실행 with Gradle
📈 **Coverage:** `${{ steps.jacoco.outputs.COVERAGE }}%`

📁 [Test Report](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})
📁 [Coverage Report (HTML)](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})

- name: Fail PR if tests fail
if: failure()
run: |
echo "❌ Tests failed. Please fix them before merging."
exit 1
- name: Generate Coverage Badge
run: |
chmod +x .github/scripts/generate-coverage-badge.sh
.github/scripts/generate-coverage-badge.sh

- name: Commit & Push Coverage Badge
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: "chore: update coverage badge"
file_pattern: badges/coverage.svg
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🎮 마비노기 경매장 거래 내역 조회 및 통계 서비스

[![Coverage](https://img.shields.io/codecov/c/github/devnogi/open-api-batch-server/main)](https://codecov.io/gh/devnogi/open-api-batch-server)
![Coverage](https://github.com/devnogi/open-api-batch-server/dev/badges/coverage.svg)
[![License](https://img.shields.io/github/license/devnogi/open-api-batch-server)](LICENSE)
[![Last Commit](https://img.shields.io/github/last-commit/devnogi/open-api-batch-server)](https://github.com/devnogi/open-api-batch-server)

Expand Down
21 changes: 21 additions & 0 deletions badges/coverage.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 34 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ plugins {
id("io.spring.dependency-management") version "1.1.4"
id("org.asciidoctor.jvm.convert") version "4.0.2"
id("com.diffplug.spotless") version "6.25.0"
id("jacoco")
}

group = property("projectGroup") as String
Expand All @@ -18,6 +19,7 @@ java {
}
}


val querydslDir = "$buildDir/generated/querydsl"

sourceSets["main"].java.srcDirs(querydslDir)
Expand Down Expand Up @@ -95,12 +97,44 @@ dependencies {
testImplementation("org.flywaydb.flyway-test-extensions:flyway-spring-test:${property("flywayTestExtensionVersion")}")
}

extensions.configure<JacocoPluginExtension>("jacoco") {
toolVersion = "0.8.10"
}

// QueryDSL Q 클래스 생성 위치
tasks.withType<JavaCompile> {
options.annotationProcessorGeneratedSourcesDirectory = file(querydslDir)
options.annotationProcessorPath = configurations.annotationProcessor.get()
}

tasks.test {
useJUnitPlatform()
finalizedBy("jacocoTestReport") // 테스트 끝나면 커버리지 리포트 생성
}

tasks.named<JacocoReport>("jacocoTestReport") {
dependsOn(tasks.test)

reports {
xml.required.set(true)
html.required.set(true)
}

classDirectories.setFrom(
fileTree("${buildDir}/classes/java/main") {
exclude(
"**/config/**",
"**/dto/**",
"**/entity/**",
"**/exception/**"
)
}
)

sourceDirectories.setFrom(files("src/main/java"))
executionData.setFrom(fileTree(buildDir).include("jacoco/test.exec"))
}

// Spotless
spotless {
java {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package until.the.eternity.auctionhistory.application.service;

import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
Expand All @@ -18,8 +19,6 @@
import until.the.eternity.common.request.PageRequestDto;
import until.the.eternity.common.response.PageResponseDto;

import java.util.List;

@Service
@RequiredArgsConstructor
@Slf4j
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package until.the.eternity.auctionhistory.application.service.fetcher;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
Expand All @@ -9,9 +11,6 @@
import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse;
import until.the.eternity.common.enums.ItemCategory;

import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package until.the.eternity.auctionhistory.application.service.persister;

import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
Expand All @@ -11,8 +12,6 @@
import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse;
import until.the.eternity.common.enums.ItemCategory;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@Component
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package until.the.eternity.auctionhistory.domain.entity;

import jakarta.persistence.*;
import lombok.*;
import until.the.eternity.itemoption.domain.entity.ItemOption;

import java.time.Instant;
import java.util.List;
import lombok.*;
import until.the.eternity.itemoption.domain.entity.ItemOption;

@Entity
@Table(name = "auction_history")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
package until.the.eternity.auctionhistory.domain.mapper;

import java.util.List;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import until.the.eternity.auctionhistory.domain.entity.AuctionHistory;
import until.the.eternity.auctionhistory.interfaces.rest.dto.response.AuctionHistoryDetailResponse;
import until.the.eternity.auctionhistory.interfaces.rest.dto.response.ItemOptionResponse;
import until.the.eternity.itemoption.domain.entity.ItemOption;

import java.util.List;

/**
* AuctionHistory Entity to internal.responseDto transfer mapper class 데이터 흐름은 external.responseDto
* -> entity -> internal.responseDto 단방향으로 흐름
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package until.the.eternity.auctionhistory.domain.mapper;

import java.time.Instant;
import org.mapstruct.Context;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
Expand All @@ -8,8 +9,6 @@
import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse;
import until.the.eternity.common.enums.ItemCategory;

import java.time.Instant;

@Mapper(componentModel = "spring", uses = OpenApiItemOptionMapper.class)
public interface OpenApiAuctionHistoryMapper {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package until.the.eternity.auctionhistory.domain.repository;

import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import until.the.eternity.auctionhistory.domain.entity.AuctionHistory;
import until.the.eternity.auctionhistory.interfaces.rest.dto.request.AuctionHistorySearchRequest;

import java.util.List;
import java.util.Optional;

/** 경매장 거래 내역 POJO Repository - Mock 또는 Stub 으로 대체해 단위 테스트 용이성 확보 */
public interface AuctionHistoryRepositoryPort {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package until.the.eternity.auctionhistory.domain.service;

import java.util.Collection;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import until.the.eternity.auctionhistory.domain.repository.AuctionHistoryRepositoryPort;
import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse;

import java.util.Collection;
import java.util.List;

@Component
@RequiredArgsConstructor
public class AuctionHistoryDuplicateChecker {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package until.the.eternity.auctionhistory.domain.service.fetcher;

import java.util.List;
import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse;
import until.the.eternity.common.enums.ItemCategory;

import java.util.List;

public interface AuctionHistoryFetcherPort {
List<OpenApiAuctionHistoryResponse> fetch(ItemCategory category);
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package until.the.eternity.auctionhistory.domain.service.persister;

import java.util.List;
import until.the.eternity.auctionhistory.interfaces.external.dto.OpenApiAuctionHistoryResponse;
import until.the.eternity.common.enums.ItemCategory;

import java.util.List;

public interface AuctionHistoryPersisterPort {

void saveIfNotExists(List<OpenApiAuctionHistoryResponse> dtoList, ItemCategory category);
Expand Down
Loading