-
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
Changes from all commits
5901c80
2585c45
7dcca89
8f17102
26aa16b
880b60b
706abe5
e7ad8e8
eeac732
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,117 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| pull_request: | ||
| branches: [ "develop", "main" ] | ||
| types: [ opened, synchronize, reopened, ready_for_review ] | ||
| workflow_dispatch: {} | ||
|
|
||
| permissions: | ||
| contents: read | ||
| checks: write | ||
| pull-requests: write | ||
| issues: write | ||
|
|
||
| concurrency: | ||
| group: pr-ci-${{ github.ref }} | ||
| cancel-in-progress: true | ||
|
|
||
| jobs: | ||
| build: | ||
| runs-on: ubuntu-latest | ||
|
|
||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-java@v4 | ||
| with: { distribution: temurin, java-version: 17 } | ||
| - uses: gradle/actions/setup-gradle@v3 | ||
| if: ${{ !env.ACT }} | ||
| with: | ||
| cache-read-only: ${{ github.event_name == 'pull_request' }} | ||
| gradle-home-cache-cleanup: true | ||
|
|
||
| - name: Create dummy .env for CI | ||
| working-directory: gdgoc | ||
| run: echo "# ci dummy" > .env | ||
|
|
||
| - name: Gradle build (skip tests) | ||
| id: assemble | ||
| working-directory: gdgoc | ||
| env: { GRADLE_OPTS: "-Dorg.gradle.vfs.watch=false" } | ||
| run: | | ||
| chmod +x ./gradlew | ||
| ./gradlew build -x test --no-daemon --stacktrace --info --no-watch-fs | tee ../build.log | ||
|
|
||
| - name: Gradle test (H2 in-memory) | ||
| id: test | ||
| working-directory: gdgoc | ||
| env: | ||
| GRADLE_OPTS: "-Dorg.gradle.vfs.watch=false" | ||
| SPRING_PROFILES_ACTIVE: test | ||
| SPRING_DATASOURCE_URL: jdbc:h2:mem:ci;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE | ||
| SPRING_DATASOURCE_USERNAME: sa | ||
| SPRING_DATASOURCE_PASSWORD: "" | ||
| SPRING_DATASOURCE_DRIVER_CLASS_NAME: org.h2.Driver | ||
| SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.H2Dialect | ||
| SPRING_JPA_HIBERNATE_DDL_AUTO: create-drop | ||
| SPRING_FLYWAY_ENABLED: "false" | ||
| run: ./gradlew test --no-daemon --stacktrace --info --no-watch-fs | tee ../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 | ||
| with: | ||
| github_token: ${{ secrets.GITHUB_TOKEN }} | ||
| files: "**/build/test-results/test/**/*.xml" | ||
| comment_mode: off | ||
| check_run: ${{ !github.event.pull_request.head.repo.fork }} | ||
| job_summary: true | ||
|
|
||
| - name: Compose message | ||
| id: status | ||
| if: ${{ always() }} | ||
| run: | | ||
| if [ "${{ steps.assemble.outcome }}" = "success" ]; then | ||
| MSG="✅ Assemble 성공" | ||
| else | ||
| MSG="❌ Assemble 실패" | ||
| fi | ||
|
|
||
| if [ "${{ steps.test.outcome }}" = "success" ]; then | ||
| MSG="$MSG"$'\n'"✅ Test 성공" | ||
| else | ||
| MSG="$MSG"$'\n'"❌ Test 실패" | ||
| fi | ||
|
|
||
| if [ "${{ steps.publish.outcome }}" = "failure" ]; then | ||
| MSG="$MSG"$'\n'"⚠️ 테스트 리포트 게시 실패(권한/토큰 문제일 수 있음)" | ||
| fi | ||
|
|
||
| printf "message<<EOF\n%s\nEOF\n" "$MSG" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Find existing CI status comment | ||
| id: find-comment | ||
| if: ${{ always() && github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && !env.ACT }} | ||
| uses: peter-evans/find-comment@v3 | ||
| with: | ||
| issue-number: ${{ github.event.pull_request.number }} | ||
| comment-author: 'github-actions[bot]' | ||
| body-includes: 'CI status' | ||
|
|
||
| - name: Create or update PR comment | ||
| if: ${{ always() && github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && !env.ACT }} | ||
| uses: peter-evans/create-or-update-comment@v4 | ||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
| issue-number: ${{ github.event.pull_request.number }} | ||
| comment-id: ${{ steps.find-comment.outputs.comment-id }} | ||
| edit-mode: replace | ||
| body: | | ||
| **CI status** | ||
| ${{ steps.status.outputs.message }} | ||
|
|
||
|
|
||
| - name: Fail if any failed | ||
| if: ${{ always() && (steps.assemble.outcome != 'success' || steps.test.outcome != 'success') }} | ||
| run: exit 1 |
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,70 +7,80 @@ plugins { | |||||||||||
| group = 'inha' | ||||||||||||
| version = '0.0.1-SNAPSHOT' | ||||||||||||
|
|
||||||||||||
| /* ===== Java Toolchain ===== */ | ||||||||||||
| java { | ||||||||||||
| toolchain { | ||||||||||||
| languageVersion = JavaLanguageVersion.of(17) | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /* ===== Configurations ===== */ | ||||||||||||
| configurations { | ||||||||||||
| compileOnly { | ||||||||||||
| extendsFrom annotationProcessor | ||||||||||||
| } | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /* ===== Repositories ===== */ | ||||||||||||
| repositories { | ||||||||||||
| mavenCentral() | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| /* ===== Dependencies ===== */ | ||||||||||||
| dependencies { | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||||||||||||
| // --- Spring Boot Starters --- | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-web' | ||||||||||||
| implementation 'com.vladmihalcea:hibernate-types-60:2.21.1' | ||||||||||||
| implementation group: 'org.postgresql', name: 'postgresql', version: '42.7.3' | ||||||||||||
| implementation 'io.github.cdimascio:java-dotenv:5.2.2' | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-data-jpa' | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-validation' | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-mail' | ||||||||||||
|
|
||||||||||||
| compileOnly 'org.projectlombok:lombok' | ||||||||||||
| runtimeOnly 'com.h2database:h2' | ||||||||||||
| annotationProcessor 'org.projectlombok:lombok' | ||||||||||||
| // --- DB & JPA Utils --- | ||||||||||||
| implementation 'com.vladmihalcea:hibernate-types-60:2.21.1' | ||||||||||||
| implementation 'org.postgresql:postgresql:42.7.3' | ||||||||||||
| runtimeOnly 'com.h2database:h2' // 테스트/로컬용 인메모리 DB | ||||||||||||
|
|
||||||||||||
| testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||||||||||||
| testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||||||||||||
| // --- QueryDSL --- | ||||||||||||
| implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' | ||||||||||||
| annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta' | ||||||||||||
| annotationProcessor 'jakarta.annotation:jakarta.annotation-api' | ||||||||||||
| annotationProcessor 'jakarta.persistence:jakarta.persistence-api' | ||||||||||||
|
|
||||||||||||
| testImplementation 'org.mockito:mockito-core:5.6.0' | ||||||||||||
| testImplementation 'org.mockito:mockito-junit-jupiter:5.6.0' | ||||||||||||
| // --- JWT (JJWT 0.9.x, 레거시 패키지) --- | ||||||||||||
| implementation 'io.jsonwebtoken:jjwt:0.9.1' | ||||||||||||
|
|
||||||||||||
| testImplementation 'org.assertj:assertj-core:3.24.2' | ||||||||||||
| // --- AWS (S3) --- | ||||||||||||
| implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' | ||||||||||||
|
|
||||||||||||
|
Comment on lines
+52
to
54
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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로 교체 필요
대안:
예시: - 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 설정 바인딩( 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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로의 마이그레이션을 고려해보시길 권합니다. ✏️ Learnings added
|
||||||||||||
| //querydsl | ||||||||||||
| implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' | ||||||||||||
| annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta" | ||||||||||||
| annotationProcessor "jakarta.annotation:jakarta.annotation-api" | ||||||||||||
| annotationProcessor "jakarta.persistence:jakarta.persistence-api" | ||||||||||||
| // --- Flyway (DB Migration) --- | ||||||||||||
| implementation "org.flywaydb:flyway-core:10.21.0" | ||||||||||||
| implementation "org.flywaydb:flyway-database-postgresql:10.21.0" | ||||||||||||
|
|
||||||||||||
| // OAuth | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' | ||||||||||||
| // --- 환경변수(.env) --- | ||||||||||||
| implementation 'io.github.cdimascio:java-dotenv:5.2.2' | ||||||||||||
|
|
||||||||||||
| // jwt | ||||||||||||
| implementation 'io.jsonwebtoken:jjwt:0.9.1' | ||||||||||||
| // --- Lombok --- | ||||||||||||
| compileOnly 'org.projectlombok:lombok' | ||||||||||||
| annotationProcessor 'org.projectlombok:lombok' | ||||||||||||
|
|
||||||||||||
| // --- Test --- | ||||||||||||
| testImplementation 'org.springframework.boot:spring-boot-starter-test' | ||||||||||||
| testImplementation 'org.mockito:mockito-core:5.6.0' | ||||||||||||
| testImplementation 'org.mockito:mockito-junit-jupiter:5.6.0' | ||||||||||||
| testImplementation 'org.assertj:assertj-core:3.24.2' | ||||||||||||
| testRuntimeOnly 'org.junit.platform:junit-platform-launcher' | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // aws s3 | ||||||||||||
| implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE' | ||||||||||||
| /* ===== Tasks ===== */ | ||||||||||||
|
|
||||||||||||
| // mail sender | ||||||||||||
| implementation 'org.springframework.boot:spring-boot-starter-mail' | ||||||||||||
| // 테스트: 프로필과 JUnit 플랫폼 한 곳에서 설정 | ||||||||||||
| tasks.test { | ||||||||||||
| useJUnitPlatform() | ||||||||||||
| systemProperty "spring.profiles.active", "test" | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| // QueryDSL 생성물 경로 고정 | ||||||||||||
| tasks.withType(JavaCompile).configureEach { | ||||||||||||
| options.annotationProcessorGeneratedSourcesDirectory = file("build/generated/sources/annotationProcessor/java/main") | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| tasks.named('compileJava') { | ||||||||||||
| dependsOn 'clean' | ||||||||||||
| } | ||||||||||||
|
|
||||||||||||
| tasks.named('test') { | ||||||||||||
| useJUnitPlatform() | ||||||||||||
| } | ||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -21,8 +21,14 @@ spring: | |||||||||||||||||||||||||||||
| hibernate: | ||||||||||||||||||||||||||||||
| default_batch_fetch_size: 100 | ||||||||||||||||||||||||||||||
| time_zone: Asia/Seoul | ||||||||||||||||||||||||||||||
| show-sql: true | ||||||||||||||||||||||||||||||
| show-sql: false | ||||||||||||||||||||||||||||||
| database-platform: org.hibernate.dialect.PostgreSQLDialect | ||||||||||||||||||||||||||||||
| flyway: | ||||||||||||||||||||||||||||||
| enabled: true | ||||||||||||||||||||||||||||||
kaswhy marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||
| baseline-on-migrate: true # 변경 확인 후 제거 예정 | ||||||||||||||||||||||||||||||
| clean-disabled: true | ||||||||||||||||||||||||||||||
| validate-migration-naming: true | ||||||||||||||||||||||||||||||
| locations: classpath:db/migration | ||||||||||||||||||||||||||||||
|
Comment on lines
+26
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chainFlyway locations와 실제 마이그레이션 파일 위치 불일치 가능성 — 운영 시 마이그레이션 미적용 위험 현재 다음 선택지 중 하나로 정합성을 맞춰 주세요.
참고 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 마이그레이션 파일 경로 불일치 확인 및 조치 필요 운영 시 마이그레이션 미적용 위험이 실제로 존재함이 확인되었습니다. 조치 항목:
추가 권장 설정 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
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||
| mail: | ||||||||||||||||||||||||||||||
| host: smtp.gmail.com | ||||||||||||||||||||||||||||||
| port: 587 | ||||||||||||||||||||||||||||||
|
|
@@ -38,7 +44,7 @@ spring: | |||||||||||||||||||||||||||||
| logging: | ||||||||||||||||||||||||||||||
| level: | ||||||||||||||||||||||||||||||
| org.hibernate.SQL: debug | ||||||||||||||||||||||||||||||
| org.hibername.type: trace | ||||||||||||||||||||||||||||||
| org.hibernate.type: off | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| google: | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| DO $$ | ||
| DECLARE r record; | ||
| BEGIN | ||
| FOR r IN | ||
| SELECT conname | ||
| FROM pg_constraint c | ||
| JOIN pg_class t ON t.oid = c.conrelid | ||
| JOIN pg_namespace n ON n.oid = t.relnamespace | ||
| WHERE t.relname = 'users' | ||
| AND n.nspname = 'public' | ||
| AND c.contype = 'c' | ||
| AND pg_get_constraintdef(c.oid) ILIKE '%user_role%' -- user_role 관련 CHECK | ||
| LOOP | ||
| EXECUTE format('ALTER TABLE public.users DROP CONSTRAINT %I', r.conname); | ||
| END LOOP; | ||
| END $$; | ||
|
|
||
| ALTER TABLE public.users ALTER COLUMN user_role DROP DEFAULT; | ||
|
|
||
| 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; | ||
|
|
||
| -- 5) 새 디폴트/체크 제약조건 설정 | ||
| 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')); |
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 계열로 전환해 주세요.
마이그레이션 시, 기존
Jwts.builder()코드는 대부분 호환되며, 키/알고리즘 설정만 최신 가이드를 반영하면 됩니다.📝 Committable suggestion
🤖 Prompt for AI Agents