Merge pull request #166 from rostilos/1.5.5-rc #26
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
| ############################################################################### | |
| # CodeCrow CI/CD Pipeline | |
| # | |
| # Triggers: push to main branch, or manual dispatch | |
| # | |
| # Flow: | |
| # 1. Checkout code (with submodules) | |
| # 2. Build & test Java artifacts (Maven + JaCoCo) | |
| # 3. Build all 5 Docker images | |
| # 4. Push images to GHCR | |
| # 5. SSH into server and run deployment script | |
| # | |
| # Required GitHub Secrets: | |
| # DEPLOY_SSH_KEY — Private SSH key for env | |
| # DEPLOY_HOST — Server IP | |
| # DEPLOY_USER — SSH user | |
| # DEPLOY_HOST_FINGERPRINT — Server SSH host key (ssh-keyscan -H <ip>) | |
| # ENV_INFERENCE_ORCHESTRATOR — Contents of inference-orchestrator/.env | |
| # ENV_RAG_PIPELINE — Contents of rag-pipeline/.env | |
| # ENV_WEB_FRONTEND — Contents of frontend/.env | |
| # GHCR_PAT — GitHub Personal Access Token for GHCR (optional, uses GITHUB_TOKEN if not set) | |
| ############################################################################### | |
| name: Deploy to Production | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| inputs: | |
| skip_build: | |
| description: "Skip build (deploy existing images on server)" | |
| required: false | |
| default: "false" | |
| concurrency: | |
| group: production-deploy | |
| cancel-in-progress: false | |
| env: | |
| DEPLOY_PATH: /opt/codecrow | |
| permissions: | |
| contents: read | |
| packages: write | |
| checks: write | |
| jobs: | |
| build: | |
| name: Build & Test → Docker Images | |
| runs-on: ubuntu-latest | |
| if: github.event.inputs.skip_build != 'true' | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| fetch-depth: 0 | |
| - name: Set up JDK 17 | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: temurin | |
| java-version: 17 | |
| cache: maven | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to the Container registry | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and Push (ci-build.sh) | |
| env: | |
| ENV_INFERENCE_ORCHESTRATOR: ${{ secrets.ENV_INFERENCE_ORCHESTRATOR }} | |
| ENV_RAG_PIPELINE: ${{ secrets.ENV_RAG_PIPELINE }} | |
| ENV_WEB_FRONTEND: ${{ secrets.ENV_WEB_FRONTEND }} | |
| GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }} | |
| run: | | |
| chmod +x deployment/ci/ci-build.sh | |
| deployment/ci/ci-build.sh | |
| - name: Publish test results | |
| if: always() | |
| uses: dorny/test-reporter@v1 | |
| with: | |
| name: Java Tests | |
| path: java-ecosystem/**/target/surefire-reports/*.xml | |
| reporter: java-junit | |
| - name: Upload test reports | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: surefire-reports | |
| path: java-ecosystem/**/target/surefire-reports/ | |
| retention-days: 7 | |
| deploy: | |
| name: Deploy to Server | |
| runs-on: ubuntu-latest | |
| needs: [build] | |
| if: always() && (needs.build.result == 'success' || github.event.inputs.skip_build == 'true') | |
| timeout-minutes: 15 | |
| environment: production | |
| steps: | |
| - name: Checkout (for compose file + deploy script) | |
| uses: actions/checkout@v4 | |
| - name: Setup SSH | |
| run: | | |
| mkdir -p ~/.ssh | |
| echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/deploy_key | |
| chmod 600 ~/.ssh/deploy_key | |
| # Use pre-registered host fingerprint instead of ssh-keyscan (MITM-safe) | |
| # Generate with: ssh-keyscan -H <server-ip> 2>/dev/null | |
| echo "${{ secrets.DEPLOY_HOST_FINGERPRINT }}" >> ~/.ssh/known_hosts | |
| - name: Upload docker-compose.prod.yml and deploy script | |
| run: | | |
| scp -i ~/.ssh/deploy_key \ | |
| deployment/docker-compose.prod.yml \ | |
| deployment/ci/server-deploy.sh \ | |
| ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}:${{ env.DEPLOY_PATH }}/ | |
| - name: Deploy on server | |
| run: | | |
| ssh -i ~/.ssh/deploy_key \ | |
| ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \ | |
| "chmod +x ${{ env.DEPLOY_PATH }}/server-deploy.sh && GITHUB_REPOSITORY_OWNER=${{ github.repository_owner }} ${{ env.DEPLOY_PATH }}/server-deploy.sh" | |
| - name: Verify deployment | |
| run: | | |
| ssh -i ~/.ssh/deploy_key \ | |
| ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} \ | |
| "cd ${{ env.DEPLOY_PATH }} && docker compose -f docker-compose.prod.yml ps --format 'table {{.Name}}\t{{.Status}}'" | |
| - name: Cleanup SSH key | |
| if: always() | |
| run: rm -f ~/.ssh/deploy_key |