Skip to content

Commit

Permalink
Merge branch 'dev' into feat/#4/social-login
Browse files Browse the repository at this point in the history
  • Loading branch information
dudxo authored Aug 2, 2024
2 parents 271b595 + ad20e37 commit ff3ca70
Show file tree
Hide file tree
Showing 19 changed files with 517 additions and 1 deletion.
80 changes: 80 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
name: CD Backend

on:
push:
branches: [ "main", "dev" ]

permissions:
contents: read

jobs:
build-and-push-image:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3

# 자바 버전 설정
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

# yml 파일 생성
- name: Generate application.yml
run: |
mkdir -p ./src/main/resources
echo "${{ secrets.APPLICATION_YML }}" | base64 -d > ./src/main/resources/application.yml
# gradle 권한 부여
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
shell: bash

# 빌드 시 캐시 적용
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
# 빌드
- name: Build with Gradle
run: ./gradlew build -x test

# 도커 허브 로그인
- name: Docker Hub Login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

# 도커 이미지 빌드 및 푸시
- name: docker image build and push
run: |
docker build -f Dockerfile -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_APP_NAME }} .
docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_APP_NAME }}
deploy:
needs: build-and-push-image
runs-on: ubuntu-latest
steps:
# 서버 백그라운드 실행
- name: pull image and run container
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_KEY }}
port: ${{ secrets.EC2_PORT }}
script: |
cd compose
docker rm -f $(docker ps -qa)
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${{ secrets.DOCKERHUB_APP_NAME }}
docker-compose up -d
docker system prune -f
61 changes: 61 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: CI Backend

on:
pull_request:
branches: ["main", "dev"]

permissions:
contents: read
checks: write
pull-requests: write
jobs:
build:
runs-on: ubuntu-latest
env:
TZ: 'Asia/Seoul'
steps:
- uses: actions/checkout@v3

- name: Check the timezone
run: date

# 자바 버전 설정
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'

# gradle 권한 부여
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
shell: bash

# 빌드 시 캐시 적용
- name: Gradle Caching
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
# 빌드
- name: Build with Gradle
run: ./gradlew build

# 테스트 결과 PR 코멘트에 등록
- name: Register the test results as PR comments
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: '**/build/test-results/test/TEST-*.xml'

# 테스트 실패시 코드 라인에 대한 체크 추가
- name: If test fail, add check comment on failed code line
uses: mikepenz/action-junit-report@v3
if: always()
with:
report_paths: '**/build/test-results/test/TEST-*.html'
4 changes: 4 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM openjdk:17-jdk
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]
24 changes: 23 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,39 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'

runtimeOnly 'com.mysql:mysql-connector-j'

// lombok 설정
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok:1.18.22'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'

// JUnit
testImplementation "org.junit.jupiter:junit-jupiter:5.8.1"

// TestContainer
testImplementation "org.testcontainers:testcontainers:1.19.5"
testImplementation "org.testcontainers:junit-jupiter:1.19.5"
// mysql 컨테이너
testImplementation "org.testcontainers:mysql:1.19.2"

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'


/*JWT 관련 라이브러리*/
implementation 'io.jsonwebtoken:jjwt-api:0.12.3'
implementation 'io.jsonwebtoken:jjwt-impl:0.12.3'
implementation 'io.jsonwebtoken:jjwt-jackson:0.12.3'

implementation 'org.springframework.cloud:spring-cloud-starter-aws:2.2.6.RELEASE'

//spring bean validation
implementation 'org.springframework.boot:spring-boot-starter-validation'

}

tasks.named('test') {
Expand Down
8 changes: 8 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: "3"
services:
redis:
image: redis
container_name: gongmuin-redis
ports:
- "6379:6379"
restart: always
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dnd.gongmuin.common.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@Configuration
@EnableJpaAuditing
public class JpaAuditingConfig {
}
33 changes: 33 additions & 0 deletions src/main/java/com/dnd/gongmuin/common/config/S3Config.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.dnd.gongmuin.common.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.AWSStaticCredentialsProvider;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;

@Configuration
public class S3Config {

@Value("${cloud.aws.credentials.access-key}")
private String accessKey;

@Value("${cloud.aws.credentials.secret-key}")
private String secretKey;

@Value("${cloud.aws.region.static}")
private String region;

@Bean
public AmazonS3 amazonS3Client() {
AWSCredentials awsCredentials = new BasicAWSCredentials(accessKey, secretKey);
return AmazonS3ClientBuilder.standard()
.withRegion(region)
.withCredentials(new AWSStaticCredentialsProvider(awsCredentials))
.build();
}
}
43 changes: 43 additions & 0 deletions src/main/java/com/dnd/gongmuin/s3/controller/S3Controller.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package com.dnd.gongmuin.s3.controller;

import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.dnd.gongmuin.s3.dto.ImagesUploadRequest;
import com.dnd.gongmuin.s3.dto.ImagesUploadResponse;
import com.dnd.gongmuin.s3.dto.VideoUploadRequest;
import com.dnd.gongmuin.s3.dto.VideoUploadResponse;
import com.dnd.gongmuin.s3.service.S3Service;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/files")
public class S3Controller {

private final S3Service s3Service;

@PostMapping("/images")
public ResponseEntity<ImagesUploadResponse> uploadImages(
@ModelAttribute @Valid ImagesUploadRequest request
) {
List<String> imageUrls = s3Service.uploadImages(request.imageFiles());
return ResponseEntity.ok(ImagesUploadResponse.from(imageUrls));
}

@PostMapping("/videos")
public ResponseEntity<VideoUploadResponse> uploadVideo(
@ModelAttribute @Valid VideoUploadRequest request
) {
String videoUrl = s3Service.uploadVideo(request.videoFile());
return ResponseEntity.ok(VideoUploadResponse.from(videoUrl));
}

}
16 changes: 16 additions & 0 deletions src/main/java/com/dnd/gongmuin/s3/dto/ImagesUploadRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.dnd.gongmuin.s3.dto;

import java.util.List;

import org.springframework.web.multipart.MultipartFile;

import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record ImagesUploadRequest(

@NotNull(message = "이미지 파일은 필수 입력 항목입니다.")
@Size(min = 1, max = 10, message = "이미지는 1장 이상 10장 이하로 선택하세요.")
List<MultipartFile> imageFiles
) {
}
11 changes: 11 additions & 0 deletions src/main/java/com/dnd/gongmuin/s3/dto/ImagesUploadResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.dnd.gongmuin.s3.dto;

import java.util.List;

public record ImagesUploadResponse(
List<String> imageUrls
) {
public static ImagesUploadResponse from(List<String> imageUrls) {
return new ImagesUploadResponse(imageUrls);
}
}
11 changes: 11 additions & 0 deletions src/main/java/com/dnd/gongmuin/s3/dto/VideoUploadRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.dnd.gongmuin.s3.dto;

import org.springframework.web.multipart.MultipartFile;

import jakarta.validation.constraints.NotNull;

public record VideoUploadRequest(
@NotNull(message = "비디오 파일은 필수 입력 항목입니다.")
MultipartFile videoFile
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.dnd.gongmuin.s3.dto;

public record VideoUploadResponse(
String videoUrl
) {
public static VideoUploadResponse from(String videoUrl) {
return new VideoUploadResponse(videoUrl);
}
}
19 changes: 19 additions & 0 deletions src/main/java/com/dnd/gongmuin/s3/exception/S3ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.dnd.gongmuin.s3.exception;

import com.dnd.gongmuin.common.exception.ErrorCode;

import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public enum S3ErrorCode implements ErrorCode {
EMPTY_FILE_NAME("원본 파일명은 필수입니다.", "S3_001"),
INVALID_FILE_EXTENSION("잘못된 되었거나 지원하지 않는 파일 형식입니다.", "S3_002"),

FAILED_TO_UPLOAD("파일을 업로드하는데 실패했습니다.", "S3_003");


private final String message;
private final String code;
}
Loading

0 comments on commit ff3ca70

Please sign in to comment.