# CI/CD

WEB(API Server)은  IoT와 App과 **데이터를 주고받고** **저장**하는 역할을 하므로 다른 분야와의 협업과 연동을 위해서 API Server는 **빠르게 개발**되어야 하고 다른 분야에 제공하는 **API의 코드가 최신 상태**여야 한다. 따라서 아래와 같은 CI/CD 도구를 이용하여 협업 간의 효율을 높였다.

![Github Actions](https://2653380560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MKdTwUS64F4uZsg5UX2%2F-ML7433mEF14qs38ggkT%2F-ML74dBqPH0bUtMxIJjY%2F%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%2C%202020-11-02%2017-32-15.png?alt=media\&token=31d376f4-b9a6-4d64-bdf7-ba9a760c9fdb)

![AWS Code Deploy](https://2653380560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MKdTwUS64F4uZsg5UX2%2F-ML7433mEF14qs38ggkT%2F-ML74yICSI8PGakb-P5p%2F%EC%8A%A4%ED%81%AC%EB%A6%B0%EC%83%B7%2C%202020-11-02%2017-34-10.png?alt=media\&token=ffefce23-14c1-4ada-b4fd-8051e3075a9c)

## Github Actions

프로젝트에서 **Github Actions과 AWS CodeDeploy를** 이용하여 **CI(지속적 통합)/CD(지속적 제공)**&#xB97C; 적용하여 리포지토리에 **커밋과 동시에 빌드를 진행**하고 **PR의 머지**가 될 때 **원격 서버에 자동으로 배포**가 되게 하여 **짧은 주기**로 다른 분야 개발자들에게 제공하였다.

![CI/CD Pipeline](https://2653380560-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MKdTwUS64F4uZsg5UX2%2F-MKeYk579vNLM3JYSHEp%2F-MKeZ34vnQNr6wVso5U7%2F96108958-238d6480-0f19-11eb-916d-2a808083bd19.jpg?alt=media\&token=2b33d317-c43b-4a33-a21a-4f432a429e08)

1. **Github**에서 **push 이벤트가 발생**하면 **Github Actions**로 **trigger**를 한다.
2. **Github Actions**에서는 정해진 **Job**과 **Step**에 따라 빌드를 하고 소스 코드를 \***.jar** 파일로 만들어 소스 코드와 함께 압축하여 **AWS S3**에 저장한다.
3. **AWS CodeDeploy**에 배포 요정을 하면 **AWS S3**에 저장되어 있는 압축된 소스 코드와 \***.jar** 파일을 가져와 원격 서버(**AWS EC2**)에 배포한다.

## Github Actions workflow

### deploy.yml

```yaml
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle

name: Java CI with Gradle

env:
  PROJECT_NAME: WEB_KookMoBan_PonJohmNaimann
  
on:
  push:
    branches:
      - '*'         # matches every branch that doesn't contain a '/'
      - '*/*'       # matches every branch containing a single '/'
      - '**'        # matches every branch
    
jobs:
  deploy:
    name: DEPLOY
    runs-on: ubuntu-18.04

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

      - name: Set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

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

      - name: Build with Gradle
        run: ./gradlew build
        shell: bash

      - name: Make zip file
        run: zip -qq -r ./$GITHUB_SHA.zip .
        shell: bash

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      - name: Upload to S3
        run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://osam-s3/$PROJECT_NAME/$GITHUB_SHA.zip

      - name: Code Deploy
        run: aws deploy create-deployment --application-name OSAM_Hackathon --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name dev --s3-location bucket=osam-s3,bundleType=zip,key=$PROJECT_NAME/$GITHUB_SHA.zip

```

## AWS CodeDeploy

### appsepc.yml

```yaml
version: 0.0
os: linux

files:
  - source: /
    destination: /opt/OSAM_Hackathon
permissions:
  - object: /opt/OSAM_Hackathon/
    owner: ubuntu
    group: ubuntu
    mode: 755
hooks:
  AfterInstall:
    - location: deploy.sh
      timeout: 60
      runas: root
```

### deploy.sh

**AWS EC2**에서 현재 동작하고 있는 **Spring Boot Application**의 **PID**값을 찾아 종료하고 새로운 **Spring Boot Application**을 실행한다.

```bash
#!/usr/bin/env bash

REPOSITORY=/opt/OSAM_Hackathon
cd $REPOSITORY

APP_NAME=OSAM_Hackathon
JAR_NAME=$(ls $REPOSITORY/build/libs/ | grep '.jar' | tail -n 1)
JAR_PATH=$REPOSITORY/build/libs/$JAR_NAME

CURRENT_PID=$(pgrep -f $APP_NAME)

if [ -z $CURRENT_PID ]
then
  echo "> 종료할것 없음."
else
  echo "> kill -9 $CURRENT_PID"
  kill -15 $CURRENT_PID
  sleep 5
fi

echo "> $JAR_PATH 배포"
nohup java -jar $JAR_PATH > /dev/null 2> /dev/null < /dev/null &
```
