๐ CI์ AWS ํ๊ฒฝ์ค์ ์ ๋จผ์ ํด์ผํ๋ค.
๐ ๊นํ > Actions
๐ Actions secrets ์์ฑ
๐Setting > Secrets and variables > Actions > New repository secret ํด๋ฆญ
๐2๊ฐ ์์ฑ ๊ฐ๊ฐ ( AWS ํ๊ฒฝ์ค์ ๊ธ 4๋ฒ์์ ๋ค์ด๋ฐ์ CSVํ์ผ์์ ํคID ๊ฐ๊ณผ ์ก์ธ์คํค๋ฅผ ๊ฐ์ ธ์ ๊ฐ๊ฐ ์ ์ฉ)
- CSV๋ ,๋ก ๊ฐ์ ๋๋๋ค.
๐ AppSpec ํ์ผ ์์ฑ
********* AppSpec ํ์ผ๋ช ์ appspec์ผ๋ก ๋ชจ๋ ์๋ฌธ์๋ก ํด์ผํจ!!!!!!! ์๋์ฒ๋ผ ํ๋ค๊ฐ 255 Error๋ด
root ํด๋ ์ฆ, builda.gradle ์ด๋ gradlew ๋ฑ์ด ์๋ ๊ฒฝ๋ก์ ์์ฑ. ์ด ํ์ผ์ CodeDeploy๊ฐ ๋ฐฐํฌ๋ฅผ ์ํด ์ฐธ์กฐํ๋ ํ์ผ!
์ฌ๊ธฐ์ ํ์ผ์ EC2 ์ด๋ ๊ฒฝ๋ก์ ๋ณต์ฌํ ๊ฑด์ง, ๋ฐฐํฌ ์ดํ์ ์ด๋ค ํ๋์ ํ๊ฒ ํ ๊ฑด์ง ํ ์ ์์ด ์๋ฒ ๋ฐฐํฌ์ ๋ํ ์ค์ ์ ํ ์ ์๋ค.
version: 0.0 # ๋ฒ์ ผ
os: linux # OS
files: # ๋ฐฐํฌ ํ์ผ ์ค์
- source: / # ์ธ์คํด์ค์ ๋ณต์ฌํ ๋๋ ํฐ๋ฆฌ ๊ฒฝ๋ก
destination: /home/ubuntu/app # ์ธ์คํด์ค์์ ํ์ผ์ด ๋ณต์ฌ๋ ๋ชฉ์ ์ง
overwrite: yes # ๋ฎ์ด์ฐ๊ธฐ ํ์ฉ
permissions: # ํ์ผ์ ๊ดํ ๊ถํ ์ค์
- object: / # ๊ถํ ์ง์ ๋๋ ํ์ผ ๋๋ ๊ฒฝ๋ก
pattern: "**" # ๋งค์นญ๋๋ ํจํด์๋ง ๊ถํ๋ถ์ฌ
owner: ubuntu # Object ์์ ์
group: ubuntu # Object ๊ทธ๋ฃน ์ด๋ฆ
hooks: # ๋ฐฐํฌ ์ดํ ์ํํ ์คํฌ๋ฆฝํธ ๋ถ๋ถ
AfterInstall: # ํ์ผ ์ค์น ํ ์คํ๋๋ ์คํฌ๋ฆฝํธ
- location: scripts/stop.sh # ์คํ๋๋ ์คํฌ๋ฆฝํธ ๊ฒฝ๋ก, ์์น
timeout: 60 # ์คํฌ๋ฆฝํธ ์คํ ํ์ฉ ์๊ฐ, ๋์ผ๋ฉด ๋ฐฐํฌ ์คํจ
runas: ubuntu # ์คํฌ๋ฆฝํธ ์คํ ์ฌ์ฉ์
ApplicationStart: # ์ ํ๋ฆฌ์ผ์ด์
์คํ ์คํฌ๋ฆฝํธ
- location: scripts/start.sh
timeout: 60
runas: ubuntu
๐ Code Deploy ํ๋ฆ ์๊ฐํด์ hook ์์ฑ
๐ ์คํ ์คํฌ๋ฆฝํธ ์์ฑ
rootํด๋์ scripts ํด๋ ์์ฑ
appspec ํ์ผ์์ ์คํ ์ํฌ ์คํ ์คํฌ๋ฆฝํธ ๋ํ ์์ฑํ๋ค.
๋ฑ๊ทค๋ ์ฝ๋๋ฅผ ๊ทธ๋๋ก ์จ์ ๊ณต๋ถํ์ต๋๋ค! 7-1๊ณผ 7-2๋ฒ ์ฝ๋!
๐ stop.sh (๊ธฐ์กด์ ์คํ ์ค์ด๋ ํ์ผ์ ์ข ๋ฃ)
#!/usr/bin/env bash
PROJECT_ROOT="/home/ubuntu/app"
JAR_FILE="$PROJECT_ROOT/CICD_githubActions-0.0.1-SNAPSHOT.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 & # ๊ณ์ ์คํ๋๊ฒ nohup์ผ๋ก ์คํ
CURRENT_PID=$(pgrep -f $JAR_FILE) # nohup์ผ๋ก ์คํ ํ ํ๋ก์ธ์ค ์์ด๋๋ฅผ ์ป์
echo "$TIME_NOW > ์คํ๋ ํ๋ก์ธ์ค ์์ด๋ : $CURRENT_PID" >> $DEPLOY_LOG
๐ start.sh (์๋ก์ด jarํ์ผ์ ์คํ)
#!/usr/bin/env bash
# #!์ ๋ช
๋ น์ด ์งํฉํ์, ๋ค๋ ์ด ๋ช
๋ น์ด๋ค์ ํด์ํ ํ๋ก๊ทธ๋จ ์์น์ ํ๋ก๊ทธ๋จ
#-------------------------------------------------- ๋ณ์ ์ ์ธ START
PROJECT_ROOT="/home/ubuntu/app" # ์ข
๋ฃํ jarํ์ผ ์์น
JAR_FILE="$PROJECT_ROOT/CICD_githubActions-0.0.1-SNAPSHOT.jar" # ์ข
๋ฃํ jarํ์ผ ์ด๋ฆ
DEPLOY_LOG="$PROJECT_ROOT/deploy.log" # ๋ก๊ทธํ์ผ ์์ฑ
TIME_NOW=$(date +%c) # ํ์ฌ์๊ฐ
# ํ์ฌ ๊ตฌ๋ ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
pid ํ์ธ
CURRENT_PID=$(pgrep -f $JAR_FILE)
#-------------------------------------------------- ๋ณ์ ์ ์ธ END
#-------------------------------------------------- ๋ช
๋ น์ด START
# ํ๋ก์ธ์ค๊ฐ ์ผ์ ธ ์์ผ๋ฉด ์ข
๋ฃ
if [ -z $CURRENT_PID ]; then
# ๋ฆฌ๋
์ค์์ > ์ >> ์ ์ฐจ์ด : > (๋ค์ ๋์ค๋ ํ์ผ์ write or overwrite), >> (๋ค์ ๋์ค๋ ํ์ผ์ ์ถ๊ฐ append)
echo "$TIME_NOW > ํ์ฌ ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ด ์์ต๋๋ค" >> $DEPLOY_LOG # ๋ฆฌ๋
์ค ํฐ๋ฏธ๋ ์ถ๋ ฅ ๋ช
๋ น์ด
else
echo "$TIME_NOW > ์คํ์ค์ธ $CURRENT_PID ์ ํ๋ฆฌ์ผ์ด์
์ข
๋ฃ " >> $DEPLOY_LOG
kill -15 $CURRENT_PID # -15 ํ๋ก์ธ์ค๋ฅผ ์์ ํ๊ฒ ์ข
๋ฃ
fi
๐ plain.jar ์์ฑ๋์ง ์๊ฒ build.gradle ์ค์
๋น๋์ ์ผ๋ฐ jarํ์ผ ๋ง๊ณ ๋ plain.jarํ์ผ์ด ํ๋ ๋ ์์ฑ๋๋ ๋ฐ ์ด๋ฅผ ๋ฐฉ์ง, ์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๋ฉด ๋๋ค.
* plain.jar๋ plain archive๋ผ๊ณ ํด์ dependency๋ฅผ ๋ชจ๋ ์ ์ธํ ์์ํ ์์ค์ฝ๋์ ๋ฆฌ์์ค๋ง์ ๊ฐ์ง๊ณ ์๋ ํ์ผ
jar {
enabled = false
}
๐ gradle.yml ์์
๐ ์์ ์
name: Java CI with Gradle
on: # ์ํฌํ๋ก์ฐ๋ฅผ ์คํํ ์ด๋ฒคํธ ์ข
๋ฅ์ ํน์ ๋ธ๋์น ์ค์
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
permissions: # ๊ถํ ์ค์
contents: read
jobs: # ์ํํ ์ํฌํ๋ก์ฐ
build: # ๋น๋
runs-on: ubuntu-latest # ๋น๋๊ฐ ์คํํ OS
steps: # ๋จ๊ณ ์ค์
- uses: actions/checkout@v3 # ์ํฌํ๋ก์ฐ ์คํ์ ์ฒดํฌ์์
- name: Set up JDK 11 # JDK 11 ๋ฒ์ ์ค์น
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
# Build
- name: Build with Gradle # gradle๋ก ๋น๋ ์คํ
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: build
๐ ์์ ํ
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
name: Java CI/CD with Gradle
on: # ์ํฌํ๋ก์ฐ๋ฅผ ์คํํ ์ด๋ฒคํธ ์ข
๋ฅ์ ํน์ ๋ธ๋์น ์ค์
push:
branches: [ "main" ]
pull_request:
branches: [ "main" ]
env: # ํ๊ฒฝ ์ค์
AWS_REGION: ap-northeast-2
S3_BUCKET_NAME: littlezerobucket
CODE_DEPLOY_APPLICATION_NAME: cicd_Test
CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: cicd_group # IAM์ CodeDeploy์ฉ ์ญํ
permissions: # ๊ถํ ์ค์
contents: read
jobs: # ์ํํ ์ํฌํ๋ก์ฐ
deploy: # Deploy
name: Deploy
runs-on: ubuntu-latest # ๋น๋๊ฐ ์คํํ OS
environment: production
steps: # ๋จ๊ณ ์ค์
# ์ฒดํฌ์์
- name: Checkout
uses: actions/checkout@v3 # ์ํฌํ๋ก์ฐ ์คํ์ ์ฒดํฌ์์
# JDK 11 ์ธํ
- name: Set up JDK 11 # JDK 11 ๋ฒ์ ์ค์น
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
# BUILD ๊ถํ ๋ถ์ฌ
- name: Grant execute permission for gradlew
run: chmod +x ./gradlew
# Build
# BUILD
- name: Build with Gradle # gradle๋ก ๋น๋ ์คํ
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: clean build
# 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: ${{ env.AWS_REGION }}
# ๋น๋ํ ํ์ผ S3 ๋ฒํท์ ์
๋ก๋
- name: Upload to AWS S3
run: |
aws deploy push \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--ignore-hidden-files \
--s3-location s3://$S3_BUCKET_NAME/$GITHUB_SHA.zip \
--source .
# S3 ๋ฒํท์ ์ฌ๋ฆฐ ํ์ผ๋ก CodeDeploy ์คํ
- name: Deploy to AWS EC2 from S3
run: |
aws deploy create-deployment \
--application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \
--deployment-config-name CodeDeployDefault.AllAtOnce \
--deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \
--s3-location bucket=$S3_BUCKET_NAME,key=$GITHUB_SHA.zip,bundleType=zip
๐ ๊ทธ๋ฆฌ๊ณ ์๋ ๋ฐ์ํ ๋ค์ํ ํธ๋ฌ๋ธ... ๋ค์ ํด๊ฒฐํ๊ณ ๋์ ๋๋์ด ์๋ ๋ฐฐํฌ ์ฑ๊ณต!
ํธ๋ฌ๋ธ ์ํ ๋ค ****
*** 1)
Error: The security token included in the request invalid.
๋ฌธ์ : credential ๊ฒ์ฆ์์ ์ค๋ฅ
์์ธ: Code Deploy Application Name ๊ฐ๊ณผ Code Deploy Application Group Name์ ์๋ชป๋ฃ์ด์ ๋ฐ์
ํด๊ฒฐ: AWS CodeDeploy์์ ์์ฑํ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฆ๊ณผ ๊ทธ ์์ ๋ฐฐํฌ ๊ทธ๋ฃน ์ด๋ฆ์ผ๋ก ์ค์ ํด์ฃผ๋ ํด๊ฒฐ
๐ ๋๋ค AWSํ๊ฒฝ ์ค์ ๊ธ์์ 9๋ฒ์์ ๋ง๋ ๊ฒ์ yml์ ๋ฃ์ด์ค์ผ ํ๋ค.
*** 2)
Error: Process completed with exit code 255.
appspec.yml was not found.
๋ฌธ์ : appspec.yml์ ์ฐพ์ง ๋ชปํด ์คํ ๋ชปํจ
์์ธ: appspec ํ์ผ๋ช ์ AppSpec์ผ๋ก ํด์ ์ฐพ์ง ๋ชปํจ
ํด๊ฒฐ: ํ์ผ๋ช ์ ๋ชจ๋ ์๋ฌธ์๋ก ํด์คฌ๋๋ ํด๊ฒฐ
*** 3)
Error: Process completed with exit code 127.
command not found
๋ฌธ์ : ์๊ตฌํ๋ arguments๋ฅผ ๋ชป๋ถ๋ฌ์ด
์์ธ: ํด๋น arguments ์์ ๋ง์ง ์๋ arguments๊ฐ ๋ถ์ด ๋ค๋ฅผ ์ฝ์ง ๋ชปํจ
ํด๊ฒฐ: ๋ถํ์ํ arguments ์ญ์ ๋ก ํด๊ฒฐ
*** 4)
CodeDeploy agent was not able to receive the lifecycle event. Check the CodeDeploy agent logs on your host and make sure the agent is running and can connect to the CodeDeploy server.
- CodeDeploy agent๊ฐ ๋ผ์ดํ์ฌ์ดํด ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ์ ์์ผ๋ host์ ๋ก๊ทธ๋ฅผ ์ดํด๋ณด๋ผ๋ ๋ด์ฉ
EC2 ๋ก๊ทธ๋ ์ฒ์ ์ฐ๋ถํฌ ์ ์ ๊ธฐ์ค
../../var/log/aws/codedeploy-agent/codedeploy-agent.log
์ ์์นํ๊ณ ์๋ค. ๊ทธ๊ณณ์ ์จ์๋ ๋ก๊ทธ๋ฅผ ๋ณด๋ฉด
ERROR [codedeploy-agent(1163)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Missing credentials - please check if this instance was started with an IAM instance profile
๋ฌธ์ : github actions์์ Deploy๊ฐ ์ฑ๊ณตํ์์๋ ๋ถ๊ตฌํ๊ณ ์ค์ ๋ก AWS Deploy๊ฒฐ๊ณผ๋ฅผ ๋ดค์ ๋ ApplicationStop์์ ๋ฐ๋ก ์คํจํ ์ผ์ด์ค
์์ธ: IAM ์ญํ ์ ์ง์ ํ์ง ์์ ์ธ์คํด์ค์ CodeDeployAgent๋ฅผ ๋จผ์ ์ค์นํด ๋ฒ๋ ค CodeDeploy์ ํด๋น ์ญํ ์ ์คํํ ์ ์๋ ์๊ฒฉ ์ฆ๋ช ์ด ์์ด์ ์๊ธด ๋ฌธ์
ํด๊ฒฐ: CodeDeploy Agent๋ฅผ EC2์์ ๋ค์ ์คํ ์ํค๋ฉด ๋๋ค.
- 1) ๋ค์ ์คํ
- 2) ์ํ ํ์ธ
sudo service codedeploy-agent restart
sudo service codedeploy-agent status
๐ ์์ ์ฑ๊ณต ๋ก๊ทธ ๋ณด๋ค๊ฐ ๋ ์๋ฌธ์
์ด ๋ก๊ทธ๋ฅผ ๋ณด๋ฉด ํ์ฌ ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์๋ค๊ณ ํ๋ค. ํ์ง๋ง ์๋์ฒ๋ผ ์ ์คํฌ๋ฆฝํธ๋ฅผ ๋ฃ์ด์คฌ๊ณ , ๊ธฐ์กด nohup์ ์ฃฝ์ด๊ณ ์๋ก์ด ๋น๋ ํ์ผ๋ก๋ ๋ณ๊ฒฝ์ด๋์ nohup์ผ๋ก ๋์๊ฐ๋ ์ํฉ. ๊ทผ๋ฐ ํ๋ก์ธ์ค๊ฐ ์ผ์ ธ์์ด์ stop.sh๊ฐ killํด์คฌ๋ค๋ฉด ์คํ์ค์ธ ํ๋ก์ธ์ค ์์ด๋์ ์ ํ๋ฆฌ์ผ์ด์ ์ข ๋ฃ์ ๋ํ ๋ก๊ทธ๋ ์ฐํ์ด์ผํ๋ ๋ฐ ์๋ค. ์ด๋ฏธ stop์ ์ ํ๋ก์ธ์ค๊ฐ kill์ด ๋ ๊ฒ์ผ๋ก ๋ณด์ธ๋ค.
# ํ๋ก์ธ์ค๊ฐ ์ผ์ ธ ์์ผ๋ฉด ์ข
๋ฃ
if [ -z $CURRENT_PID ]; then
# ๋ฆฌ๋
์ค์์ > ์ >> ์ ์ฐจ์ด : > (๋ค์ ๋์ค๋ ํ์ผ์ write or overwrite), >> (๋ค์ ๋์ค๋ ํ์ผ์ ์ถ๊ฐ append)
echo "$TIME_NOW > ํ์ฌ ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์
์ด ์์ต๋๋ค" >> $DEPLOY_LOG # ๋ฆฌ๋
์ค ํฐ๋ฏธ๋ ์ถ๋ ฅ ๋ช
๋ น์ด
else
echo "$TIME_NOW > ์คํ์ค์ธ $CURRENT_PID ์ ํ๋ฆฌ์ผ์ด์
์ข
๋ฃ " >> $DEPLOY_LOG
kill -15 $CURRENT_PID # -15 ํ๋ก์ธ์ค๋ฅผ ์์ ํ๊ฒ ์ข
๋ฃ
fi
์ง์ killํ์ง ์์๋ application์ stopํด ์ฃผ๋ ๋ก์ง์ด ์๋ ๊ฑธ๊น ์ถ์ด ์ด๋ฒคํธ๋ฅผ ๋ณด๋ ApplicationStop์ด ๋ง์์ ๊ฑธ๋ฆฐ๋ค.
ํน์ ์ ๋ง ์์์ ํด์ฃผ๊ณ ์๋ ๊ฑฐ ์๋๊น ์ถ์ด์
AfterInstall๊ณผ์ ์์ stop.sh์ ์คํํ ์ ์๋๋ก ์ค์ ํ yml ํ์ผ ๋ถ๋ถ์ ์์ ์ฃผ์์ฒ๋ฆฌ ํด๋ฒ๋ฆฌ๊ณ ํ ์คํธ๋ฅผ ํ๋๋ฐ
๋ ์ฉ ์๋๋ค. ์์ ์ฐํ ๋ก๊ทธ์ ๋ฌ๋ฆฌ ๋ง์ง๋ง ๋ก๊ทธ์ stop.sh์ ์๋ ํ์ฌ ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์ต๋๋ค ๋ก๊ทธ๋ ์๋ค. ๊ทธ๋ผ stop.sh๊ฐ ์๋ ๋ฒ์ ผ์ผ๋ก ์ ์คํ๋ฌ๋ค๋ ์ด์ผ๊ธฐ..
์ฐพ์๋ณด๋ ๋ฐฐํฌ ๋ผ์ดํ์ฌ์ดํด ์ด๋ฒคํธ ์ค์ ApplicationStop์ ๋ง์ง๋ง์ผ๋ก ์ฑ๊ณต ๋ฐฐํฌํ ๋ฒ์ ผ์์ appspec file๊ณผ ์คํฌ๋ฆฝํธ๋ฅผ ๊ฐ์ ธ์์ ์ฌ์ฉํ๋ค๊ณ ํ๋ค. ์ด ๋ง์ ์ฆ ์๋ก ๋ฐฐํฌํ ํ์ผ์์์ applicationStop๊ด๋ จ์ ์ด๋ฒ ๋ฐฐํฌ๊ฐ ์๋ ๋ค์ ๋ฐฐํฌ๋ฅผ ์ํด ์ ์ฉ๋๋ค๋ ๋ป์ด๊ธฐ๋ ํ๋ค. ํ์ง๋ง ๋๋ ์ ์๋ ํ์๋ applicationStop์ killํ๋ ๊ฑธ ์ค์ ํด์ค ์ ์ด ์๋๋ฐ? ์๋๋ฉด ์ ์ ํ์ผ์ ๋ค์ ์ญํํ๋ ๋ฐฉ์? ์.. ์๋๊ฑฐ ๊ฐ๊ณ ์ kill์ฒ๋ฆฌ๋ฅผ ์ฃผ์ํด์คฌ์์๋ killํ๋๊ฒ ๋๋ ๊ฑธ๊น ๊ถ๊ธํด!!
์ด์ ๋ํ ๋ด์ฉ์ ์ข ๋ ์กฐ์ฌํด๋ด์ผํ ๊ฑฐ ๊ฐ๋ค.
โ CI/CD ์ฐ์ตํ ๊นํ ๋ ํฌ์งํ ๋ฆฌ
โ ๊ณต๋ถ์๋ฃ
'DevOps > CI & CD' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
CI/CD] ์๋ ๋ฐฐํฌ ๊ด๋ จ ๋ค์ํ ์ํ ํ์ธ ๋ฐฉ๋ฒ (0) | 2023.01.26 |
---|---|
CI/CD] Properties ๊ด๋ฆฌ (1) | 2023.01.26 |
CI/CD] CodeDeploy - AWS ํ๊ฒฝ ์ค์ (2) | 2023.01.20 |
CI/CD] Github Actions CI (0) | 2023.01.20 |