name: Docker Build & Deploy on: workflow_dispatch: push: branches: [ main ] env: COMPOSE_PROJECT_NAME: emailbill IMAGE_NAME: emailbill-app jobs: build: name: Build Docker Image runs-on: ubuntu-latest steps: # ✅ 使用 Gitea 兼容的代码检出方式 - name: Checkout code uses: https://gitea.com/actions/checkout@v3 with: gitea-server: http://192.168.31.14:14200 token: ${{ secrets.GITEA_TOKEN }} ref: ${{ gitea.ref }} # 必须传递 Gitea 的 ref 参数 - name: Cleanup old containers run: | docker compose -p $COMPOSE_PROJECT_NAME down || true docker rmi $IMAGE_NAME || true - name: Build new image run: | RETRIES=3 DELAY=10 count=0 until docker build -t $IMAGE_NAME .; do count=$((count+1)) if [ $count -ge $RETRIES ]; then echo "Build failed after $RETRIES attempts" exit 1 fi echo "Build failed. Retrying in $DELAY seconds... ($count/$RETRIES)" sleep $DELAY done deploy: name: Deploy to Production runs-on: ubuntu-latest needs: build environment: production steps: - name: Checkout code uses: https://gitea.com/actions/checkout@v3 - name: Start containers run: | docker compose -p $COMPOSE_PROJECT_NAME down # 添加重试逻辑 RETRIES=3 DELAY=10 count=0 until docker compose -p $COMPOSE_PROJECT_NAME up -d --build; do count=$((count+1)) if [ $count -ge $RETRIES ]; then echo "Deployment failed after $RETRIES attempts" exit 1 fi echo "Deployment failed. Retrying in $DELAY seconds... ($count/$RETRIES)" sleep $DELAY done cleanup: name: Cleanup Dangling Images runs-on: ubuntu-latest needs: deploy if: always() steps: - name: Remove dangling images run: | docker rm $(docker images -f "dangling=true" -q) || true echo "Cleanup completed." notify: name: WeChat Notification runs-on: ubuntu-latest needs: [build, deploy] if: always() steps: - name: Send WeChat Notification run: | # 判断结果:只有 build 和 deploy 都成功才算成功 if [[ "${{ needs.build.result }}" == "success" && "${{ needs.deploy.result }}" == "success" ]]; then MSG_TITLE="构建并部署成功" RESULT_ICON="✅" MSG_COLOR="info" else MSG_TITLE="自动部署发现异常" RESULT_ICON="❌" MSG_COLOR="warning" fi WEBHOOK_URL="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=96f9fa23-a959-4492-ac3a-7415fae19680" # 准备 Markdown 内容 cat < wechat_payload.json { "msgtype": "markdown", "markdown": { "content": "### $RESULT_ICON $MSG_TITLE\n> **项目**: [${{ gitea.repository }}](${{ gitea.server_url }}/${{ gitea.repository }})\n> **状态**: $MSG_TITLE\n> **分支**: \`${{ gitea.ref_name }}\`\n> **触发者**: ${{ gitea.actor }}\n> **任务编号**: [#${{ gitea.run_number }}](${{ gitea.server_url }}/${{ gitea.repository }}/actions/runs/${{ gitea.run_id }})\n> **构建状态**: ${{ needs.build.result || 'skipped' }}\n> **部署状态**: ${{ needs.deploy.result || 'skipped' }}\n> **提交详情**: [${{ gitea.sha }}](${{ gitea.server_url }}/${{ gitea.repository }}/commit/${{ gitea.sha }})" } } EOF # 添加重试逻辑 RETRIES=3 DELAY=5 count=0 # 使用 -f 让 curl 在 HTTP 错误时返回非零退出码 until curl -s -f -X POST "$WEBHOOK_URL" \ -H "Content-Type: application/json" \ -d @wechat_payload.json; do count=$((count+1)) if [ $count -ge $RETRIES ]; then echo "WeChat notification failed after $RETRIES attempts" exit 1 fi echo "Notification failed. Retrying in $DELAY seconds... ($count/$RETRIES)" sleep $DELAY done