name: MCP Server CI/CD on: push: branches: - main - develop paths: - 'services/mcp-server/**' - '.github/workflows/mcp-server-deploy.yml' pull_request: branches: - main - develop paths: - 'services/mcp-server/**' workflow_dispatch: inputs: environment: description: 'Deployment environment' required: true default: 'staging' type: choice options: - staging - production env: REGISTRY: ghcr.io IMAGE_NAME: ${{ github.repository }}/mcp-server AZURE_REGISTRY: taiji.azurecr.io AZURE_IMAGE_NAME: taiji-mcp-server jobs: build-and-push: name: Build and Push Docker Image runs-on: ubuntu-latest permissions: contents: read packages: write id-token: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Log in to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Log in to Azure Container Registry if: github.event_name == 'push' && github.ref == 'refs/heads/main' uses: docker/login-action@v3 with: registry: ${{ env.AZURE_REGISTRY }} username: ${{ secrets.AZURE_CLIENT_ID }} password: ${{ secrets.AZURE_CLIENT_SECRET }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: | ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} ${{ env.AZURE_REGISTRY }}/${{ env.AZURE_IMAGE_NAME }} tags: | type=ref,event=branch type=ref,event=pr type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix={{branch}}- type=raw,value=latest,enable={{is_default_branch}} - name: Build and push Docker image uses: docker/build-push-action@v5 with: context: ./services/mcp-server file: ./services/mcp-server/Dockerfile push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max platforms: linux/amd64,linux/arm64 - name: Generate build summary run: | echo "### 🚀 Build Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "**Image:** \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}\`" >> $GITHUB_STEP_SUMMARY echo "**Tags:**" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY echo "${{ steps.meta.outputs.tags }}" >> $GITHUB_STEP_SUMMARY echo "\`\`\`" >> $GITHUB_STEP_SUMMARY deploy-staging: name: Deploy to Staging needs: build-and-push if: github.event_name == 'push' && github.ref == 'refs/heads/develop' runs-on: ubuntu-latest environment: name: staging url: https://staging-mcp.taiji-ai.com steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up kubectl uses: azure/setup-kubectl@v3 with: version: 'v1.28.0' - name: Configure kubectl run: | mkdir -p $HOME/.kube echo "${{ secrets.KUBE_CONFIG_STAGING }}" | base64 -d > $HOME/.kube/config - name: Update deployment image run: | kubectl set image deployment/mcp-server \ mcp-server=${{ env.AZURE_REGISTRY }}/${{ env.AZURE_IMAGE_NAME }}:develop \ -n taiji-ai - name: Wait for rollout run: | kubectl rollout status deployment/mcp-server -n taiji-ai --timeout=5m - name: Verify deployment run: | kubectl get pods -n taiji-ai -l app=mcp-server kubectl get svc -n taiji-ai -l app=mcp-server deploy-production: name: Deploy to Production needs: build-and-push if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: name: production url: https://mcp.taiji-ai.com steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up kubectl uses: azure/setup-kubectl@v3 with: version: 'v1.28.0' - name: Configure kubectl run: | mkdir -p $HOME/.kube echo "${{ secrets.KUBE_CONFIG_PRODUCTION }}" | base64 -d > $HOME/.kube/config - name: Update deployment image run: | kubectl set image deployment/mcp-server \ mcp-server=${{ env.AZURE_REGISTRY }}/${{ env.AZURE_IMAGE_NAME }}:latest \ -n taiji-ai - name: Wait for rollout run: | kubectl rollout status deployment/mcp-server -n taiji-ai --timeout=5m - name: Verify deployment run: | kubectl get pods -n taiji-ai -l app=mcp-server kubectl get svc -n taiji-ai -l app=mcp-server - name: Send deployment notification if: always() uses: 8398a7/action-slack@v3 with: status: ${{ job.status }} text: 'MCP Server deployment to production: ${{ job.status }}' webhook_url: ${{ secrets.SLACK_WEBHOOK }} env: SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }} health-check: name: Post-Deployment Health Check needs: [deploy-staging, deploy-production] if: always() && (needs.deploy-staging.result == 'success' || needs.deploy-production.result == 'success') runs-on: ubuntu-latest steps: - name: Determine environment id: env run: | if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then echo "url=https://mcp.taiji-ai.com" >> $GITHUB_OUTPUT echo "env=production" >> $GITHUB_OUTPUT else echo "url=https://staging-mcp.taiji-ai.com" >> $GITHUB_OUTPUT echo "env=staging" >> $GITHUB_OUTPUT fi - name: Health check run: | echo "Checking health endpoint: ${{ steps.env.outputs.url }}/health" for i in {1..10}; do if curl -f -s "${{ steps.env.outputs.url }}/health" > /dev/null; then echo "✅ Health check passed!" exit 0 fi echo "Attempt $i failed, waiting 10s..." sleep 10 done echo "❌ Health check failed after 10 attempts" exit 1 - name: API smoke test run: | echo "Running API smoke tests..." # Test agents endpoint curl -f -s "${{ steps.env.outputs.url }}/api/v1/agents" || exit 1 # Test health endpoint curl -f -s "${{ steps.env.outputs.url }}/health" || exit 1 echo "✅ Smoke tests passed!"