Skip to content

Commit

Permalink
Merge branch 'main' into feature/auth
Browse files Browse the repository at this point in the history
  • Loading branch information
devyubin committed Aug 12, 2023
2 parents d19258f + b168a33 commit c6faa34
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 39 deletions.
70 changes: 70 additions & 0 deletions .github/workflows/haemil-CICD.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: haemil CICD
run-name: Running
on:
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]

env:
AWS_REGION: ap-northeast-2
AWS_S3_BUCKET: haemil-deploy
AWS_CODE_DEPLOY_APPLICATION: haemil-cicd
AWS_CODE_DEPLOY_GROUP: haemil-cicd-deploy-group

permissions:
contents: read

jobs:
deploy:
name: Deploy
runs-on: ubuntu-latest
environment: production

steps:
# (1) 기본 체크아웃
- name: Checkout
uses: actions/checkout@v3

# (2) JDK 11 세팅
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: '11'
- name: Copy application-secret
env:
APPLICATION_SECRET: ${{ secrets.APPLICATION_SECRET }}
run: echo "$APPLICATION_SECRET" > src/main/resources/application-secret.yml

# (3) Gradle build (Test 제외)
- name: Build with Gradle
uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee
with:
arguments: clean build -x test

# (4) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용)
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.IAM_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.IAM_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}

# (5) 빌드 결과물을 S3 버킷에 업로드
- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.AWS_CODE_DEPLOY_APPLICATION }} \
--ignore-hidden-files \
--s3-location s3://$AWS_S3_BUCKET/$GITHUB_SHA.zip \
--source .
# (6) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행
- name: Deploy to AWS EC2 from S3
run: |
aws deploy create-deployment \
--application-name ${{ env.AWS_CODE_DEPLOY_APPLICATION }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.AWS_CODE_DEPLOY_GROUP }} \
--s3-location bucket=$AWS_S3_BUCKET,key=$GITHUB_SHA.zip,bundleType=zip
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ build/
!**/src/test/**/build/

### CUSTOM ###
application.yml
application-secret.yml

### STS ###
Expand Down
28 changes: 9 additions & 19 deletions appspec.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,23 @@
version: 0.0
os: linux
# 배포 파일 설정
## source: 인스턴스에 복사할 디렉터리 경로
## destination: 인스턴스에서 파일이 복사되는 위치
## overwrite: 복사할 위치에 파일이 있는 경우 대체

files:
- source: /
- source: /
destination: /home/ubuntu/app
overwrite: yes

# files 섹션에서 복사한 파일에 대한 권한 설정
## object: 권한이 지정되는 파일 또는 디렉터리
## pattern (optional): 매칭되는 패턴에만 권한 부여
## owner (optional): object 의 소유자
## group (optional): object 의 그룹 이름
permissions:
- object: /
pattern: "**"
owner: ubuntu
group: ubuntu
mode: 755
# 배포 이후에 실행할 일련의 라이프사이클
# 파일을 설치한 후 `AfterInstall` 에서 기존에 실행중이던 애플리케이션을 종료
# `ApplicationStart` 에서 새로운 애플리케이션을 실행
## location: hooks 에서 실행할 스크립트 위치
## timeout (optional): 스크립트 실행에 허용되는 최대 시간이며, 넘으면 배포 실패로 간주됨
## runas (optional): 스크립트를 실행하는 사용자

hooks:
AfterInstall:
# location은 프로젝트의 root경로를 기준
- location: scripts/deploy.sh
- location: scripts/stop.sh
timeout: 60
runas: ubuntu
ApplicationStart:
- location: scripts/start.sh
timeout: 60
runas: ubuntu
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,6 @@ dependencies {

}

tasks.named('test') {
useJUnitPlatform()
jar {
enabled = false
}
19 changes: 19 additions & 0 deletions scripts/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/spring-webapp.jar"

APP_LOG="$PROJECT_ROOT/application.log"
ERROR_LOG="$PROJECT_ROOT/error.log"
DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# build 파일 복사
echo "$TIME_NOW > $JAR_FILE 파일 복사" >> $DEPLOY_LOG
cp $PROJECT_ROOT/build/libs/*.jar $JAR_FILE

# jar 파일 실행
echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG
nohup java -jar $JAR_FILE > $APP_LOG 2> $ERROR_LOG &

CURRENT_PID=$(pgrep -f $JAR_FILE)
echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG
17 changes: 17 additions & 0 deletions scripts/stop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/spring-webapp.jar"

DEPLOY_LOG="$PROJECT_ROOT/deploy.log"

TIME_NOW=$(date +%c)

# 현재 구동 중인 애플리케이션 pid 확인
CURRENT_PID=$(pgrep -f $JAR_FILE)

# 프로세스가 켜져 있으면 종료
if [ -z $CURRENT_PID ]; then
echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG
else
echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG
kill -15 $CURRENT_PID
fi
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ public ResponseEntity<BaseResponse> sendGetRequest() {

try {
String jsonString = alertService.getAlertInfo(getApiDto);
log.debug("jsonString: "+jsonString);
// log.debug("jsonString: "+jsonString);
alertService.isJson(jsonString);

List<ApiInfoDto> infoList = alertService.ParsingJson(jsonString);
return new BaseResponse<>(infoList).convert();
ApiInfoDto apiInfoDto = alertService.ParsingJson(jsonString);
return new BaseResponse<>(apiInfoDto).convert();
} catch (BaseException e){
// 실패시 custom한 status로 code 헤더 설정, body로 메세지 반환
return new BaseResponse<>(e.getStatus()).convert();
Expand Down
53 changes: 39 additions & 14 deletions src/main/java/com/haemil/backend/alert/service/AlertService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,15 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.client.UnknownContentTypeException;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -38,28 +42,50 @@ public String getAlertInfo(GetApiDto reqGetApiDto) throws BaseException {
String pageNo = reqGetApiDto.getPageNo();
String numOfRows = reqGetApiDto.getNumOfRows();

log.debug("serviceKey: " + serviceKey);

StringBuilder urlBuilder = new StringBuilder(apiUrl);
urlBuilder.append("?" + URLEncoder.encode("ServiceKey", "UTF-8") + "=" + serviceKey);
urlBuilder.append("&" + URLEncoder.encode("type", "UTF-8") + "=" + URLEncoder.encode(type, "UTF-8"));
urlBuilder.append("&" + URLEncoder.encode("pageNo", "UTF-8") + "=" + URLEncoder.encode(pageNo, "UTF-8"));
urlBuilder.append("&" + URLEncoder.encode("numOfRows", "UTF-8") + "=" + URLEncoder.encode(numOfRows, "UTF-8"));

ResponseEntity<String> response = restTemplate.getForEntity(urlBuilder.toString(), String.class);
// log.debug("urlBuilder: {}", urlBuilder);

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Accept", "*/*;q=0.9"); // HTTP_ERROR 방지
HttpEntity<String> httpRequest = new HttpEntity<>(null, headers);
// log.debug("httpRequest = {}", httpRequest);

RestTemplate restTemplate = new RestTemplate();
// log.debug("restTemplate = {}", restTemplate);

responseBody = response.getBody();
HttpStatus httpStatus = null;
ResponseEntity<String> httpResponse = null;

URI uri = new URI(urlBuilder.toString()); // service key is not registered 오류 방지
// log.debug("uri = {}", uri);
httpResponse = restTemplate.exchange(uri, HttpMethod.GET, httpRequest, new ParameterizedTypeReference<String>(){});
// log.debug("httpResponse = {}", httpResponse);

if (httpResponse != null && httpResponse.getBody() != null) {
responseBody = httpResponse.getBody();
}
// log.debug("responseBody = {}",responseBody);

} catch (UnsupportedEncodingException e) { // 에러가 발생했을 때 예외 status 명시
log.debug("UnsupportedEncodingException 발생 ");
throw new BaseException(ResponseStatus.UNSUPPORTED_ENCODING);
} catch (URISyntaxException e) {
log.debug("URISyntaxException 발생 ");
throw new BaseException(ResponseStatus.UNSUPPORTED_ENCODING);
}

return responseBody;
}

public List<ApiInfoDto> ParsingJson(String responseBody) throws BaseException {
public ApiInfoDto ParsingJson(String responseBody) throws BaseException {
ApiInfoDto apiInfoDto;

List<ApiInfoDto> apiInfoDtoList;
try {
List<AlertApi> alertApiList = new ArrayList<>();
ObjectMapper objectMapper = new ObjectMapper();
Expand All @@ -72,8 +98,8 @@ public List<ApiInfoDto> ParsingJson(String responseBody) throws BaseException {
String msg = nextNode.get("msg").asText();
String location = nextNode.get("location_name").asText(); // 예시로 location_name을 사용하여 location 값을 가져옴

log.debug("msg: " + msg);
log.debug("location: " + location);
// log.debug("msg: " + msg);
// log.debug("location: " + location);

AlertApi alertApi = AlertApi.builder()
.msg(msg)
Expand All @@ -83,19 +109,18 @@ public List<ApiInfoDto> ParsingJson(String responseBody) throws BaseException {
alertApiList.add(alertApi);

// 변환된 데이터를 ApiInfoDto 형태로 리스트로 반환
apiInfoDtoList = new ArrayList<>();
apiInfoDto = new ApiInfoDto();

for (AlertApi a : alertApiList) {
ApiInfoDto apiInfoDto = new ApiInfoDto();
apiInfoDto.setMsg(a.getMsg());
apiInfoDto.setLocation(a.getLocation());
apiInfoDtoList.add(apiInfoDto);
}
log.debug("apiInfoDtoList: " + apiInfoDtoList);
// log.debug("apiInfoDto: " + apiInfoDto);

} catch (JsonProcessingException e) { // 에러가 발생했을 때 예외 status 명시
throw new BaseException(ResponseStatus.CANNOT_CONVERT_JSON);
}
return apiInfoDtoList;
return apiInfoDto;
}

public boolean isJson(String xmlString) throws BaseException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public enum ResponseStatus {
// --- 55x Custom Error --
CANNOT_CONVERT_JSON(false, 550, "JSON 문자열로 변경할 수 없습니다."),
UNSUPPORTED_ENCODING(false, 551, "지원되지 않는 인코딩 형식입니다."),
URI_SYNT(false, 551, "URISyntaxException이 발생했습니다."),
INVALID_XML_FORMAT(false, 552, "SERVICE ERROR가 발생했습니다."),
UNKNOWN_ADDR(false, 553, "알 수 없는 주소를 입력받았습니다.");

Expand Down
17 changes: 17 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# RDS Config
spring:
profiles:
include: secret
output:
ansi:
enabled: always

# Redis Config
redis:
host: 127.0.0.1
port: 6379

# logging
logging:
level:
com.haemil.backend: DEBUG

0 comments on commit c6faa34

Please sign in to comment.