Skip to content

Commit

Permalink
[FEATURE] Github Action 을 통한 CI/CD 구축 (#43)
Browse files Browse the repository at this point in the history
* refactor: 스프링 프로필 환경변수로 설정 (#36)

* feat: 운영, 개발 프로필 설정 (#36)

* refactor: 프로필별 설정 (#36)

* refactor: jpa properties 설정 (#36)

* refactor: h2-console URL 수정 (#36)

* refactor: JWT_SECRET 기본값 설정 (#36)

* refactor: 아카이브 파일 제외 (#36)

* chore: 깃허브 액션 ci/cd 작성 (#36)

* feat: Redis 서버 연결 실패 오류 핸들링 (#36)

* feat: Redis 서버 오류 핸들링 (#36)

* feat: Redis 컨테이너 설정 추가 (#36)

* feat: 스프링 프로필 설정 (#36)

* test: 깃허브 액션 테스트 (#36)

* test: 깃허브 액션 운영 테스트 (#36)

* test: 깃허브 액션 운영 테스트 완료 (#36)

* docs: README 수정 (#36)

* chore: 버전 수정 (#36)

---------

Co-authored-by: hyunmin0317 <choihm9903@naver.com>
  • Loading branch information
hyunmin0317 and hyunmin0317 authored Sep 8, 2024
1 parent c81a2e6 commit 28fda71
Show file tree
Hide file tree
Showing 13 changed files with 223 additions and 16 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/dev_cicd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Dev CI/CD

on:
push:
branches:
- develop

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '17'

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew clean build
env:
SPRING_PROFILE: dev
JWT_SECRET: ${{ secrets.JWT_SECRET }}
DB_URL: ${{ secrets.DB_URL }}
DB_USERNAME: ${{ secrets.DB_USERNAME }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
REDIS_URL: ${{ secrets.REDIS_URL }}
REDIS_PORT: ${{ secrets.REDIS_PORT }}

- name: Get current time
uses: josStorer/get-current-time@v2.0.2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss
utcOffset: "+09:00"

- name: Set artifact
run: echo "artifact=$(ls ./build/libs)" >> $GITHUB_ENV

- name: Beanstalk Deploy
uses: einaregilsson/beanstalk-deploy@v20
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: jwt-dev
environment_name: jwt-dev-env
version_label: github-action-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: ./build/libs/${{env.artifact}}
55 changes: 55 additions & 0 deletions .github/workflows/release_cicd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Release CI/CD

on:
push:
branches:
- main

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Set up JDK 17
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '17'

- name: Grant execute permission for gradlew
run: chmod +x gradlew

- name: Build with Gradle
run: ./gradlew clean build
env:
SPRING_PROFILE: release
JWT_SECRET: ${{ secrets.JWT_SECRET }}
DB_URL: ${{ secrets.DB_URL }}
DB_USERNAME: ${{ secrets.DB_USERNAME }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
REDIS_URL: ${{ secrets.REDIS_URL }}
REDIS_PORT: ${{ secrets.REDIS_PORT }}

- name: Get current time
uses: josStorer/get-current-time@v2.0.2
id: current-time
with:
format: YYYY-MM-DDTHH-mm-ss
utcOffset: "+09:00"

- name: Set artifact
run: echo "artifact=$(ls ./build/libs)" >> $GITHUB_ENV

- name: Beanstalk Deploy
uses: einaregilsson/beanstalk-deploy@v20
with:
aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
application_name: jwt-release
environment_name: jwt-release-env
version_label: github-action-${{steps.current-time.outputs.formattedTime}}
region: ap-northeast-2
deployment_package: ./build/libs/${{env.artifact}}
4 changes: 0 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -483,8 +483,4 @@ gradle-app.setting
# Java heap dump
*.hprof

# yml files
application-*.yml
!application-local.yml

# End of https://www.toptal.com/developers/gitignore/api/macos
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
# Spring Boot JWT

> Spring Boot, Spring Security를 이용한 JWT 인증·인가 서버 템플릿
## ⚒️ Tech Stack

* #### Backend
<img src="https://img.shields.io/badge/Java-17-007396?style=round-square&logo=oracle&logoColor=white"/>
<img src="https://img.shields.io/badge/Spring-6DB33F?style=round-square&logo=Spring&logoColor=white"/>
<img src="https://img.shields.io/badge/Spring%20Boot-6DB33F?style=round-square&logo=springboot&logoColor=white"/>
<img src="https://img.shields.io/badge/Spring%20Security-6DB33F?style=round-square&logo=SpringSecurity&logoColor=white"/>

* #### Build Tool
<img src="https://img.shields.io/badge/Gradle-02303A?style=round-square&logo=Gradle&logoColor=white"/>

* #### DBMS
<img src="https://img.shields.io/badge/MySQL-4479A1?style=round-square&logo=MySQL&logoColor=white"/>

* #### CI/CD
<img src="https://img.shields.io/badge/Git-F05032?style=round-square&logo=Git&logoColor=white"/>
<img src="https://img.shields.io/badge/GitHub-181717?style=round-square&logo=github&logoColor=white"/>
<img src="https://img.shields.io/badge/GitHub Actions-2088FF?style=round-square&logo=githubactions&logoColor=white"/>
<img src="https://img.shields.io/badge/Docker-2496ED?style=round-square&logo=docker&logoColor=white"/>

* #### Deploy
<img src="https://img.shields.io/badge/AWS-232F3E?style=round-square&logo=amazonwebservices&logoColor=white"/>
<img src="https://img.shields.io/badge/EC2-FF9900?style=round-square&logo=amazonec2&logoColor=white"/>
<img src="https://img.shields.io/badge/RDS-527FFF?style=round-square&logo=amazonrds&logoColor=white"/>
<img src="https://img.shields.io/badge/Elastic Beanstalk-FF9900?style=round-square&logo=awselasticloadbalancing&logoColor=white"/>
6 changes: 5 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ plugins {
}

group = 'com.hyunmin'
version = '0.0.1-SNAPSHOT'
version = '1.0.0'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

jar {
enabled = false
}

configurations {
compileOnly {
extendsFrom annotationProcessor
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:latest
container_name: jwt-redis
ports:
- "6379:6379"
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ public enum ErrorCode {

// Member Errors
MEMBER_FORBIDDEN(403, "MEMBER001", "사용자 권한이 없습니다."),
MEMBER_NOT_FOUND(404, "MEMBER002", "해당 사용자가 없습니다.");
MEMBER_NOT_FOUND(404, "MEMBER002", "해당 사용자가 없습니다."),

// Redis Errors
REDIS_CONNECTION_FAILURE(500, "REDIS001", "Redis 서버에 연결할 수 없습니다."),
REDIS_SYSTEM_EXCEPTION(500, "REDIS002", "Redis 시스템 예외가 발생했습니다.");

private final int value;
private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.RedisSystemException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
Expand Down Expand Up @@ -51,6 +53,22 @@ protected ResponseEntity<ErrorResponse<Void>> handleHandlerMethodValidationExcep
return ErrorResponse.handle(errorCode);
}

// Redis 서버 연결 실패(RedisConnectionFailureException) 처리 메서드
@ExceptionHandler(RedisConnectionFailureException.class)
protected ResponseEntity<ErrorResponse<Void>> handleRedisConnectionFailureException(RedisConnectionFailureException ex) {
log.warn("[WARNING] {} : {}", ex.getClass(), ex.getMessage());
ErrorCode errorCode = ErrorCode.REDIS_CONNECTION_FAILURE;
return ErrorResponse.handle(errorCode);
}

// Redis 서버 오류(REDIS_SYSTEM_EXCEPTION) 처리 메서드
@ExceptionHandler(RedisSystemException.class)
protected ResponseEntity<ErrorResponse<Void>> handleRedisSystemException(RedisSystemException ex) {
log.warn("[WARNING] {} : {}", ex.getClass(), ex.getMessage());
ErrorCode errorCode = ErrorCode.REDIS_SYSTEM_EXCEPTION;
return ErrorResponse.handle(errorCode);
}

// 기타 모든 예외(Exception) 처리 메서드
@ExceptionHandler(Exception.class)
protected ResponseEntity<ErrorResponse<Void>> handleException(Exception ex) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import com.hyunmin.jwt.global.security.handler.JwtAuthenticationEntryPoint;
import com.hyunmin.jwt.global.security.provider.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.security.servlet.PathRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
Expand Down Expand Up @@ -51,8 +50,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 경로별 인가 작업
http.authorizeHttpRequests(authorize -> authorize
// H2 콘솔과 Swagger UI 및 API 문서에 대한 접근 허용
.requestMatchers(PathRequest.toH2Console()).permitAll()
.requestMatchers("/swagger-ui/**", "/v3/api-docs/**").permitAll()
.requestMatchers("/h2-console/**", "/swagger-ui/**", "/v3/api-docs/**").permitAll()
// API 계정 관련 요청에 대한 접근 허용
.requestMatchers("/api/v1/accounts/**").permitAll()
// 전체 사용자 정보 조회 API 관리자 권한만 접근 허용
Expand Down
21 changes: 21 additions & 0 deletions src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
spring:
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver

data:
redis:
host: ${REDIS_URL}
port: ${REDIS_PORT}

jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQLDialect
show_sql: true
format_sql: true

hibernate:
ddl-auto: update
11 changes: 6 additions & 5 deletions src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ spring:
password:
driver-class-name: org.h2.Driver

h2:
console:
enabled: true

jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
show_sql: true
format_sql: true

h2:
console:
enabled: true
hibernate:
ddl-auto: update
21 changes: 21 additions & 0 deletions src/main/resources/application-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
spring:
datasource:
url: ${DB_URL}
username: ${DB_USERNAME}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver

data:
redis:
host: ${REDIS_URL}
port: ${REDIS_PORT}

jpa:
properties:
hibernate:
dialect: org.hibernate.dialect.MySQLDialect
show_sql: true
format_sql: true

hibernate:
ddl-auto: none
4 changes: 2 additions & 2 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
spring:
profiles:
active: local
active: ${SPRING_PROFILE:local}

jwt:
secret: ${JWT_SECRET}
secret: ${JWT_SECRET:secret}
token:
access-expiration-time: 1800 # 30 minutes
refresh-expiration-time: 1209600 # 14 days

0 comments on commit 28fda71

Please sign in to comment.