Feature: (BRD-7) 로그인 API 구현 (#47) #55
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: Deploy | |
on: | |
push: | |
branches: | |
- master | |
jobs: | |
Deploy: | |
runs-on: ubuntu-latest | |
env: | |
DB_NAME: board_db_test | |
DB_ROOT_PASSWORD: root | |
DB_TEST_USERNAME: board_user_test | |
DB_TEST_USER_PASSWORD: db1004 | |
steps: | |
- name: 체크 아웃 | |
uses: actions/checkout@v4 | |
- name: 데이터베이스 설정 | |
run: | | |
sudo /etc/init.d/mysql start | |
mysql -e "CREATE DATABASE ${{ env.DB_NAME }};" -uroot -p${{ env.DB_ROOT_PASSWORD }} | |
mysql -e "CREATE user '${{ env.DB_TEST_USERNAME }}'@'%' IDENTIFIED BY '${{ env.DB_TEST_USER_PASSWORD }}';" -uroot -p${{ env.DB_ROOT_PASSWORD }} | |
mysql -e "GRANT ALL ON *.* TO '${{ env.DB_TEST_USERNAME }}'@'%';" -uroot -p${{ env.DB_ROOT_PASSWORD }} | |
mysql -e "FLUSH PRIVILEGES;" -uroot -p${{ env.DB_ROOT_PASSWORD }} | |
- name: Java 21 설정 | |
uses: actions/setup-java@v4 | |
with: | |
distribution: 'temurin' | |
java-version: '21' | |
- name: Gradle 캐싱 | |
uses: actions/cache@v4 | |
with: | |
path: | | |
~/.gradle/caches | |
~/.gradle/wrapper | |
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }} | |
restore-keys: | | |
${{ runner.os }}-gradle- | |
- name: gradlew 파일 실행권한 부여 | |
run: chmod +x gradlew | |
shell: bash | |
- name: 프로젝트 빌드 | |
run: | | |
./gradlew build | |
- name: DockerHub 로그인 | |
uses: docker/login-action@v3 | |
with: | |
username: ${{ secrets.DOCKERHUB_USERNAME }} | |
password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }} | |
- name: 도커 이미지 빌드 | |
run: docker build --platform linux/amd64 -t ${{ secrets.DOCKERHUB_USERNAME }}/board-be . | |
- name: 도커 이미지 푸시 | |
run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/board-be:latest | |
- name: 배포 대상 포트/PROFILE 확인 | |
run: | | |
response=$(curl -s -w "%{http_code}" "http://${{ secrets.LIVE_SERVER_IP }}/api/v1/deploy/health-check") | |
STATUS="${response: -3}" # 마지막 3글자 (HTTP 상태 코드) | |
BODY="${response::-3}" # 나머지 (응답 본문) | |
echo "STATUS=$STATUS" | |
if [ "$STATUS" = "200" ]; then | |
CURRENT_PROFILE=$(echo "$BODY" | jq -r '.data.profile') | |
echo "CURRENT_PROFILE=$CURRENT_PROFILE" | |
CURRENT_UPSTREAM="$CURRENT_PROFILE" | |
else | |
CURRENT_UPSTREAM="green" | |
fi | |
echo "CURRENT_UPSTREAM=$CURRENT_UPSTREAM" | |
echo "CURRENT_UPSTREAM=$CURRENT_UPSTREAM" >> $GITHUB_ENV | |
if [ "$CURRENT_UPSTREAM" = "blue" ]; then | |
echo "CURRENT_PORT=${{ secrets.BLUE_PORT }}" >> $GITHUB_ENV | |
echo "STOPPED_PORT=${{ secrets.GREEN_PORT }}" >> $GITHUB_ENV | |
echo "TARGET_UPSTREAM=green" >> $GITHUB_ENV | |
elif [ "$CURRENT_UPSTREAM" = "green" ]; then | |
echo "CURRENT_PORT=${{ secrets.GREEN_PORT }}" >> $GITHUB_ENV | |
echo "STOPPED_PORT=${{ secrets.BLUE_PORT }}" >> $GITHUB_ENV | |
echo "TARGET_UPSTREAM=blue" >> $GITHUB_ENV | |
else | |
echo "error" | |
exit 1 | |
fi | |
- name: GitHub Actions 실행자 IP 얻어오기 | |
id: GITHUB_ACTIONS_IP | |
uses: haythem/[email protected] | |
- name: AWS CLI 설정 | |
uses: aws-actions/configure-aws-credentials@v4 | |
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: GitHub Actions - SSH 및 컨테이너 실제 포트 접근 권한 부여 | |
run: | | |
aws ec2 authorize-security-group-ingress \ | |
--group-id ${{ secrets.EC2_SECURITY_GROUP_ID }} \ | |
--ip-permissions \ | |
'IpProtocol=tcp,FromPort=${{ secrets.EC2_SSH_PORT }},ToPort=${{ secrets.EC2_SSH_PORT }},IpRanges=[{CidrIp=${{ steps.GITHUB_ACTIONS_IP.outputs.ipv4 }}/32}]' \ | |
'IpProtocol=tcp,FromPort=${{ env.STOPPED_PORT }},ToPort=${{ env.STOPPED_PORT }},IpRanges=[{CidrIp=${{ steps.GITHUB_ACTIONS_IP.outputs.ipv4 }}/32}]' | |
- name: SSH Key 설정 | |
run: | | |
mkdir -p ~/.ssh | |
echo "${{ secrets.EC2_SSH_KEY }}" > ~/.ssh/board-ec2-key.pem | |
chmod 600 ~/.ssh/board-ec2-key.pem | |
echo "Host board-ec2" >> ~/.ssh/config | |
echo " HostName ${{ secrets.LIVE_SERVER_IP }}" >> ~/.ssh/config | |
echo " User ${{ secrets.EC2_USERNAME }}" >> ~/.ssh/config | |
echo " IdentityFile ~/.ssh/board-ec2-key.pem" >> ~/.ssh/config | |
echo " StrictHostKeyChecking no" >> ~/.ssh/config | |
- name: 도커 이미지 풀링 및 컨테이너 실행 | |
run: | | |
ssh board-ec2 << 'EOF' | |
set -e | |
# 필요한 프로필 파일을 서버로 복사합니다. | |
echo "${{ secrets.DB_CONFIG_PRODUCTION_YML }}" | base64 --decode > /home/ec2-user/config/board-system/db-config-production.yml | |
echo "${{ secrets.EMAIL_SEND_CONFIG_PRODUCTIONSECRET_YML }}" | base64 --decode > /home/ec2-user/config/board-system/email-send-config-productionSecret.yml | |
echo "${{ secrets.PUBLIC_KEY_PRODUCTIONSECRET_PEM }}" > /home/ec2-user/config/board-system/public_key_productionSecret.pem | |
echo "${{ secrets.PRIVATE_KEY_PRODUCTIONSECRET_PEM }}" > /home/ec2-user/config/board-system/private_key_productionSecret.pem | |
if [ "${{ env.TARGET_UPSTREAM }}" = "blue" ]; then | |
echo "${{ secrets.DEPLOY_CONFIG_BLUE_YML }}" | base64 --decode > /home/ec2-user/config/board-system/deploy-config-blue.yml | |
else | |
echo "${{ secrets.DEPLOY_CONFIG_GREEN_YML }}" | base64 --decode > /home/ec2-user/config/board-system/deploy-config-green.yml | |
fi | |
docker pull ${{ secrets.DOCKERHUB_USERNAME }}/board-be:latest | |
docker compose -f docker-compose-${{ env.TARGET_UPSTREAM }}.yml up -d | |
EOF | |
- name: 새로 실행한 서버 컨테이너 헬스 체크 | |
uses: jtalk/url-health-check-action@v3 | |
with: | |
url: http://${{ secrets.LIVE_SERVER_IP }}:${{ env.STOPPED_PORT }}/api/v1/deploy/health-check | |
max-attempts: 3 | |
retry-delay: 10s | |
- name: Nginx 의 대상 서버를 새로 실행한 컨테이너쪽으로 전환 | |
run: | | |
ssh board-ec2 << 'EOF' | |
set -e | |
docker exec -i nginx bash -c 'echo "set \$service_url ${{ env.TARGET_UPSTREAM }};" > /etc/nginx/conf.d/service-env.inc && nginx -s reload' | |
EOF | |
- name: 기존 배포 컨테이너 정지 | |
run: | | |
ssh board-ec2 << 'EOF' | |
set -e | |
docker stop ${{ env.CURRENT_UPSTREAM }} | |
docker rm ${{ env.CURRENT_UPSTREAM }} | |
EOF | |
- name: GitHub Actions - SSH 및 컨테이너 실제 포트 접근 권한 제거 | |
if: always() | |
run: | | |
aws ec2 revoke-security-group-ingress \ | |
--group-id ${{ secrets.EC2_SECURITY_GROUP_ID }} \ | |
--ip-permissions \ | |
'IpProtocol=tcp,FromPort=${{ secrets.EC2_SSH_PORT }},ToPort=${{ secrets.EC2_SSH_PORT }},IpRanges=[{CidrIp=${{ steps.GITHUB_ACTIONS_IP.outputs.ipv4 }}/32}]' \ | |
'IpProtocol=tcp,FromPort=${{env.STOPPED_PORT}},ToPort=${{env.STOPPED_PORT}},IpRanges=[{CidrIp=${{ steps.GITHUB_ACTIONS_IP.outputs.ipv4 }}/32}]' |