name: CI-CD
# 어떤 브랜치에 push시 github action CI를 동작시킬지
on:
push:
branches:
# - dev
- release/1.0.0
# 환경 변수 설정
# 생성한 Code Deploy와 S3의 이름을 설정한다.
env:
CONTEXT: dev
S3_BUCKET_NAME: s3-42partner-dev
RESOURCE_PATH: ./module-api/src/main/resources/application.yml
CODE_DEPLOY_APPLICATION_NAME: 42partner-CODE-DEPLOY
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: 42partner-CODE-DEPLOY-GROUP
# push 시 수행할 일들 정의
jobs:
build:
# 실행 환경 이미지
runs-on: ubuntu-latest
# 각 실행 스텝을 정의해준다.
# name은 실행 스텝의 이름으로 출력된다.
# uses는 github action의 특정한 action을 실행시키는 것이다.
# run은 커맨드를 실행시킨다.
# with는 uses에서 사용할 변수를 지정해준다.
# GitHub Actions 입장에서 바라보면 GitHub의 코드 저장소에 올려둔 코드를
# CI 서버로 내려받은 후에 특정 브랜치로 전환하는 행위
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
# github action에 secret으로 application.yml을 올려두고 빌드시 활용할 수 있도록 복사해준다.
- run: mkdir ./module-api/src/main/resources
- run: touch ./module-api/src/main/resources/application.yml
- run: echo "${{ secrets.APPLICATION_DEV }}" > ./module-api/src/main/resources/application.yml
- run: cat ./module-api/src/main/resources/application.yml
- name: Grant execute permission for gradlew
run: chmod +x ./module-api/gradlew
shell: bash
# jar파일을 빌드한다.
- name: Build with Gradle
run: ./module-api/gradlew build -x test -Pprofile=${{ env.CONTEXT }}
shell: bash
- name: Make zip file
run: zip -r ./$GITHUB_SHA .
shell: bash
# AWS 계정의 key값을 입력하여 aws 커맨드를 사용할 수 있게 설정한다.
- 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: ${{ secrets.AWS_REGION }}
# S3에 빌드된 파일을 전송해준다.
- name: Upload to S3
run: aws s3 cp --region ${{ secrets.AWS_REGION }} ./$GITHUB_SHA.zip s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip
# Code deploy에게 S3에 저장된 빌드파일을 배포하도록 명령 내린다.
- name: Code Deploy
run: |
aws deploy create-deployment \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$GITHUB_SHA.zip
version: 0.0
os: linux
# 파일의 source경로와 EC2내의 경로를 입력하고 파일이 중첩될 시 어떤 행동을 취할지 설정한다.
files:
- source: /
destination: /home/ec2-user/app/42Partner-Backend
overwrite: yes
# 위에서 overwrite를 yes로 하더라도 파일이 중첩되면 배포가 실패할 수 있으므로 꼭 따로 또 설정한다.
file_exists_behavior: OVERWRITE
permissions:
- object: /
pattern: "**"
owner: ec2-user
group: ec2-user
hooks:
ApplicationStart:
# 배포 스크립트로 다음 스크립트를 활용한다.
- location: scripts/gh_deploy.sh
timeout: 60
runas: root
#!/bin/bash
PROJECT_PATH="/home/ec2-user/app/42Partner-Backend"
MODULE_NAME="module-api"
CONTEXT="dev"
JAR_PATH="$PROJECT_PATH/$MODULE_NAME/build/libs/*.jar"
DEPLOY_PATH=$PROJECT_PATH/$MODULE_NAME
DEPLOY_LOG_PATH="$PROJECT_PATH/$MODULE_NAME/deploy.log"
DEPLOY_ERR_LOG_PATH="$PROJECT_PATH/$MODULE_NAME/deploy_err.log"
APPLICATION_LOG_PATH="$PROJECT_PATH/$MODULE_NAME/application.log"
BUILD_JAR=$(ls $JAR_PATH)
JAR_NAME=$(basename $BUILD_JAR)
echo "===== 배포 시작 : $(date +%c) =====" >> $DEPLOY_LOG_PATH
echo "> build 파일명: $JAR_NAME" >> $DEPLOY_LOG_PATH
echo "> build 파일 복사" >> $DEPLOY_LOG_PATH
cp $BUILD_JAR $DEPLOY_PATH
echo "> 현재 동작중인 어플리케이션 pid 체크" >> $DEPLOY_LOG_PATH
CURRENT_PID=$(pgrep -f $JAR_NAME)
if [ -z $CURRENT_PID ]
then
echo "> 현재 동작중인 어플리케이션 존재 X" >> $DEPLOY_LOG_PATH
else
echo "> 현재 동작중인 어플리케이션 존재 O" >> $DEPLOY_LOG_PATH
echo "> 현재 동작중인 어플리케이션 강제 종료 진행" >> $DEPLOY_LOG_PATH
echo "> kill -9 $CURRENT_PID" >> $DEPLOY_LOG_PATH
kill -9 $CURRENT_PID
fi
# spring.profiles.active는 application.yml에 명시하고 빌드시에 이미 포함됨.
DEPLOY_JAR="$DEPLOY_PATH/build/libs/$JAR_NAME"
echo "> DEPLOY_JAR 배포" >> $DEPLOY_LOG_PATH
nohup java -jar $DEPLOY_JAR >> $APPLICATION_LOG_PATH 2> $DEPLOY_ERR_LOG_PATH &
sleep 3
echo "> 배포 종료 : $(date +%c)" >> $DEPLOY_LOG_PATH
Blue-Green 배포는 기존의 배포 그룹(Blue group)을 그대로 유지한 상태로 새로운 버전의 배포 그룹(Green Gruop)을 같은 instance개수로 생성한 후 한번에 트래픽을 Blue에서 Green으로 전환하는 방법이다.
무중단 배포의 방법은 Blue-Green 외에도 Rolling, Canary deploy등이 있지만 Blue-Green을 선택한 이유는 다음과 같다.
name: CI-CD
on:
push:
branches:
# - dev
- main
env:
CONTEXT: prod
S3_BUCKET_NAME: partner-cicd-s3
RESOURCE_PATH: ./module-api/src/main/resources/application.yml
CODE_DEPLOY_APPLICATION_NAME: 42partner-CODE-DEPLOY
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: 42partner-CODE-DEPLOY-PROD-GROUP
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- run: mkdir -p ./module-api/src/main/resources
- run: touch ${{ env.RESOURCE_PATH }}
- run: echo "${{ secrets.APPLICATION_PROD }}" > ${{ env.RESOURCE_PATH }}
- name: Grant execute permission for gradlew
run: chmod +x ./module-api/gradlew
shell: bash
- name: Build with Gradle
run: ./module-api/gradlew build -x test
shell: bash
- name: Make zip file
run: zip -r ./$GITHUB_SHA .
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: ${{ secrets.AWS_REGION }}
- name: Upload to S3
run: aws s3 cp --region ${{ secrets.AWS_REGION }} ./$GITHUB_SHA.zip s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip
- name: Code Deploy
run: |
aws deploy create-deployment \
--deployment-config-name CodeDeployDefault.OneAtATime \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=$GITHUB_SHA.zip
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "VisualEditor0",
"Effect": "Allow",
"Action": [
"iam:PassRole",
"ec2:CreateTags",
"ec2:RunInstances"
],
"Resource": "*"
}
]
}