diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 0000000..35bfbac --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,43 @@ +name: CD + +on: + push: + branches: [ main ] + +jobs: + deploy: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to Amazon ECR + uses: aws-actions/amazon-ecr-login@v2 + + - name: Build Docker image + run: | + docker build -t focussu-backend:latest ./backend + docker tag focussu-backend:latest ${{ secrets.ECR_REPO_URI }}:latest + + - name: Push Docker image + run: docker push ${{ secrets.ECR_REPO_URI }}:latest + + - name: Run deploy script + run: bash ./deploy/deploy-prod.sh + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: ap-northeast-2 + BACKEND_IMAGE: ${{ secrets.ECR_REPO_URI }}:latest + SPRING_PROFILES_ACTIVE: prod + RDS_ENDPOINT: ${{ secrets.RDS_ENDPOINT }} + RDS_PORT: ${{ secrets.RDS_PORT }} + RDS_DATABASE: ${{ secrets.RDS_DATABASE }} + RDS_USER: ${{ secrets.RDS_USER }} + RDS_PASSWORD: ${{ secrets.RDS_PASSWORD }} + KAFKA_BOOTSTRAP_SERVERS: ${{ secrets.KAFKA_BOOTSTRAP_SERVERS }} + diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..177a381 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,29 @@ +name: CI + +on: + pull_request: + branches: [ main ] + +jobs: + build-only: + runs-on: ubuntu-latest + + defaults: + run: + working-directory: ./backend + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: 17 + distribution: temurin + + - name: Grant execute permission to Gradle wrapper + run: chmod +x gradlew + + - name: Build without tests + run: ./gradlew build -x test --no-daemon diff --git a/.gitignore b/.gitignore index 9b16662..c5493ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # === Secret Config Files (DO NOT COMMIT) === /.env /backend/src/main/resources/application-secret.yml +/backend/src/main/resources/application-dev.yml /backend/.idea/ diff --git a/backend/Dockerfile b/backend/Dockerfile index 414fcae..8c9d99a 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -10,5 +10,5 @@ RUN gradle clean build -x test --no-daemon FROM openjdk:17-slim WORKDIR /app COPY --from=builder /app/build/libs/*.jar app.jar -EXPOSE 8080 +EXPOSE 80 ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/backend/src/main/java/com/focussu/backend/common/BaseEntity.java b/backend/src/main/java/com/focussu/backend/common/BaseEntity.java index f83ef01..35b443e 100644 --- a/backend/src/main/java/com/focussu/backend/common/BaseEntity.java +++ b/backend/src/main/java/com/focussu/backend/common/BaseEntity.java @@ -3,6 +3,7 @@ import jakarta.persistence.Column; import jakarta.persistence.MappedSuperclass; import lombok.Getter; +import lombok.Setter; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.UpdateTimestamp; @@ -10,6 +11,7 @@ @MappedSuperclass @Getter +@Setter public abstract class BaseEntity { @CreationTimestamp diff --git a/backend/src/main/java/com/focussu/backend/config/SwaggerConfig.java b/backend/src/main/java/com/focussu/backend/config/SwaggerConfig.java index 5751030..041d08b 100644 --- a/backend/src/main/java/com/focussu/backend/config/SwaggerConfig.java +++ b/backend/src/main/java/com/focussu/backend/config/SwaggerConfig.java @@ -17,12 +17,12 @@ public class SwaggerConfig { @Bean public OpenAPI openAPI() { Server localServer = new Server() - .url("http://localhost:8080") + .url("http://localhost:80") .description("Local 서버"); Server prodServer = new Server() - .url("https://focussu-api.life") - .description("개발 서버"); + .url("https://focussu-api.com") + .description("프로덕션 서버"); // Bearer 토큰을 위한 스키마 설정 SecurityScheme bearerScheme = new SecurityScheme() diff --git a/backend/src/main/java/com/focussu/backend/studyroom/service/StudyRoomQueryService.java b/backend/src/main/java/com/focussu/backend/studyroom/service/StudyRoomQueryService.java index a9f6edc..f1b2543 100644 --- a/backend/src/main/java/com/focussu/backend/studyroom/service/StudyRoomQueryService.java +++ b/backend/src/main/java/com/focussu/backend/studyroom/service/StudyRoomQueryService.java @@ -13,8 +13,9 @@ public class StudyRoomQueryService { private final StudyRoomRepository studyRoomRepository; public StudyRoomCreateResponse getStudyRoom(Long id) { + // TODO: 예외 커스텀 StudyRoom studyRoom = studyRoomRepository.findById(id) - .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 회원입니다.")); + .orElseThrow(() -> new IllegalArgumentException("존재하지 않는 스터디룸입니다.")); return StudyRoomCreateResponse.from(studyRoom); } } diff --git a/backend/src/main/resources/application-dev.yml b/backend/src/main/resources/application-dev.yml index 10f8528..2632746 100644 --- a/backend/src/main/resources/application-dev.yml +++ b/backend/src/main/resources/application-dev.yml @@ -1,15 +1,16 @@ +# src/main/resources/application-dev.yml + server: - port: 8080 + port: 80 spring: - config: - import: optional:classpath:application-secret.yml - application: name: focussu-backend datasource: url: jdbc:mysql://focussu-mysql:3306/focussu-db?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true + username: admin + password: wlqwndgo1! driver-class-name: com.mysql.cj.jdbc.Driver jpa: @@ -31,14 +32,14 @@ spring: listener: missing-topics-fatal: false - data: - redis: - port: 6379 - host: redis - springdoc: default-produces-media-type: application/json api-docs: resolve-schema-properties: true swagger-ui: path: /docs + +security: + jwt: + secret-key: de740246db0e808088253b1bbd8afb062dfcf5e661f20cb41cc7283366d1d8fcccbdbacf3ef8af9ac7159c9ac3a4302fc2321dba0d510a5695a62dd9728ea1ade417542d25e6d80312bc66b13852621f3be0a0188c9e122fedb30186455a4ee2f6ad6bf6daac10db65e9386f3bdf099bee7a18f2e1ef572ab212d7c3a87248d5f1e55243559adfc539df7a2d9110840a825ef27d14899ce630eed7e5366485b642d0f516f468b20af3a6bd67051f00be7a27f122c785f80091bcff6e510330a6f3f30629397a4439281559647cd9c6922d560fd2bd158b527357ff01377eb5333ea9e77f48908b9f96781eaa0fc5f67e7fa4d54d6088ef26c61e43ffb647412b + expiration-time: 86400 \ No newline at end of file diff --git a/backend/src/main/resources/application-prod.yml b/backend/src/main/resources/application-prod.yml new file mode 100644 index 0000000..2bad4c7 --- /dev/null +++ b/backend/src/main/resources/application-prod.yml @@ -0,0 +1,40 @@ +# src/main/resources/application-prod.yml + +spring: + config: + import: optional:application-secret.yml + + application: + name: focussu-backend + + datasource: + url: jdbc:mysql://${RDS_ENDPOINT}:${RDS_PORT}/${RDS_DATABASE}?serverTimezone=UTC + driver-class-name: com.mysql.cj.jdbc.Driver + + jpa: + hibernate: + ddl-auto: none + show-sql: false + properties: + hibernate: + dialect: org.hibernate.dialect.MySQL8Dialect + + kafka: + bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS} + properties: + security.protocol: SSL + +server: + port: 80 + +springdoc: + default-produces-media-type: application/json + api-docs: + resolve-schema-properties: true + swagger-ui: + path: /docs + +security: + jwt: + secret-key: ${JWT_SECRET_KEY} + expiration-time: ${JWT_EXPIRATION_TIME} \ No newline at end of file diff --git a/backend/src/main/resources/application.yml b/backend/src/main/resources/application.yml new file mode 100644 index 0000000..ca99e19 --- /dev/null +++ b/backend/src/main/resources/application.yml @@ -0,0 +1,7 @@ +# src/main/resources/application.yml + +spring: + profiles: + active: prod + config: + import: optional:classpath:application-secret.yml