Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: 개발 서버를 추가하고, 워크플로우를 개선한다 #126

Merged
merged 8 commits into from
Apr 4, 2024
57 changes: 36 additions & 21 deletions .github/workflows/cd.yml → .github/workflows/dev-deploy.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: Production CD

name: 변경사항을 개발 서버에 배포한다
on:
workflow_dispatch:
push:
branches: [ "dev" ]
permissions:
contents: read

Expand All @@ -11,7 +12,9 @@ env:

jobs:
deploy:
runs-on: production
runs-on: dev
environment:
name: dev
steps:
- name: Get token from Submodule Reader
uses: actions/create-github-app-token@v1
Expand All @@ -27,56 +30,68 @@ jobs:
submodules: true
token: ${{ steps.app_token.outputs.token }}

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Create bootjar
run: |
chmod +x ./gradlew
./gradlew bootjar
uses: gradle/gradle-build-action@v3
with:
arguments: bootjar

- name: Copy jar
shell: bash {0}
run: |
mkdir $JAR_DIRECTORY
cp ./build/libs/$JAR_NAME $JAR_DIRECTORY/$JAR_NAME

- name: Download Datadog Java Agent
working-directory: ${{ env.JAR_DIRECTORY }}
run: |
wget -O dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'

- name: 현재 사용중인 어플리케이션 포트 확인
shell: bash {0}
run: |
if [ -n "$(lsof -ti:${{ vars.APPLICATION_PORT_A }})" ]; then
PORT_A_PID=$(lsof -ti:${{ vars.APPLICATION_PORT_A }})
PORT_B_PID=$(lsof -ti:${{ vars.APPLICATION_PORT_B }})
if [ -n $PORT_A_PID -a -n $PORT_B_PID ]; then
echo "::error title=배포 실패::$PORT_A_PID, $PORT_B_PID 두 포트가 모두 사용중입니다";
exit 1;
fi

if [ -n $PORT_A_PID ]; then
Comment on lines +50 to +56
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

포트를 둘다 쓰고 있을 경우가 있나요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오류가 난 적 있었어요. (짧은 시간에 여러번 배포시도한 경우)
스크립트가 서버 잘 실행된줄 알고 계속 접속 시도하더라구요.

echo "BLUE_PORT=${{ vars.APPLICATION_PORT_A }}" >> "$GITHUB_ENV"
echo "GREEN_PORT=${{ vars.APPLICATION_PORT_B }}" >> "$GITHUB_ENV"
else
fi
if [ -n $PORT_B_PID ]; then
echo "BLUE_PORT=${{ vars.APPLICATION_PORT_B }}" >> "$GITHUB_ENV"
echo "GREEN_PORT=${{ vars.APPLICATION_PORT_A }}" >> "$GITHUB_ENV"
fi

- name: Download Datadog Java Agent
working-directory: ${{ env.JAR_DIRECTORY }}
run: |
wget -O dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'

- name: 그린 어플리케이션 실행
env:
RUNNER_TRACKING_ID: ""
shell: bash
working-directory: ${{ env.JAR_DIRECTORY }}
run: |
nohup java -javaagent:dd-java-agent.jar \
-Dspring.profiles.active=production \
nohup java \
-Dserver.port=$GREEN_PORT \
-Dspring.profiles.active=${{ vars.ENVIRONMENT_NAME }} \
-DACCESS_TOKEN_SECRET_KEY=${{ secrets.ACCESS_TOKEN_SECRET_KEY }} \
-DACCESS_TOKEN_EXPIRY_DAYS=${{ secrets.ACCESS_TOKEN_EXPIRY_DAYS }} \
-DREFRESH_TOKEN_SECRET_KEY=${{ secrets.REFRESH_TOKEN_SECRET_KEY }} \
-DREFRESH_TOKEN_EXPIRY_DAYS=${{ secrets.REFRESH_TOKEN_EXPIRY_DAYS }} \
-Dserver.port=$GREEN_PORT \
-DPRODUCTION_DB_URL=${{ secrets.PRODUCTION_DB_URL }} \
-DPRODUCTION_DB_USERNAME=${{ secrets.PRODUCTION_DB_USERNAME }} \
-DPRODUCTION_DB_PASSWORD=${{ secrets.PRODUCTION_DB_PASSWORD }} \
-DPRODUCTION_DB_URL=${{ secrets.DB_URL }} \
-DPRODUCTION_DB_USERNAME=${{ secrets.DB_USERNAME }} \
-DPRODUCTION_DB_PASSWORD=${{ secrets.DB_PASSWORD }} \
-javaagent:dd-java-agent.jar \
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DPRODUCTION_ 이라는 이름이 '운영 서버'의 의미로 썼던건가요 아님 다른 의미가 있나요??

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

운영의 의미로 사용했습니다.
이제 환경에 따라 프로파일 및 시크릿이 분리되었기 때문에 PRODUCTION_ 접두사를 유지할 필요가 없어서 제거했습니다.

-Ddd.profiling.enabled=true \
-XX:FlightRecorderOptions=stackdepth=256 \
-Ddd.logs.injection=true \
-Ddd.appsec.enabled=true \
-Ddd.iast.enabled=true \
-Ddd.service=snackgame \
-Ddd.env=production \
-Ddd.env=${{ vars.ENVIRONMENT_NAME }} \
-jar $JAR_NAME > ~/snackgame-server.log &

- name: 그린 어플리케이션이 접속 가능할 때까지 기다린다
Expand All @@ -85,7 +100,7 @@ jobs:
PROCESS_ID="$(lsof -i:$GREEN_PORT -t)"
while [ "$(curl -o /dev/null -s -w %{http_code} localhost:$GREEN_PORT/rankings?by=BEST_SCORE)" != 200 ]
do
if [ -n "$PROCESS_ID" ]; then
if [ -e /proc/$PROCESS_ID ]; then
echo "::error title=배포 실패::블루 어플리케이션으로 롤백합니다.";
exit 1;
fi
Expand Down
126 changes: 126 additions & 0 deletions .github/workflows/production-deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
name: 변경사항을 운영 서버에 배포한다
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 스크립트는 dev-deploy.yml과 발동 조건 빼고 동일합니다.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그 발동 조건이 branches: main이고 job runs-on 부분만 다른거 맞죠? 확인차 여쭙니다.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그 발동 조건이 branches: main이고 job runs-on 부분만 다른거 맞죠? 확인차 여쭙니다.

맞습니다!


on:
workflow_dispatch:
push:
branches: [ "main" ]
permissions:
contents: read

env:
JAR_NAME: snackgame-server.jar
JAR_DIRECTORY: /home/ubuntu/snackgame

jobs:
deploy:
runs-on: production
environment:
name: production
steps:
- name: Get token from Submodule Reader
uses: actions/create-github-app-token@v1
id: app_token
with:
app-id: ${{ secrets.SUBMODULE_APP_ID }}
private-key: ${{ secrets.SUBMODULE_APP_PEM }}
owner: ${{ github.repository_owner }}

- name: Checkout
uses: actions/checkout@v4
with:
submodules: true
token: ${{ steps.app_token.outputs.token }}

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Build
uses: gradle/gradle-build-action@v3
with:
arguments: build

- name: Copy jar
shell: bash {0}
run: |
mkdir $JAR_DIRECTORY
cp ./build/libs/$JAR_NAME $JAR_DIRECTORY/$JAR_NAME

- name: 현재 사용중인 어플리케이션 포트 확인
shell: bash {0}
run: |
PORT_A_PID=$(lsof -ti:${{ vars.APPLICATION_PORT_A }})
PORT_B_PID=$(lsof -ti:${{ vars.APPLICATION_PORT_B }})
if [ -n $PORT_A_PID -a -n $PORT_B_PID ]; then
echo "::error title=배포 실패::$PORT_A_PID, $PORT_B_PID 두 포트가 모두 사용중입니다";
exit 1;
fi

if [ -n $PORT_A_PID ]; then
echo "BLUE_PORT=${{ vars.APPLICATION_PORT_A }}" >> "$GITHUB_ENV"
echo "GREEN_PORT=${{ vars.APPLICATION_PORT_B }}" >> "$GITHUB_ENV"
fi
if [ -n $PORT_B_PID ]; then
echo "BLUE_PORT=${{ vars.APPLICATION_PORT_B }}" >> "$GITHUB_ENV"
echo "GREEN_PORT=${{ vars.APPLICATION_PORT_A }}" >> "$GITHUB_ENV"
fi

- name: Download Datadog Java Agent
working-directory: ${{ env.JAR_DIRECTORY }}
run: |
wget -O dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'

- name: 그린 어플리케이션 실행
env:
RUNNER_TRACKING_ID: ""
shell: bash
working-directory: ${{ env.JAR_DIRECTORY }}
run: |
nohup java \
-Dserver.port=$GREEN_PORT \
-Dspring.profiles.active=${{ vars.ENVIRONMENT_NAME }} \
-DACCESS_TOKEN_SECRET_KEY=${{ secrets.ACCESS_TOKEN_SECRET_KEY }} \
-DACCESS_TOKEN_EXPIRY_DAYS=${{ secrets.ACCESS_TOKEN_EXPIRY_DAYS }} \
-DREFRESH_TOKEN_SECRET_KEY=${{ secrets.REFRESH_TOKEN_SECRET_KEY }} \
-DREFRESH_TOKEN_EXPIRY_DAYS=${{ secrets.REFRESH_TOKEN_EXPIRY_DAYS }} \
-DPRODUCTION_DB_URL=${{ secrets.DB_URL }} \
-DPRODUCTION_DB_USERNAME=${{ secrets.DB_USERNAME }} \
-DPRODUCTION_DB_PASSWORD=${{ secrets.DB_PASSWORD }} \
-javaagent:dd-java-agent.jar \
-Ddd.profiling.enabled=true \
-XX:FlightRecorderOptions=stackdepth=256 \
-Ddd.logs.injection=true \
-Ddd.appsec.enabled=true \
-Ddd.iast.enabled=true \
-Ddd.service=snackgame \
-Ddd.env=${{ vars.ENVIRONMENT_NAME }} \
-jar $JAR_NAME > ~/snackgame-server.log &

- name: 그린 어플리케이션이 접속 가능할 때까지 기다린다
shell: bash {0}
run: |
PROCESS_ID="$(lsof -i:$GREEN_PORT -t)"
while [ "$(curl -o /dev/null -s -w %{http_code} localhost:$GREEN_PORT/rankings?by=BEST_SCORE)" != 200 ]
do
if [ -e /proc/$PROCESS_ID ]; then
echo "::error title=배포 실패::블루 어플리케이션으로 롤백합니다.";
exit 1;
fi
echo "새로운 어플리케이션을 띄우는 중입니다.";
sleep 5;
done

- name: 리버스 프록시 설정 변경
working-directory: ${{ env.JAR_DIRECTORY }}
shell: bash {0}
run: |
echo "proxy_pass http://localhost:$GREEN_PORT;" > port.inc;
sudo nginx -s reload;

- name: 블루 어플리케이션 종료
shell: bash {0}
run: |
PROCESS_ID="$(lsof -i:$BLUE_PORT -t)"
if [ -n "$PROCESS_ID" ]; then
sudo kill -15 $PROCESS_ID
echo "구동중인 애플리케이션을 종료했습니다. (pid : $PROCESS_ID)\n"
fi
13 changes: 6 additions & 7 deletions .github/workflows/ci.yml → .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: build and test with Gradle
name: PR을 테스트한다

on:
workflow_dispatch:
pull_request:
branches: [ "main" ]
branches: [ "main", "dev" ]

permissions:
contents: read
Expand All @@ -20,7 +20,7 @@ jobs:
app-id: ${{ secrets.SUBMODULE_APP_ID }}
private-key: ${{ secrets.SUBMODULE_APP_PEM }}
owner: ${{ github.repository_owner }}

- name: Checkout
uses: actions/checkout@v4
with:
Expand All @@ -33,12 +33,11 @@ jobs:
java-version: '17'
distribution: 'corretto'

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

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
uses: gradle/gradle-build-action@v3
with:
arguments: build

Expand Down
Loading