name: CD on: push: branches: [main] paths-ignore: - 'docs/**' - '*.md' workflow_dispatch: # 沿用 AIOPS 設計: 新 commit 自動取消舊 workflow concurrency: group: cd-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: REGISTRY: 192.168.0.110:5000 IMAGE_PREFIX: library/awoooi jobs: # ==================== Build & Push Images ==================== build-images: name: Build & Push Images runs-on: self-hosted strategy: matrix: app: [web, api] steps: - uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 with: # 修復: Harbor 是 HTTP,需要設定 insecure registry driver-opts: | network=host buildkitd-config-inline: | [registry."192.168.0.110:5000"] http = true insecure = true - name: Login to WOOO Harbor uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ secrets.HARBOR_USER }} password: ${{ secrets.HARBOR_PASSWORD }} - name: Generate image tag id: tag run: | SHA=$(git rev-parse --short HEAD) RUN_ID=${{ github.run_id }} echo "tag=${SHA}-${RUN_ID}" >> $GITHUB_OUTPUT - name: Build & Push to Harbor uses: docker/build-push-action@v5 with: context: . file: apps/${{ matrix.app }}/Dockerfile push: true tags: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.app }}:${{ steps.tag.outputs.tag }} cache-from: type=gha cache-to: type=gha,mode=max - name: Output image tag run: | echo "::notice::Image pushed: ${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-${{ matrix.app }}:${{ steps.tag.outputs.tag }}" # ==================== Deploy to Production ==================== # Memory 鐵律: 禁止 UAT,只有 Dev + Prod deploy-prod: name: Deploy to Production runs-on: self-hosted needs: build-images environment: production steps: - uses: actions/checkout@v4 - name: Setup Kubeconfig run: | mkdir -p ~/.kube echo "${{ secrets.KUBE_CONFIG_PROD }}" | base64 -d > ~/.kube/config chmod 600 ~/.kube/config - name: Generate image tag id: tag run: | SHA=$(git rev-parse --short HEAD) RUN_ID=${{ github.run_id }} echo "tag=${SHA}-${RUN_ID}" >> $GITHUB_OUTPUT - name: Deploy with Kustomize run: | cd k8s/overlays/prod kustomize edit set image \ awoooi-web=${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-web:${{ steps.tag.outputs.tag }} \ awoooi-api=${{ env.REGISTRY }}/${{ env.IMAGE_PREFIX }}-api:${{ steps.tag.outputs.tag }} kubectl apply -k . - name: Wait for rollout run: | kubectl rollout status deployment/awoooi-web -n awoooi --timeout=300s kubectl rollout status deployment/awoooi-api -n awoooi --timeout=300s - name: Health check run: | sleep 10 curl -f https://api.awoooi.wooo.work/api/v1/health || exit 1 - name: Notify Telegram on Success if: success() run: | curl -s -X POST "https://api.telegram.org/bot${{ secrets.OPENCLAW_TG_BOT_TOKEN }}/sendMessage" \ -d chat_id="${{ secrets.OPENCLAW_TG_CHAT_ID }}" \ -d text="✅ *AWOOOI 部署成功*%0A%0ACommit: \`${{ github.sha }}\`%0ABranch: \`${{ github.ref_name }}\`%0AWorkflow: [查看](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" \ -d parse_mode="Markdown" - name: Notify Telegram on Failure if: failure() run: | curl -s -X POST "https://api.telegram.org/bot${{ secrets.OPENCLAW_TG_BOT_TOKEN }}/sendMessage" \ -d chat_id="${{ secrets.OPENCLAW_TG_CHAT_ID }}" \ -d text="❌ *AWOOOI 部署失敗*%0A%0ACommit: \`${{ github.sha }}\`%0ABranch: \`${{ github.ref_name }}\`%0AWorkflow: [查看](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})" \ -d parse_mode="Markdown"