Skip to content

Merge branch 'dev' #128

Merge branch 'dev'

Merge branch 'dev' #128

Workflow file for this run

name: GTRPGM Rule Engine CI/CD
on:
push:
branches:
- "main"
- "ops/deploy-compose"
workflow_dispatch:
env:
# service settings
SERVICE_NAME: ${{ vars.SERVICE_NAME }}
PORT: ${{ vars.PORT}}
TAG: ${{ vars.TAG || 'latest' }}
# system settings
REGISTRY: ${{ vars.REGISTRY }}
ORG_NAME: ${{ vars.ORG_NAME }}
IMAGE_NAME: ${{ vars.REGISTRY }}/${{ vars.ORG_NAME }}/${{ vars.SERVICE_NAME }}
jobs:
build-and-test:
runs-on: ubuntu-22.04
env:
REMOTE_HOST: ${{ secrets.REMOTE_HOST }}
DB_USER: ${{ secrets.DB_USER }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
DB_PORT: ${{ secrets.POSTGRES_PORT }}
DB_NAME: ${{ secrets.DB_NAME }}
REDIS_PORT: ${{ secrets.REDIS_PORT }}
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }}
APP_HOST: "127.0.0.1"
APP_PORT: ${{ secrets.APP_PORT }}
APP_ENV: "local"
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v5
with:
version: "latest"
enable-cache: true
- name: Set up Python 3.11
run: uv python install 3.11
- name: Install dependencies
run: uv sync
- name: Check DB Connection
run: |
export PYTHONPATH=$PYTHONPATH:.
uv run python -c "from src.configs.database import check_db_connection; check_db_connection()"
- name: Check Redis Connection
run: |
export PYTHONPATH=$PYTHONPATH:.
uv run python -c "from src.configs.redis_conn import check_redis_connection; check_redis_connection()"
- name: Server Smoke Test (Health Check)
run: |
export PYTHONPATH=$PYTHONPATH:.
# 1. 서버 실행 (reload 모드 없이 실행하는 것을 권장)
uv run python src/main.py > test_server.log 2>&1 &
# 2. 서버가 응답할 때까지 대기 (최대 10번 시도)
echo "Waiting for server to start..."
for i in {1..10}; do
if curl -s http://127.0.0.1:$APP_PORT/ > /dev/null; then
echo "✅ Server is up and running!"
pkill -f "python src/main.py" || true
exit 0
fi
echo "Attempt $i: Server not ready yet... (waiting 3s)"
sleep 3
done
# 3. 10번 시도 후에도 안 되면 실패 처리
echo "❌ 서버 응답 테스트 실패. 로그를 출력합니다:"
cat test_server.log
exit 1
build-and-push:
needs: build-and-test
runs-on: ubuntu-22.04
permissions:
contents: read
packages: write
id-token: write
outputs:
image: ${{ env.IMAGE_NAME }}:${{ env.TAG }}
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ${{ env.IMAGE_NAME }}
tags: |
type=raw,value=${{ env.TAG }}
type=sha,format=short
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
APP_PORT=${{ secrets.APP_PORT }}
deploy:
needs: build-and-push
runs-on: ubuntu-latest
if: ${{ github.actor != 'nektos/act' }}
steps:
- uses: actions/checkout@v4
with:
sparse-checkout: |
docker-compose.yml
sparse-checkout-cone-mode: false
- name: Upload docker-compose.yml
uses: appleboy/scp-action@v1
with:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USERNAME }}
key: ${{ secrets.REMOTE_SSH_KEY }}
source: docker-compose.yml
target: /opt/services/${{ env.SERVICE_NAME }}
- name: Deploy via SSH
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.REMOTE_HOST }}
username: ${{ secrets.REMOTE_USERNAME }}
key: ${{ secrets.REMOTE_SSH_KEY }}
script: |
set -e
if [ "$(docker ps -aq -f name=rule-engine)" ]; then
echo "Stopping and removing existing container..."
docker stop rule-engine || true
docker rm rule-engine || true
fi
export DOCKER_CONFIG=$(mktemp -d)
trap 'rm -rf "$DOCKER_CONFIG"' EXIT
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
cd /opt/services/${{ env.SERVICE_NAME }}
export IMAGE_NAME=${{ env.IMAGE_NAME }}:${{ env.TAG }}
# --- Environment Variables from Secrets/Vars ---
export REMOTE_HOST="${{ secrets.REMOTE_HOST }}"
export APP_PORT=${{ secrets.APP_PORT }}
# Database Settings
export DB_USER="${{ secrets.DB_USER }}"
export DB_PASSWORD="${{ secrets.DB_PASSWORD }}"
export DB_HOST="${{ secrets.DB_HOST }}"
export DB_PORT="${{ secrets.DB_PORT }}"
export DB_NAME="${{ secrets.DB_NAME }}"
# Redis Settings
export REDIS_PORT="${{ secrets.REDIS_PORT }}"
export REDIS_PASSWORD="${{ secrets.REDIS_PASSWORD }}"
# External Service
export BE_ROUTER_HOST=${{ vars.BE_ROUTER_HOST }}
export BE_ROUTER_PORT=${{ vars.BE_ROUTER_PORT }}
export GM_HOST=${{ vars.GM_HOST }}
export GM_PORT=${{ vars.GM_PORT }}
export STATE_MANAGER_HOST=${{ vars.STATE_MANAGER_HOST }}
export STATE_MANAGER_PORT=${{ vars.STATE_MANAGER_PORT }}
export SCENARIO_SERVICE_HOST=${{ vars.SCENARIO_SERVICE_HOST }}
export SCENARIO_SERVICE_PORT=${{ vars.SCENARIO_SERVICE_PORT }}
export RULE_ENGINE_HOST=${{ vars.RULE_ENGINE_HOST }}
export RULE_ENGINE_PORT=${{ vars.RULE_ENGINE_PORT }}
export LLM_GATEWAY_HOST=${{ vars.LLM_GATEWAY_HOST }}
export LLM_GATEWAY_PORT=${{ vars.LLM_GATEWAY_PORT }}
export WEB_HOST=${{ vars.WEB_HOST }}
export WEB_PORT=${{ vars.WEB_PORT }}
# Others
export LLM_MODEL_NAME="${{ vars.LLM_MODEL_NAME }}"
# Logic Settings
docker compose pull
docker compose up -d
docker image prune -f