-
Notifications
You must be signed in to change notification settings - Fork 1
[FEAT] #178: CI 추가 #180
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[FEAT] #178: CI 추가 #180
Conversation
WalkthroughPR에 CI 워크플로우를 추가하고, Gradle 빌드 스크립트를 대폭 개편했습니다. 테스트 프로파일 도입과 Dotenv 로딩 조건 추가, 사용자 역할 enum의 문자열 매핑 전환, 환경별 설정 정리, 테스트 전용 설정 추가, 그리고 사용자 역할 컬럼을 정수→문자열로 변환하는 Flyway 마이그레이션을 포함합니다. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor Dev as Developer
participant GH as GitHub
participant CI as CI: build(job)
participant Gradle as Gradle
participant H2 as H2 (test DB)
participant UT as Test Publisher
Dev->>GH: Open/Update PR (develop/main)
GH-->>CI: Trigger workflow (PR events / dispatch)
CI->>CI: Concurrency group pr-ci-${ref}
CI->>Gradle: Checkout / Setup Java 17 / Setup Gradle
CI->>Gradle: Assemble (skip tests)
Gradle-->>CI: build.log (status)
CI->>H2: Start in-memory DB (PostgreSQL mode)
CI->>Gradle: Test with profile=test
Gradle-->>CI: test.log (status)
CI->>UT: Publish JUnit XML (if available)
UT-->>CI: Check run (conditional for forks)
CI->>GH: Post status message / Fail if any step failed
sequenceDiagram
autonumber
participant App as Spring Boot App
participant Profile as Profiles
participant Env as DotenvLoader(@Profile("!test"))
participant Flyway as Flyway
participant JPA as Hibernate/JPA
participant DB as DB (H2|PostgreSQL)
App->>Profile: Resolve active profile
alt profile == test
App -x Env: Bean not loaded
App-->>DB: H2 (in-memory)
App--x Flyway: disabled
App->>JPA: ddl-auto=create-drop
else profile == local|prod
App->>Env: Load .env
App-->>DB: PostgreSQL
App->>Flyway: migrate (baseline if needed)
App--x JPA: ddl-auto=none
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (4)
gdgoc/src/main/resources/application-local.yml (1)
46-46: 오타:org.hibername.type→org.hibernate.type현재 키 오타로 로깅 레벨 적용이 되지 않습니다. 로컬 디버깅 편의 목적이라도 정확한 키로 교체해야 합니다.
적용 diff:
- org.hibername.type: trace + org.hibernate.type: tracegdgoc/src/main/java/inha/gdgoc/config/DotenvLoader.java (1)
12-29:.env키 누락 시System.setPropertyNPE 가능 +printStackTrace()사용 지양
dotenv.get()가 null을 반환하면System.setProperty에서 NPE가 발생해 부트스트랩이 실패합니다. 또한 표준 출력 스택트레이스는 운영 로그 정책에 부적합합니다. null-safe 세팅과 로거 사용을 권장합니다.다음 변경 제안:
@PostConstruct public void loadEnv() { try { - Dotenv dotenv = Dotenv.load(); - System.setProperty("AWS_ACCESS_KEY_ID", dotenv.get("AWS_ACCESS_KEY_ID")); - System.setProperty("AWS_SECRET_ACCESS_KEY", dotenv.get("AWS_SECRET_ACCESS_KEY")); - System.setProperty("AWS_REGION", dotenv.get("AWS_REGION")); - System.setProperty("AWS_RESOURCE_BUCKET", dotenv.get("AWS_RESOURCE_BUCKET")); - System.setProperty("AWS_TEST_RESOURCE_BUCKET", dotenv.get("AWS_TEST_RESOURCE_BUCKET")); - System.setProperty("GOOGLE_CLIENT_ID", dotenv.get("GOOGLE_CLIENT_ID")); - System.setProperty("GOOGLE_CLIENT_SECRET", dotenv.get("GOOGLE_CLIENT_SECRET")); - System.setProperty("GOOGLE_REDIRECT_URI", dotenv.get("GOOGLE_REDIRECT_URI")); - System.setProperty("GMAIL", dotenv.get("GMAIL")); - System.setProperty("GMAIL_PASSWORD", dotenv.get("GMAIL_PASSWORD")); + Dotenv dotenv = Dotenv.load(); + String[] keys = { + "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "AWS_REGION", + "AWS_RESOURCE_BUCKET", "AWS_TEST_RESOURCE_BUCKET", + "GOOGLE_CLIENT_ID", "GOOGLE_CLIENT_SECRET", "GOOGLE_REDIRECT_URI", + "GMAIL", "GMAIL_PASSWORD" + }; + for (String key : keys) { + String value = dotenv.get(key); + if (value != null && !value.isBlank()) { + System.setProperty(key, value); + } + } } catch (Exception e) { - e.printStackTrace(); // 오류 로그 출력 - throw new RuntimeException("Error loading .env file: " + e.getMessage(), e); + log.error("Error loading .env file", e); + throw new RuntimeException("Error loading .env file: " + e.getMessage(), e); } }추가 import 및 로거 필드(파일 상단 보완):
import org.slf4j.Logger; import org.slf4j.LoggerFactory; private static final Logger log = LoggerFactory.getLogger(DotenvLoader.class);gdgoc/src/main/java/inha/gdgoc/domain/user/entity/User.java (2)
32-38: 중복된 Lombok@Builder선언으로 컴파일 에러 가능클래스 레벨(라인 32)과 생성자(라인 87)에 동시에
@Builder가 선언되어 있으면 Lombok이 동일한builder()메서드를 2번 생성해 충돌합니다. 하나만 유지하거나builderMethodName을 분리하세요.권장 수정(생성자 쪽만 유지):
-@Builder @Getter @Entity @Table(name = "users") @NoArgsConstructor(access = AccessLevel.PROTECTED) @AllArgsConstructor public class User extends BaseEntity {대안(양쪽 유지 필요 시 메서드명 분리):
-@Builder +@Builder(builderMethodName = "allArgsBuilder") ... -@Builder +@Builder(builderMethodName = "creationBuilder") public User( ... ) { ... }Also applies to: 87-103
105-117: null 항목이 리스트에 삽입되는 버그 — null 체크 순서 수정 필요현재
addStudy/addStudyAttendee에서 먼저 리스트에 추가한 뒤 null을 검사해, null이 컬렉션에 들어갈 수 있습니다. JPA 연관관계 편의 메서드는 null 방어를 먼저 수행해야 합니다.public void addStudy(Study study) { - this.studies.add(study); - if (study != null && study.getUser() != this) { - study.setUser(this); - } + if (study == null) return; + if (study.getUser() != this) { + study.setUser(this); + } + this.studies.add(study); } public void addStudyAttendee(StudyAttendee studyAttendee) { - this.studyAttendees.add(studyAttendee); - if (studyAttendee != null && studyAttendee.getUser() != this) { - studyAttendee.setUser(this); - } + if (studyAttendee == null) return; + if (studyAttendee.getUser() != this) { + studyAttendee.setUser(this); + } + this.studyAttendees.add(studyAttendee); }
🧹 Nitpick comments (9)
gdgoc/build.gradle (1)
22-24: 테스트 시 프로필 강제 활성화 설정 적절
tasks.test에서spring.profiles.active=test를 주입해 테스트 환경을 일관되게 보장합니다. 다만 테스트 클래스에도@ActiveProfiles("test")가 있어 중복입니다. 한 곳(gradle 또는 테스트 어노테이션)만 유지해도 충분합니다.가능한 선택지:
- CI/로컬 모두 동일하게 강제하려면 gradle 설정만 두고 테스트 어노테이션 제거
- 반대로 gradle 설정 제거, 테스트 어노테이션 유지
gdgoc/src/main/resources/application-local.yml (1)
18-18: 로컬에서ddl-auto: none전환은 Flyway 중심 운영에 부합Hibernate의 자동 DDL 생성을 끄고 마이그레이션에 일원화한 결정은 좋습니다. 로컬 DB가 기존 스키마를 가진 경우
baseline-on-migrate명시를 고려해 주세요.gdgoc/src/test/java/inha/gdgoc/GdgocApplicationTests.java (1)
5-8: 테스트 프로필 중복 @activeprofiles 어노테이션 제거 및 Flyway 비활성화 검토
build.gradle의
tasks.test에 이미systemProperty "spring.profiles.active", "test"설정이 있어 Gradle로 테스트 실행 시 자동으로
test프로필이 활성화됩니다.
→GdgocApplicationTests.java에서@ActiveProfiles("test")어노테이션은 중복이므로 제거를 권장합니다.
application-test.yml확인 결과 H2 메모리 DB와spring: jpa: hibernate: ddl-auto: create-drop설정은 잘 되어 있는데, Flyway에 대한 비활성화(
spring.flyway.enabled) 설정이 없어 기본 마이그레이션이 실행됩니다.
→ Hibernate DDL만 사용하려면 테스트 프로필에 Flyway 비활성화 설정을 추가하는 것을 고려하세요.// GdgocApplicationTests.java -import org.springframework.test.context.ActiveProfiles; - -@ActiveProfiles("test") @SpringBootTest class GdgocApplicationTests { // ... }# application-test.yml spring: datasource: driver-class-name: org.h2.Driver url: jdbc:h2:mem:gdgoc-test;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE username: sa password: jpa: database: h2 hibernate: ddl-auto: create-drop + flyway: + enabled: false # ...gdgoc/src/main/java/inha/gdgoc/domain/user/enums/UserRole.java (1)
7-9: UserRole enum 중복 필드role제거 리팩토링 제안
UserRole.getRole()호출 및.role직접 참조를 전수 조사한 결과, 빌드 디렉터리를 제외한 전체 코드베이스에서 해당 메서드 호출 또는 필드 접근이 전혀 발견되지 않았습니다. 즉, 아래와 같이role필드를 제거하고getRole()만 남기는 리팩터를 적용해도 기존 코드 호환성에 문제가 없습니다.
검증 스크립트
rg -n --hidden -S "(UserRole\.getRole\(|\.role\b)" -g '!**/build/**'– 결과:
gdgoc/src/main/java/inha/gdgoc/domain/user/enums/UserRole.java:14: this.role = role;내부 생성자 할당문 외에는 참조되지 않음
대상 파일
gdgoc/src/main/java/inha/gdgoc/domain/user/enums/UserRole.java제안 리팩터
-@Getter -public enum UserRole { - GUEST("GUEST"), - MEMBER("MEMBER"), - ADMIN("ADMIN"); - - private final String role; - - UserRole(String role){ - this.role = role; - } -} +public enum UserRole { + GUEST, MEMBER, ADMIN; + + // 기존 getRole() 사용처 호환 + public String getRole() { + return name(); + } +}위 리팩터를 적용하시면 중복된 필드를 제거하여 코드가 더욱 단순해지고, 유지보수가 용이해집니다.
gdgoc/src/main/java/inha/gdgoc/domain/user/entity/User.java (1)
63-65:@Enumerated(EnumType.STRING)적용 적절 — DB 마이그레이션/제약과의 정합성 체크문자열 매핑 전환과 Flyway 스크립트가 일치합니다. 몇 가지 확인/보완 권장사항입니다:
- DB 측
NOT NULL보장이 필요한 경우, 마이그레이션에서ALTER COLUMN user_role SET NOT NULL을 함께 적용해 엔티티의nullable = false와 일관성 유지 권장.- 애플리케이션 단에서도 방어적으로 기본값을 설정하면 NPE를 줄일 수 있습니다(예: null이면
GUEST).- this.userRole = userRole; + this.userRole = (userRole != null) ? userRole : UserRole.GUEST;검증 스크립트(마이그레이션 반영 전후 데이터 상태 확인용 SQL 쿼리 제안):
select count(*) from public.users where user_role is null or user_role not in ('GUEST','MEMBER','ADMIN');gdgoc/src/main/db/migration/V20250823__user_role_ordinal_to_string.sql (1)
20-23: 타입 변경/캐스팅 접근은 적절 — Postgres 전용 문법 사용 주의
USING user_role::text로의 캐스팅은 안전하고, 이후 값 매핑과도 일관됩니다. 다만 본 스크립트는DO $$ ... $$등 Postgres 전용 문법을 사용하므로, H2 테스트 환경에서 Flyway가 실행되지 않도록 프로필/설정으로 명시적 차단이 필요합니다(아래 CI 및application-test.yml코멘트 참고)..github/workflows/ci.yml (2)
27-33: env.ACT 체크 표현식 안정화
if: ${{ !env.ACT }}는 빈 문자열 평가 등으로 혼동될 수 있습니다. 명시적으로 비교하는 편이 안전합니다.- - uses: gradle/actions/setup-gradle@v3 - if: ${{ !env.ACT }} + - uses: gradle/actions/setup-gradle@v3 + if: ${{ env.ACT != 'true' }}
59-59: 로그/리포트 아티팩트 업로드 추가 제안실패 원인 파악과 회귀 분석을 돕기 위해 빌드/테스트 로그와 테스트 리포트를 업로드하세요.
- name: Gradle test (H2 in-memory) id: test working-directory: gdgoc env: ... run: ./gradlew test --no-daemon --stacktrace --info --no-watch-fs | tee ../test.log + + - name: Upload build logs + if: always() + uses: actions/upload-artifact@v4 + with: + name: ci-logs + path: | + build.log + test.log + gdgoc/build/reports/tests/test/**gdgoc/src/test/resources/application-test.yml (1)
19-31: JPA Dialect/DDL 설정의 중복 정의 최소화현재
application-test.yml과 CI 환경변수 모두에서 H2 설정을 지정하고 있습니다. 한쪽만 유지하면 설정 표류를 줄일 수 있습니다. 보통은 yml에 고정값(database-platform,ddl-auto)을 두고 CI env는 제거하는 방식을 권장합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (10)
.github/workflows/ci.yml(1 hunks)gdgoc/build.gradle(1 hunks)gdgoc/src/main/db/migration/V20250823__user_role_ordinal_to_string.sql(1 hunks)gdgoc/src/main/java/inha/gdgoc/config/DotenvLoader.java(1 hunks)gdgoc/src/main/java/inha/gdgoc/domain/user/entity/User.java(2 hunks)gdgoc/src/main/java/inha/gdgoc/domain/user/enums/UserRole.java(1 hunks)gdgoc/src/main/resources/application-local.yml(1 hunks)gdgoc/src/main/resources/application-prod.yml(2 hunks)gdgoc/src/test/java/inha/gdgoc/GdgocApplicationTests.java(1 hunks)gdgoc/src/test/resources/application-test.yml(1 hunks)
🔇 Additional comments (1)
gdgoc/src/main/java/inha/gdgoc/config/DotenvLoader.java (1)
8-8:@Profile("!test")로 테스트 격리 OK테스트 환경에서 dotenv 로딩을 배제해 테스트 독립성을 확보한 점 좋습니다.
|
CI status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
♻️ Duplicate comments (3)
gdgoc/src/main/resources/application-prod.yml (1)
24-24: 운영에서 SQL 로그 비활성화 전환, 잘 하셨습니다.
spring.jpa.show-sql: false로 설정되어 있어 운영 노이즈·민감 정보 노출 위험이 크게 줄었습니다.gdgoc/src/test/resources/application-test.yml (1)
32-34: 테스트 프로필에서 Flyway 비활성화, 적절합니다.H2(PostgreSQL 모드)에서 Postgres 전용 스크립트 충돌을 예방합니다.
.github/workflows/ci.yml (1)
45-58: H2 테스트에서 Flyway 비활성화 환경변수 추가, 충돌 예방에 유효합니다.
🧹 Nitpick comments (8)
gdgoc/src/main/resources/application-prod.yml (2)
26-31: baseline-on-migrate 운영 사용은 “최초 1회”만 — 이후 제거 또는 baseline-version 명시 권장이미 운영 DB 스키마가 존재한다면 최초 1회
baseline-on-migrate: true가 도움 되지만, 상시 켜두면 의도치 않게 베이스라인이 생겨 새 마이그레이션 검증이 느슨해질 수 있습니다. 초기 정착 후 제거하거나baseline-version을 명시해 주세요.제안:
spring: flyway: - baseline-on-migrate: true # 변경 확인 후 제거 예정 + baseline-on-migrate: false + baseline-version: 0
46-47: 운영 로그 레벨: SQL debug는 성능/노출 리스크 — 필요 시에만 일시적으로 사용 권장
org.hibernate.SQL: debug는 바인딩 값은 숨기지만 대량 로그로 성능·비용 이슈가 있습니다. 운영에선info또는warn권장입니다.logging: level: - org.hibernate.SQL: debug + org.hibernate.SQL: info org.hibernate.type: offgdgoc/src/test/resources/application-test.yml (2)
46-48: allow-bean-definition-overriding 사용은 최소화 권장테스트에서 중복 빈을 허용하면 구성 오류를 가릴 수 있습니다. 꼭 필요한 케이스에서만 scope 한정(@TestConfiguration, slice 테스트 등)으로 사용하거나 제거를 고려해 주세요.
59-63: 정적 테스트 시크릿 키 검출 – Gitleaks 오탐 대응 권장검증 결과:
src/test/resources/application-test.yml에만 하드코딩된 Base64 키(jwt.secretKey)가 존재하며, 이는 테스트 프로필 전용입니다.src/main/resources/application-*.yml(application-prod.yml,application-local.yml) 에서는${SECRET_KEY}환경변수 참조로 설정되어 있어 프로덕션 노출 이슈는 없습니다.따라서 프로덕션 환경에는 영향이 없으나, 스캐너 오탐(“Generic API Key”)을 차단하기 위해 아래 중 하나를 권장드립니다:
.gitleaks.toml에 테스트 전용 시크릿 키 경로(src/test/resources/application-test.yml:jwt.secretKey)를 허용 목록에 추가- 또는 테스트 환경에서도 환경변수 기반 주입 방식으로 전환
gdgoc/build.gradle (1)
43-48: QueryDSL APT 설정 적절 — IDE/CI 모두 동일 경로 생성 확인
annotationProcessor구성이 맞고, generated sources 경로를 고정해 일관성을 확보했습니다. 필요 시 테스트 소스에도 Q타입이 필요한 경우에만testAnnotationProcessor추가를 고려하세요..github/workflows/ci.yml (3)
15-17: concurrency group 키 개선 제안 — PR 번호 기반이 충돌/오작동에 안전
group: pr-ci-${{ github.ref }}는 동일 ref명(포크 등) 간 상호 취소 가능성이 있습니다. PR 번호를 사용하는 것이 안전합니다.concurrency: - group: pr-ci-${{ github.ref }} + group: pr-ci-${{ github.event.pull_request.number || github.run_id }} cancel-in-progress: true
60-70: 테스트 결과 게시 플로우 적절 — 실패 시 로그 아카이브 추가 고려문제 분석을 돕기 위해 실패 시
build.log/test.log업로드를 권장합니다.- name: Publish unit-test results (check UI) id: publish if: ${{ always() && !env.ACT && hashFiles('**/build/test-results/test/**/*.xml') != '' }} uses: EnricoMi/publish-unit-test-result-action@v2 @@ job_summary: true + + - name: Upload logs on failure + if: ${{ failure() }} + uses: actions/upload-artifact@v4 + with: + name: gradle-logs + path: | + build.log + test.log
94-95: 파일 끝 개행 누락일부 린터·도구에서 경고가 발생합니다. 마지막 줄에 개행을 추가해 주세요.
- run: exit 1 + run: exit 1 +
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (5)
.github/workflows/ci.yml(1 hunks)gdgoc/build.gradle(1 hunks)gdgoc/src/main/resources/application-local.yml(1 hunks)gdgoc/src/main/resources/application-prod.yml(2 hunks)gdgoc/src/test/resources/application-test.yml(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- gdgoc/src/main/resources/application-local.yml
🧰 Additional context used
🪛 YAMLlint (1.37.1)
.github/workflows/ci.yml
[error] 95-95: no new line character at the end of file
(new-line-at-end-of-file)
🪛 Gitleaks (8.27.2)
gdgoc/src/test/resources/application-test.yml
62-62: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
🔇 Additional comments (4)
gdgoc/src/test/resources/application-test.yml (2)
19-31: H2 + create-drop 구성 합리적입니다.테스트 독립성과 재현성을 높이는 설정입니다.
49-53: 로그 레벨 warn으로 절제, 적절합니다.gdgoc/build.gradle (2)
55-58: Flyway 코어 + Postgres 모듈 추가, 구성 적합합니다.운영/로컬 마이그레이션 구동에 필요한 런타임이 확보되었습니다.
76-80: 테스트 태스크의 프로필 고정 및 JUnit Platform 사용, CI 정합성 좋습니다.
| // --- JWT (JJWT 0.9.x, 레거시 패키지) --- | ||
| implementation 'io.jsonwebtoken:jjwt:0.9.1' | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
JJWT 0.9.1은 노후·보안 이슈 — 0.11.x 3분할 아티팩트로 전환 권장
0.9.x는 Jackson/서명 처리 관련 취약점과 JDK 최신 호환성 이슈가 보고되어 있습니다. 최신 0.11.x 계열로 전환해 주세요.
- implementation 'io.jsonwebtoken:jjwt:0.9.1'
+ // JJWT 0.11.x: API/Impl/JSON(Jackson) 분리
+ implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
+ runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5'
+ runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5'마이그레이션 시, 기존 Jwts.builder() 코드는 대부분 호환되며, 키/알고리즘 설정만 최신 가이드를 반영하면 됩니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // --- JWT (JJWT 0.9.x, 레거시 패키지) --- | |
| implementation 'io.jsonwebtoken:jjwt:0.9.1' | |
| // --- JWT (JJWT 0.9.x, 레거시 패키지) --- | |
| // JJWT 0.11.x: API/Impl/JSON(Jackson) 분리 | |
| implementation 'io.jsonwebtoken:jjwt-api:0.11.5' | |
| runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.5' | |
| runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.5' |
🤖 Prompt for AI Agents
In gdgoc/build.gradle around lines 49-51, the project is using the obsolete
io.jsonwebtoken:jjwt:0.9.1; update to the 0.11.x modular artifacts and adjust
Gradle declarations: remove the old single artifact and add jjwt-api:0.11.x as
the compile dependency plus jjwt-impl:0.11.x and jjwt-jackson:0.11.x as
runtime-only dependencies (or provided implementation) so the API/impl/Jackson
modules are available correctly; after changing dependencies, scan code for
signing/key creation usages and migrate to the 0.11.x patterns (use
io.jsonwebtoken.security.Keys, and the updated builder/key API per the JJWT 0.11
migration guide) to ensure key/algorithm handling complies with the new split
artifacts.
| // --- AWS (S3) --- | ||
| implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
spring-cloud-aws 2.2.6.RELEASE는 Spring Boot 3와 미호환 — awspring 3.x 또는 AWS SDK v2로 교체 필요
org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE는 Boot 2.x용이며 Jakarta 전환 이후(Boot 3)와 호환되지 않습니다. 런타임 예외 및 빈 로딩 실패 위험이 큽니다.
대안:
- 간단:
io.awspring.cloud:spring-cloud-aws-starter-s3:3.2.0(또는 최신) 사용 - 직접 SDK:
software.amazon.awssdk:s3+software.amazon.awssdk:sts
예시:
- implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
+ // Spring Boot 3 호환 AWS S3 Starter (Apring Cloud AWS 3.x)
+ implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3:3.2.0'AWS 설정 바인딩(spring.cloud.aws.*)과 S3Template/S3Client 주입 코드도 3.x 문법으로 점검이 필요합니다.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // --- AWS (S3) --- | |
| implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' | |
| // --- AWS (S3) --- | |
| // Spring Boot 3 호환 AWS S3 Starter (Apring Cloud AWS 3.x) | |
| implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3:3.2.0' |
🤖 Prompt for AI Agents
In gdgoc/build.gradle around lines 52 to 54, the project currently depends on
org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE which is
incompatible with Spring Boot 3; replace this dependency with the awspring 3.x
starter (e.g. io.awspring.cloud:spring-cloud-aws-starter-s3:3.2.0 or latest) or
swap to AWS SDK v2 dependencies (software.amazon.awssdk:s3 and
software.amazon.awssdk:sts), then update any configuration keys and bean wiring
to the 3.x/awsspring conventions (verify and migrate spring.cloud.aws.*
properties, replace legacy S3Template usages with the awspring S3 client/bean
APIs or SDK v2 S3Client, and adjust injection points and imports accordingly).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이미 잘 되고 있는데
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kaswhy 현재 작동하고 있다니 다행입니다!
다만 spring-cloud-aws 2.2.6과 Spring Boot 3 간의 호환성 이슈는 AWS 기능을 실제로 사용할 때 나타날 수 있습니다. 현재 AWS S3 기능을 적극적으로 사용하고 계신지 궁금합니다.
만약 아직 AWS 관련 기능을 본격적으로 구현하지 않으셨다면, 나중에 S3 업로드나 SES 이메일 발송 등을 구현할 때 Jakarta EE vs Java EE 네임스페이스 충돌로 인한 문제가 발생할 수 있습니다.
현재 설정으로 계속 진행하시되, 혹시 AWS 관련 기능 구현 시 문제가 발생하면 awspring 3.x로의 마이그레이션을 고려해보시길 권합니다.
(\ /)
( ._.)
o_(")(")
✏️ Learnings added
Learnt from: kaswhy
PR: GDGoCINHA/24-2_GDGoC_Server#180
File: gdgoc/build.gradle:52-54
Timestamp: 2025-08-23T03:40:02.707Z
Learning: In the gdgoc project using Spring Boot 3, the user kaswhy confirmed that spring-cloud-aws 2.2.6.RELEASE dependency is currently working for them despite known compatibility concerns with Jakarta EE migration.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
| flyway: | ||
| enabled: true | ||
| baseline-on-migrate: true # 변경 확인 후 제거 예정 | ||
| clean-disabled: true | ||
| validate-migration-naming: true | ||
| locations: classpath:db/migration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Flyway locations와 실제 마이그레이션 파일 위치 불일치 가능성 — 운영 시 마이그레이션 미적용 위험
현재 locations: classpath:db/migration 입니다. 이 경우 마이그레이션 스크립트는 반드시 src/main/resources/db/migration 아래에 있어야 합니다. 과거 커밋/리뷰 맥락상 파일이 src/main/db/migration에 존재했던 기록이 있어, 그대로라면 JAR 클래스패스에 포함되지 않아 운영에서 마이그레이션이 전혀 실행되지 않을 수 있습니다. 리소스 경로로 이동하는 것을 권장합니다.
다음 선택지 중 하나로 정합성을 맞춰 주세요.
- 권장: 스크립트를
src/main/resources/db/migration으로 이동 - 대안: (권장하지 않음) 운영 설정에 파일시스템 경로를 추가
참고 diff(리소스 경로 하드닝 및 추가 검증 옵션):
spring:
flyway:
enabled: true
- baseline-on-migrate: true # 변경 확인 후 제거 예정
+ baseline-on-migrate: true # 최초 1회 실행 후 제거 권장
+ validate-on-migrate: true
clean-disabled: true
validate-migration-naming: true
locations: classpath:db/migration검증 스크립트(파일 위치 확인):
🏁 Script executed:
#!/bin/bash
# 마이그레이션 파일이 resources 경로에 존재하는지 확인
echo "[1] resources 경로 확인"
fd -a '^db/migration/.+\.sql$' gdgoc/src/main/resources || echo ">> resources/db/migration 경로에 없음"
echo "[2] main/db/migration 경로 잔존 여부 확인"
fd -a '^db/migration/.+\.sql$' gdgoc/src/main/db 2>/dev/null && echo ">> src/main/db/migration 경로에 존재함(리소스로 이동 필요)"Length of output: 333
Flyway 마이그레이션 파일 경로 불일치 확인 및 조치 필요
운영 시 마이그레이션 미적용 위험이 실제로 존재함이 확인되었습니다.
application-prod.yml의 설정(locations: classpath:db/migration)은 src/main/resources/db/migration 내 스크립트만 로드하며, 현재 별도 경로인 src/main/db/migration에도 SQL 파일이 존재합니다.
조치 항목:
- 마이그레이션 파일 이동
gdgoc/src/main/db/migration/*.sql → gdgoc/src/main/resources/db/migration/ - (비권장) 운영 설정에 파일시스템 경로 추가
추가 권장 설정 hardening:
spring:
flyway:
enabled: true
- baseline-on-migrate: true # 변경 확인 후 제거 예정
+ baseline-on-migrate: true # 최초 1회 실행 후 제거 권장
+ validate-on-migrate: true
clean-disabled: true
validate-migration-naming: true
locations: classpath:db/migration📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| flyway: | |
| enabled: true | |
| baseline-on-migrate: true # 변경 확인 후 제거 예정 | |
| clean-disabled: true | |
| validate-migration-naming: true | |
| locations: classpath:db/migration | |
| spring: | |
| flyway: | |
| enabled: true | |
| baseline-on-migrate: true # 최초 1회 실행 후 제거 권장 | |
| validate-on-migrate: true | |
| clean-disabled: true | |
| validate-migration-naming: true | |
| locations: classpath:db/migration |
🤖 Prompt for AI Agents
In gdgoc/src/main/resources/application-prod.yml around lines 26–31, Flyway is
configured to load migrations from classpath:db/migration but some SQL files
currently reside in gdgoc/src/main/db/migration; move all SQL files from
gdgoc/src/main/db/migration into gdgoc/src/main/resources/db/migration (use git
mv so history is preserved) so they are packaged on the classpath, run a local
build to verify migrations are found, and remove any duplicate paths;
alternatively (not recommended) you may add a filesystem location to
application-prod.yml (e.g.,
filesystem:/absolute/or/project/path/src/main/db/migration) if you cannot move
files—if you choose the move option, also update CI/build scripts if they
reference the old path and consider enabling strict path validation in Flyway
settings as a hardening step.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (7)
gdgoc/src/main/resources/db/migration/V20250823__user_role_ordinal_to_string.sql (2)
1-16: CHECK 제약조건 드롭 로직이 다소 광범위함 — 드롭 대상 로깅/스코프 축소 고려pg_get_constraintdef ILIKE '%user_role%' 기준은 안전망이지만, 향후 다른 컬럼과 결합된 CHECK에도 매치될 수 있습니다. 최소한 드롭되는 제약조건명을 NOTICE로 남기거나, 패턴을 더 구체화(예: 컬럼명 토큰 경계)하는 방안을 고려해 주세요.
예시(로깅 추가):
DO $$ DECLARE r record; BEGIN FOR r IN SELECT conname FROM pg_constraint c ... LOOP + RAISE NOTICE 'Dropping constraint: %', r.conname; EXECUTE format('ALTER TABLE public.users DROP CONSTRAINT %I', r.conname); END LOOP; END $$;
20-31: 1패스 변환으로 테이블 재작성 최소화 (ALTER ... USING CASE) 또는 UPDATE 범위 축소현재는 TYPE 캐스트 후 UPDATE로 전 테이블을 한 번 더 쓰기합니다. CASE를 포함한 USING 절로 한 번에 매핑하면 write 패스를 줄일 수 있습니다. 유지 시에는 UPDATE에 WHERE를 추가해 불필요한 페이지 쓰기를 피하세요.
대체안 A: 단일 ALTER
-ALTER TABLE public.users - ALTER COLUMN user_role TYPE varchar(32) - USING user_role::text; - -UPDATE public.users -SET user_role = CASE user_role - WHEN '0' THEN 'GUEST' - WHEN '1' THEN 'MEMBER' - WHEN '2' THEN 'ADMIN' - ELSE user_role - END; +ALTER TABLE public.users + ALTER COLUMN user_role + TYPE varchar(32) + USING CASE + WHEN user_role = 0 THEN 'GUEST' + WHEN user_role = 1 THEN 'MEMBER' + WHEN user_role = 2 THEN 'ADMIN' + ELSE user_role::text + END;대체안 B: 현 구조 유지 시 UPDATE 범위 제한
-UPDATE public.users -SET user_role = CASE user_role - WHEN '0' THEN 'GUEST' - WHEN '1' THEN 'MEMBER' - WHEN '2' THEN 'ADMIN' - ELSE user_role - END; +UPDATE public.users +SET user_role = CASE user_role + WHEN '0' THEN 'GUEST' + WHEN '1' THEN 'MEMBER' + WHEN '2' THEN 'ADMIN' + ELSE user_role + END +WHERE user_role IN ('0','1','2');.github/workflows/ci.yml (5)
9-14: 워크플로 권한 최소화(least privilege) 재점검현재 checks/pull-requests/issues 모두 write입니다. 이 워크플로는 체크 게시와 코멘트 작성이 핵심이므로 pull-requests: write 없이도 동작 가능할 수 있습니다. 필요 최소 권한만 남기는 것을 권장합니다.
권장 예시:
permissions: contents: read checks: write - pull-requests: write issues: write필요 시 특정 액션 요구 권한을 확인 후 재조정해 주세요.
15-18: 동시성 그룹 식별자에 워크플로 이름 포함 권장여러 CI 워크플로가 있을 때 ref만으로는 구분이 모호할 수 있습니다. 워크플로명까지 포함하면 상호 간섭을 확실히 차단할 수 있습니다.
예시:
concurrency: - group: pr-ci-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true
71-92: 상태 메시지에 로그 아티팩트 링크 추가 제안PR 코멘트만으로는 디버깅이 어려울 수 있습니다. build.log / test.log를 아티팩트로 업로드하고 메시지에 링크를 포함시키면 트러블슈팅이 쉬워집니다.
아티팩트 업로드 단계 추가:
- name: Gradle test (H2 in-memory) id: test working-directory: gdgoc ... run: ./gradlew test --no-daemon --stacktrace --info --no-watch-fs | tee ../test.log + - name: Upload build artifacts + if: ${{ always() }} + uses: actions/upload-artifact@v4 + with: + name: build-and-test-logs + path: | + build.log + test.log메시지 단계에서 링크를 자동 생성하려면 job summary를 활용하거나 코멘트에 “Actions → Artifacts 참조” 문구를 추가하세요.
23-44: Gradle Wrapper 무결성 검증 추가 권장빌드 전 wrapper 검증을 통해 서드파티 코드 주입 리스크를 낮출 수 있습니다.
추가 예시:
steps: - uses: actions/checkout@v4 + - name: Validate Gradle Wrapper + uses: gradle/wrapper-validation-action@v2 - uses: actions/setup-java@v4 with: { distribution: temurin, java-version: 17 }
115-117: EOF 개행 누락 (YAMLlint 지적 반영)파일 끝 개행이 없습니다. 일부 도구에서 diff/패치 시 불필요한 잡음이 생길 수 있어 추가를 권장합니다.
- run: exit 1 + run: exit 1 +
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
.github/workflows/ci.yml(1 hunks)gdgoc/src/main/resources/db/migration/V20250823__user_role_ordinal_to_string.sql(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-23T02:57:49.824Z
Learnt from: kaswhy
PR: GDGoCINHA/24-2_GDGoC_Server#180
File: gdgoc/src/main/db/migration/V20250823__user_role_ordinal_to_string.sql:25-32
Timestamp: 2025-08-23T02:57:49.824Z
Learning: In the GDGoCINHA/24-2_GDGoC_Server project, the user_role column in the users table contains only valid ordinal values (0, 1, 2) with no NULL values or invalid data, so additional data cleanup steps in migrations are not necessary.
Applied to files:
gdgoc/src/main/resources/db/migration/V20250823__user_role_ordinal_to_string.sql
🪛 YAMLlint (1.37.1)
.github/workflows/ci.yml
[error] 117-117: no new line character at the end of file
(new-line-at-end-of-file)
🔇 Additional comments (3)
gdgoc/src/main/resources/db/migration/V20250823__user_role_ordinal_to_string.sql (1)
34-38: NOT NULL 정합성 확인 및 필요 시 제약 추가엔티티(User.userRole)가 DB에서 NOT NULL을 기대한다면 여기서도 명시하는 편이 안전합니다. 장기적으로 데이터 품질을 보장합니다. 장기 운영 중 NULL이 허용되어야 한다면 이 코멘트는 무시하셔도 됩니다. (학습 메모에 따르면 현 데이터에는 NULL이 없다고 하셨습니다.)
선택 적용안:
ALTER TABLE public.users ALTER COLUMN user_role SET DEFAULT 'GUEST'; ALTER TABLE public.users ADD CONSTRAINT users_user_role_check CHECK (user_role IN ('GUEST','MEMBER','ADMIN')); + +-- (옵션) 애플리케이션이 필드를 필수로 다룬다면: +ALTER TABLE public.users + ALTER COLUMN user_role SET NOT NULL;.github/workflows/ci.yml (2)
45-58: 테스트를 H2(PostgreSQL 모드)로 분리하고 Flyway 비활성화한 점 좋습니다SPRING_FLYWAY_ENABLED="false" 지정으로 Postgres 전용 마이그레이션과의 충돌을 회피했습니다. CI에서 테스트 신뢰도를 높이는 방향입니다.
27-31: ACT 로컬 실행 분기 조건 재확인if: ${{ !env.ACT }} 패턴은 일반적으로 동작하지만, 로컬 환경에 따라 env.ACT 값이 문자열로 세팅될 때의 진리값 해석이 엣지일 수 있습니다. 문제 없으면 유지, 이슈가 보이면 matrix/context 기반 분기로 대체를 고려하세요.
대체 예시:
- - uses: gradle/actions/setup-gradle@v3 - if: ${{ !env.ACT }} + - uses: gradle/actions/setup-gradle@v3 + if: ${{ !contains(env.ACT, 'true') }}
📌 연관된 이슈
✨ 작업 내용
💬 리뷰 요구사항(선택)
Summary by CodeRabbit
신규 기능
버그 수정
테스트
작업(Chores)