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
117 changes: 117 additions & 0 deletions .github/workflows/ci.yml
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
74 changes: 42 additions & 32 deletions gdgoc/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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'

//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()
}
2 changes: 2 additions & 0 deletions gdgoc/src/main/java/inha/gdgoc/config/DotenvLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import io.github.cdimascio.dotenv.Dotenv;
import jakarta.annotation.PostConstruct;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Component;

@Profile("!test")
@Component
public class DotenvLoader {

Expand Down
3 changes: 3 additions & 0 deletions gdgoc/src/main/java/inha/gdgoc/domain/user/entity/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
Expand Down Expand Up @@ -58,6 +60,7 @@ public class User extends BaseEntity {
@Column(name = "password", nullable = false)
private String password;

@Enumerated(EnumType.STRING)
@Column(name = "user_role", nullable = false)
private UserRole userRole;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

@Getter
public enum UserRole {
GUEST("Guest"),
MEMBER("Member"),
GUEST("GUEST"),
MEMBER("MEMBER"),
ADMIN("ADMIN");

private final String role;
Expand Down
10 changes: 9 additions & 1 deletion gdgoc/src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,20 @@ spring:
jpa:
database: postgresql
hibernate:
ddl-auto: update
ddl-auto: none
properties:
hibernate:
default_batch_fetch_size: 100
jdbc:
time_zone: Asia/Seoul
flyway:
enabled: true
locations: classpath:db/migration
schemas: public
baseline-on-migrate: true # ★ 기존 스키마를 기준선으로 등록
baseline-version: 1 # 기준선 버전(임의, 보통 1)
baseline-description: "Baseline existing schema"

mail:
host: smtp.gmail.com
port: 587
Expand Down
10 changes: 8 additions & 2 deletions gdgoc/src/main/resources/application-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
baseline-on-migrate: true # 변경 확인 후 제거 예정
clean-disabled: true
validate-migration-naming: true
locations: classpath:db/migration
mail:
host: smtp.gmail.com
port: 587
Expand All @@ -38,7 +44,7 @@ spring:
logging:
level:
org.hibernate.SQL: debug
org.hibername.type: trace
org.hibernate.type: off


google:
Expand Down
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'));
2 changes: 2 additions & 0 deletions gdgoc/src/test/java/inha/gdgoc/GdgocApplicationTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

@ActiveProfiles("test")
@SpringBootTest
class GdgocApplicationTests {

Expand Down
Loading
Loading