Skip to content

Commit bb1c1d5

Browse files
authored
[FEAT] CI 추가 및 RDS 변경
[FEAT] CI 추가 및 RDS 변경
2 parents 168b8eb + 6c4b6fd commit bb1c1d5

File tree

10 files changed

+295
-37
lines changed

10 files changed

+295
-37
lines changed

.github/workflows/ci.yml

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
branches: [ "develop", "main" ]
6+
types: [ opened, synchronize, reopened, ready_for_review ]
7+
workflow_dispatch: {}
8+
9+
permissions:
10+
contents: read
11+
checks: write
12+
pull-requests: write
13+
issues: write
14+
15+
concurrency:
16+
group: pr-ci-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
build:
21+
runs-on: ubuntu-latest
22+
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: actions/setup-java@v4
26+
with: { distribution: temurin, java-version: 17 }
27+
- uses: gradle/actions/setup-gradle@v3
28+
if: ${{ !env.ACT }}
29+
with:
30+
cache-read-only: ${{ github.event_name == 'pull_request' }}
31+
gradle-home-cache-cleanup: true
32+
33+
- name: Create dummy .env for CI
34+
working-directory: gdgoc
35+
run: echo "# ci dummy" > .env
36+
37+
- name: Gradle build (skip tests)
38+
id: assemble
39+
working-directory: gdgoc
40+
env: { GRADLE_OPTS: "-Dorg.gradle.vfs.watch=false" }
41+
run: |
42+
chmod +x ./gradlew
43+
./gradlew build -x test --no-daemon --stacktrace --info --no-watch-fs | tee ../build.log
44+
45+
- name: Gradle test (H2 in-memory)
46+
id: test
47+
working-directory: gdgoc
48+
env:
49+
GRADLE_OPTS: "-Dorg.gradle.vfs.watch=false"
50+
SPRING_PROFILES_ACTIVE: test
51+
SPRING_DATASOURCE_URL: jdbc:h2:mem:ci;MODE=PostgreSQL;DB_CLOSE_DELAY=-1;DATABASE_TO_LOWER=TRUE
52+
SPRING_DATASOURCE_USERNAME: sa
53+
SPRING_DATASOURCE_PASSWORD: ""
54+
SPRING_DATASOURCE_DRIVER_CLASS_NAME: org.h2.Driver
55+
SPRING_JPA_DATABASE_PLATFORM: org.hibernate.dialect.H2Dialect
56+
SPRING_JPA_HIBERNATE_DDL_AUTO: create-drop
57+
SPRING_FLYWAY_ENABLED: "false"
58+
run: ./gradlew test --no-daemon --stacktrace --info --no-watch-fs | tee ../test.log
59+
60+
- name: Publish unit-test results (check UI)
61+
id: publish
62+
if: ${{ always() && !env.ACT && hashFiles('**/build/test-results/test/**/*.xml') != '' }}
63+
uses: EnricoMi/publish-unit-test-result-action@v2
64+
with:
65+
github_token: ${{ secrets.GITHUB_TOKEN }}
66+
files: "**/build/test-results/test/**/*.xml"
67+
comment_mode: off
68+
check_run: ${{ !github.event.pull_request.head.repo.fork }}
69+
job_summary: true
70+
71+
- name: Compose message
72+
id: status
73+
if: ${{ always() }}
74+
run: |
75+
if [ "${{ steps.assemble.outcome }}" = "success" ]; then
76+
MSG="✅ Assemble 성공"
77+
else
78+
MSG="❌ Assemble 실패"
79+
fi
80+
81+
if [ "${{ steps.test.outcome }}" = "success" ]; then
82+
MSG="$MSG"$'\n'"✅ Test 성공"
83+
else
84+
MSG="$MSG"$'\n'"❌ Test 실패"
85+
fi
86+
87+
if [ "${{ steps.publish.outcome }}" = "failure" ]; then
88+
MSG="$MSG"$'\n'"⚠️ 테스트 리포트 게시 실패(권한/토큰 문제일 수 있음)"
89+
fi
90+
91+
printf "message<<EOF\n%s\nEOF\n" "$MSG" >> "$GITHUB_OUTPUT"
92+
93+
- name: Find existing CI status comment
94+
id: find-comment
95+
if: ${{ always() && github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && !env.ACT }}
96+
uses: peter-evans/find-comment@v3
97+
with:
98+
issue-number: ${{ github.event.pull_request.number }}
99+
comment-author: 'github-actions[bot]'
100+
body-includes: 'CI status'
101+
102+
- name: Create or update PR comment
103+
if: ${{ always() && github.event_name == 'pull_request' && !github.event.pull_request.head.repo.fork && !env.ACT }}
104+
uses: peter-evans/create-or-update-comment@v4
105+
with:
106+
token: ${{ secrets.GITHUB_TOKEN }}
107+
issue-number: ${{ github.event.pull_request.number }}
108+
comment-id: ${{ steps.find-comment.outputs.comment-id }}
109+
edit-mode: replace
110+
body: |
111+
**CI status**
112+
${{ steps.status.outputs.message }}
113+
114+
115+
- name: Fail if any failed
116+
if: ${{ always() && (steps.assemble.outcome != 'success' || steps.test.outcome != 'success') }}
117+
run: exit 1

gdgoc/build.gradle

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -7,70 +7,80 @@ plugins {
77
group = 'inha'
88
version = '0.0.1-SNAPSHOT'
99

10+
/* ===== Java Toolchain ===== */
1011
java {
1112
toolchain {
1213
languageVersion = JavaLanguageVersion.of(17)
1314
}
1415
}
1516

17+
/* ===== Configurations ===== */
1618
configurations {
1719
compileOnly {
1820
extendsFrom annotationProcessor
1921
}
2022
}
2123

24+
/* ===== Repositories ===== */
2225
repositories {
2326
mavenCentral()
2427
}
2528

29+
/* ===== Dependencies ===== */
2630
dependencies {
27-
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
31+
// --- Spring Boot Starters ---
2832
implementation 'org.springframework.boot:spring-boot-starter-web'
29-
implementation 'com.vladmihalcea:hibernate-types-60:2.21.1'
30-
implementation group: 'org.postgresql', name: 'postgresql', version: '42.7.3'
31-
implementation 'io.github.cdimascio:java-dotenv:5.2.2'
33+
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
3234
implementation 'org.springframework.boot:spring-boot-starter-validation'
35+
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
36+
implementation 'org.springframework.boot:spring-boot-starter-mail'
3337

34-
compileOnly 'org.projectlombok:lombok'
35-
runtimeOnly 'com.h2database:h2'
36-
annotationProcessor 'org.projectlombok:lombok'
38+
// --- DB & JPA Utils ---
39+
implementation 'com.vladmihalcea:hibernate-types-60:2.21.1'
40+
implementation 'org.postgresql:postgresql:42.7.3'
41+
runtimeOnly 'com.h2database:h2' // 테스트/로컬용 인메모리 DB
3742

38-
testImplementation 'org.springframework.boot:spring-boot-starter-test'
39-
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
43+
// --- QueryDSL ---
44+
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
45+
annotationProcessor 'com.querydsl:querydsl-apt:5.0.0:jakarta'
46+
annotationProcessor 'jakarta.annotation:jakarta.annotation-api'
47+
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
4048

41-
testImplementation 'org.mockito:mockito-core:5.6.0'
42-
testImplementation 'org.mockito:mockito-junit-jupiter:5.6.0'
49+
// --- JWT (JJWT 0.9.x, 레거시 패키지) ---
50+
implementation 'io.jsonwebtoken:jjwt:0.9.1'
4351

44-
testImplementation 'org.assertj:assertj-core:3.24.2'
52+
// --- AWS (S3) ---
53+
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
4554

46-
//querydsl
47-
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
48-
annotationProcessor "com.querydsl:querydsl-apt:5.0.0:jakarta"
49-
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
50-
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
55+
// --- Flyway (DB Migration) ---
56+
implementation "org.flywaydb:flyway-core:10.21.0"
57+
implementation "org.flywaydb:flyway-database-postgresql:10.21.0"
5158

52-
// OAuth
53-
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
59+
// --- 환경변수(.env) ---
60+
implementation 'io.github.cdimascio:java-dotenv:5.2.2'
5461

55-
// jwt
56-
implementation 'io.jsonwebtoken:jjwt:0.9.1'
62+
// --- Lombok ---
63+
compileOnly 'org.projectlombok:lombok'
64+
annotationProcessor 'org.projectlombok:lombok'
5765

66+
// --- Test ---
67+
testImplementation 'org.springframework.boot:spring-boot-starter-test'
68+
testImplementation 'org.mockito:mockito-core:5.6.0'
69+
testImplementation 'org.mockito:mockito-junit-jupiter:5.6.0'
70+
testImplementation 'org.assertj:assertj-core:3.24.2'
71+
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
72+
}
5873

59-
// aws s3
60-
implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'
74+
/* ===== Tasks ===== */
6175

62-
// mail sender
63-
implementation 'org.springframework.boot:spring-boot-starter-mail'
76+
// 테스트: 프로필과 JUnit 플랫폼 한 곳에서 설정
77+
tasks.test {
78+
useJUnitPlatform()
79+
systemProperty "spring.profiles.active", "test"
6480
}
6581

82+
// QueryDSL 생성물 경로 고정
6683
tasks.withType(JavaCompile).configureEach {
6784
options.annotationProcessorGeneratedSourcesDirectory = file("build/generated/sources/annotationProcessor/java/main")
6885
}
6986

70-
tasks.named('compileJava') {
71-
dependsOn 'clean'
72-
}
73-
74-
tasks.named('test') {
75-
useJUnitPlatform()
76-
}

gdgoc/src/main/java/inha/gdgoc/config/DotenvLoader.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import io.github.cdimascio.dotenv.Dotenv;
44
import jakarta.annotation.PostConstruct;
5+
import org.springframework.context.annotation.Profile;
56
import org.springframework.stereotype.Component;
67

8+
@Profile("!test")
79
@Component
810
public class DotenvLoader {
911

gdgoc/src/main/java/inha/gdgoc/domain/user/entity/User.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
import jakarta.persistence.CascadeType;
1010
import jakarta.persistence.Column;
1111
import jakarta.persistence.Entity;
12+
import jakarta.persistence.EnumType;
13+
import jakarta.persistence.Enumerated;
1214
import jakarta.persistence.GeneratedValue;
1315
import jakarta.persistence.GenerationType;
1416
import jakarta.persistence.Id;
@@ -58,6 +60,7 @@ public class User extends BaseEntity {
5860
@Column(name = "password", nullable = false)
5961
private String password;
6062

63+
@Enumerated(EnumType.STRING)
6164
@Column(name = "user_role", nullable = false)
6265
private UserRole userRole;
6366

gdgoc/src/main/java/inha/gdgoc/domain/user/enums/UserRole.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
@Getter
66
public enum UserRole {
7-
GUEST("Guest"),
8-
MEMBER("Member"),
7+
GUEST("GUEST"),
8+
MEMBER("MEMBER"),
99
ADMIN("ADMIN");
1010

1111
private final String role;

gdgoc/src/main/resources/application-local.yml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@ spring:
1515
jpa:
1616
database: postgresql
1717
hibernate:
18-
ddl-auto: update
18+
ddl-auto: none
1919
properties:
2020
hibernate:
2121
default_batch_fetch_size: 100
2222
jdbc:
2323
time_zone: Asia/Seoul
24+
flyway:
25+
enabled: true
26+
locations: classpath:db/migration
27+
schemas: public
28+
baseline-on-migrate: true # ★ 기존 스키마를 기준선으로 등록
29+
baseline-version: 1 # 기준선 버전(임의, 보통 1)
30+
baseline-description: "Baseline existing schema"
31+
2432
mail:
2533
host: smtp.gmail.com
2634
port: 587

gdgoc/src/main/resources/application-prod.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,14 @@ spring:
2121
hibernate:
2222
default_batch_fetch_size: 100
2323
time_zone: Asia/Seoul
24-
show-sql: true
24+
show-sql: false
2525
database-platform: org.hibernate.dialect.PostgreSQLDialect
26+
flyway:
27+
enabled: true
28+
baseline-on-migrate: true # 변경 확인 후 제거 예정
29+
clean-disabled: true
30+
validate-migration-naming: true
31+
locations: classpath:db/migration
2632
mail:
2733
host: smtp.gmail.com
2834
port: 587
@@ -38,7 +44,7 @@ spring:
3844
logging:
3945
level:
4046
org.hibernate.SQL: debug
41-
org.hibername.type: trace
47+
org.hibernate.type: off
4248

4349

4450
google:
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
DO $$
2+
DECLARE r record;
3+
BEGIN
4+
FOR r IN
5+
SELECT conname
6+
FROM pg_constraint c
7+
JOIN pg_class t ON t.oid = c.conrelid
8+
JOIN pg_namespace n ON n.oid = t.relnamespace
9+
WHERE t.relname = 'users'
10+
AND n.nspname = 'public'
11+
AND c.contype = 'c'
12+
AND pg_get_constraintdef(c.oid) ILIKE '%user_role%' -- user_role 관련 CHECK
13+
LOOP
14+
EXECUTE format('ALTER TABLE public.users DROP CONSTRAINT %I', r.conname);
15+
END LOOP;
16+
END $$;
17+
18+
ALTER TABLE public.users ALTER COLUMN user_role DROP DEFAULT;
19+
20+
ALTER TABLE public.users
21+
ALTER COLUMN user_role TYPE varchar(32)
22+
USING user_role::text;
23+
24+
25+
UPDATE public.users
26+
SET user_role = CASE user_role
27+
WHEN '0' THEN 'GUEST'
28+
WHEN '1' THEN 'MEMBER'
29+
WHEN '2' THEN 'ADMIN'
30+
ELSE user_role
31+
END;
32+
33+
-- 5) 새 디폴트/체크 제약조건 설정
34+
ALTER TABLE public.users ALTER COLUMN user_role SET DEFAULT 'GUEST';
35+
36+
ALTER TABLE public.users
37+
ADD CONSTRAINT users_user_role_check
38+
CHECK (user_role IN ('GUEST','MEMBER','ADMIN'));

gdgoc/src/test/java/inha/gdgoc/GdgocApplicationTests.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import org.junit.jupiter.api.Test;
44
import org.springframework.boot.test.context.SpringBootTest;
5+
import org.springframework.test.context.ActiveProfiles;
56

7+
@ActiveProfiles("test")
68
@SpringBootTest
79
class GdgocApplicationTests {
810

0 commit comments

Comments
 (0)