Skip to content

Commit

Permalink
Merge pull request #1 from Central-MakeUs/spec/v1
Browse files Browse the repository at this point in the history
v1 스펙 1차 배포
  • Loading branch information
wwingyou authored Jan 11, 2025
2 parents d6de602 + a046f1c commit d26f521
Show file tree
Hide file tree
Showing 16 changed files with 1,733 additions and 53 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Deploy Java Application to EC2

on:
push:
branches:
- dev # Trigger on pushes to the main branch

jobs:
deploy:
runs-on: ubuntu-latest

steps:
# Step 1: Check out the repository
- name: Checkout Code
uses: actions/checkout@v3

# Step 2: Set up Java environment
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17' # Adjust based on your project requirements

- name: Test Project
run: |
./gradlew test
# Step 3: Build the application
- name: Build JAR
run: |
./gradlew clean build
# Step 4: Transfer the JAR to the EC2 instance
- name: Transfer JAR to EC2
env:
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
scp -i <(echo "$EC2_SSH_KEY") -o StrictHostKeyChecking=no \
build/libs/api-0.0.1-SNAPSHOT.jar $EC2_USER@$EC2_HOST:/home/$EC2_USER/
# TODO: The name of jar file might change. Need other way to handle this.
# Step 5: Deploy the application on the EC2 instance
- name: Deploy Application on EC2
env:
EC2_SSH_KEY: ${{ secrets.EC2_SSH_KEY }}
EC2_USER: ${{ secrets.EC2_USER }}
EC2_HOST: ${{ secrets.EC2_HOST }}
run: |
ssh -i <(echo "$EC2_SSH_KEY") -o StrictHostKeyChecking=no \
$EC2_USER@$EC2_HOST << EOF
pkill -f api-0.0.1-SNAPSHOT.jar || true
nohup java -jar /home/$EC2_USER/your-application.jar > app.log 2>&1 &
EOF
39 changes: 23 additions & 16 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.7'
id 'java'
id 'org.springframework.boot' version '3.4.1'
id 'io.spring.dependency-management' version '1.1.7'
id 'org.hidetake.swagger.generator' version '2.19.2'
}

group = 'com.goolbitg'
version = '0.0.1-SNAPSHOT'

processResources {
dependsOn(generateSwaggerCode)
}

swaggerSources {
def typeMappings = 'URI=URI'
def importMappings = 'URI=java.net.URI'
Expand All @@ -24,7 +20,7 @@ swaggerSources {
language = 'spring'
configFile = file(configJson)
rawOptions = ['--ignore-file-override', ignoreFile, '--type-mappings',
typeMappings, '--import-mappings', importMappings] as List<String>
typeMappings, '--import-mappings', importMappings] as List<String>
components = [models: true, apis: true, supportingFiles: 'ApiUtil.java']
dependsOn validation
}
Expand All @@ -36,21 +32,22 @@ sourceSets.main.java.srcDir "${swaggerSources.goolbitg.code.outputDir}/src/main/
sourceSets.main.resources.srcDir "${swaggerSources.goolbitg.code.outputDir}/src/main/resources"

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

repositories {
mavenCentral()
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
swaggerCodegen 'org.openapitools:openapi-generator-cli:6.2.1'
swaggerUI 'org.webjars:swagger-ui:3.52.5'
compileOnly 'io.swagger:swagger-annotations:1.6.4'
compileOnly 'org.springframework.boot:spring-boot-starter-validation'
compileOnly 'org.openapitools:jackson-databind-nullable:0.2.3'
Expand All @@ -60,5 +57,15 @@ dependencies {
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
}

build.dependsOn generateSwaggerUI

processResources {
dependsOn generateSwaggerCode
dependsOn generateSwaggerUI
from("${swaggerSources.goolbitg.ui.outputDir}") {
into 'static/swagger-ui'
}
}
5 changes: 5 additions & 0 deletions docs/errors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# 굴비잇기 에러코드 목록

## 인증 오류 (10)

## 로그인 & 회원가입 오류 (20)
40 changes: 40 additions & 0 deletions docs/log/2025-01-07-spec-v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
## 오늘의 작업

- [x] 인증 관련 엔드포인트 스펙 작성
- [x] 에러코드 규칙 정의
- [x] Swagger Codegen 스텁 활성화

## 회고

볼륨이 커지다보니 점점 스펙 작성 속도가 느려지는것이 보인다. 앞으로의 엔드포인트
스펙 작성에 있어서 결정해야 할 사항들이 몇가지 있다.

1. 모든 엔드포인트 요청, 응답에 대한 스키마를 작성해야 하는가? 한다면 이름
형식은 어떻게?
2. 응답 부분에서 가능한 모든 예외 응답 케이스를 적어줘야 하는가? 모든걸 다
적는다고 하면 앞으로 쓸 거의 모든 엔드포인트에는 400, 401, 403, 500 에러가
필수적으로 포함될 예정이다.
-> 서버오류나 인풋 밸리데이션 오류는 굳이 포함시키지 않아도 될 것 같다. 거의
모든 엔드포인트에 적용 가능한 오류들은 빼고, 유니크한 경우에만 적어주도록
하자.
3. 스키마 프로퍼티에 여러가지 제약사항을 걸어도 코드 생성시에 따로 밸리데이션이
추가되는건 아닌 모양이다. 어쩌면 밸리데이션 설정을 해줄 수도 있을것 같은데,
일단은 그냥 넘어가야겠다.
4. 등록 스키마와 응답 스키마의 속성값들의 통일을 좀 주고 싶은데, 지금으로써는
각 속성마다 재사용 스키마를 따로 정의해주는 방법이 유일해 보인다. 그런데
그렇게 했다가는 스키마 양이 어마어마해질 것 같아 좀 꺼려진다.
5. 실패한 요청에 대해 202 상태코드를 발생시키는건 적절해보이지 않는다.
클라이언트에서 보낸 요청이 유효하지 않아 발생하는 케이스에 대해서는 무조건
400번대 응답을 보내는 것이 맞는것 같다. 422 Unprocessable Entity 상태코드가
지금의 애매한 부분들을 해결해줄 것 같다. 500번대 에러는 말 그대로 서버가 터진
것이니 의도적으로 500번 에러를 발생시키는 일은 없어야 할 것이다.
6. request, response들도 모두 컴포넌트화 해야하는가? 이건 코드젠에서 따로
클래스를 생성하는 부분도 아니라서 재사용될것 같지 않다면 그냥 paths 정의에
적는게 좋을지도?

내일은 스키마들 이름만 보고도 어떤 용도로 사용하는지 알 수 있도록 작명 규칙을 좀
정의해야겠다. Req, Res 서픽스를 작성하는 것이 가장 좋아보이긴 하는데, 등록 폼의
경우에는 Req 서픽스가 그닥 잘 맞아보이지 않는다. Form 도 괜찮다.

내일 스펙 작성 마무리하고, Swagger UI 설정까지 마무리할 수 있으면 좋겠다. 그리고
다음날 배포랑 CI/CD 구축해놓으면 기본 스펙과 스텁까지 딱 마무리할 수 있다.
6 changes: 6 additions & 0 deletions docs/log/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# 개발일지

개발일지를 적어두는 곳입니다.

일지 이름 형식은 다음과 같습니다.
`yyyy-MM-dd-<branch>.md`
21 changes: 21 additions & 0 deletions src/main/java/com/goolbitg/api/controllers/AuthController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.AuthApi;

/**
* AuthController
*/
@RestController
public class AuthController implements AuthApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
21 changes: 21 additions & 0 deletions src/main/java/com/goolbitg/api/controllers/BuyOrNotController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.BuyOrNotApi;

/**
* BuyOrNotController
*/
@RestController
public class BuyOrNotController implements BuyOrNotApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.ChallengeApi;

/**
* ChallengeController
*/
@RestController
public class ChallengeController implements ChallengeApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.ChallengeGroupApi;

/**
* ChallengeGroupController
*/
@RestController
public class ChallengeGroupController implements ChallengeGroupApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.ChallengeGroupRecordApi;

/**
* ChallengeGroupRecordController
*/
@RestController
public class ChallengeGroupRecordController implements ChallengeGroupRecordApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.ChallengeRecordApi;

/**
* ChallengeRecordController
*/
@RestController
public class ChallengeRecordController implements ChallengeRecordApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
30 changes: 30 additions & 0 deletions src/main/java/com/goolbitg/api/controllers/ControllerUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.request.ServletWebRequest;

/**
* ControllerUtils
*/
public class ControllerUtils {

public static Optional<NativeWebRequest> getRequest() {
ServletRequestAttributes attributes =
(ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

if (attributes != null) {
HttpServletRequest servletRequest = attributes.getRequest();
HttpServletResponse servletResponse = attributes.getResponse();
return Optional.of(new ServletWebRequest(servletRequest, servletResponse));
}
return Optional.empty();
}

}
21 changes: 21 additions & 0 deletions src/main/java/com/goolbitg/api/controllers/ImageController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.ImageApi;

/**
* ImageController
*/
@RestController
public class ImageController implements ImageApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
21 changes: 21 additions & 0 deletions src/main/java/com/goolbitg/api/controllers/UserController.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.goolbitg.api.controllers;

import java.util.Optional;

import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.NativeWebRequest;

import com.goolbitg.api.UserApi;

/**
* UserController
*/
@RestController
public class UserController implements UserApi {

@Override
public Optional<NativeWebRequest> getRequest() {
return ControllerUtils.getRequest();
}

}
Loading

0 comments on commit d26f521

Please sign in to comment.