Merge branch 'dev' #128
This file contains hidden or 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: 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 |