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: # 网络连接测试 - name: Test network connectivity run: | echo "Testing network connectivity to Gitea server..." MAX_RETRIES=5 RETRY_DELAY=10 for i in $(seq 1 $MAX_RETRIES); do echo "Network test attempt $i/$MAX_RETRIES" if curl -s --connect-timeout 10 -f http://192.168.31.14:14200 > /dev/null; then echo "✅ Gitea server is reachable" exit 0 else echo "❌ Network test failed, waiting $RETRY_DELAY seconds..." sleep $RETRY_DELAY fi done echo "❌ All network tests failed" exit 1 - name: Checkout code uses: https://gitea.com/actions/checkout@v3 # 添加重试策略 continue-on-error: true # 手动重试逻辑 - name: Retry checkout if failed if: steps.checkout.outcome == 'failure' run: | echo "First checkout attempt failed, retrying..." MAX_RETRIES=3 RETRY_DELAY=15 for i in $(seq 1 $MAX_RETRIES); do echo "Retry attempt $i/$MAX_RETRIES" # 清理可能的部分检出 rm -rf .git || true git clean -fdx || true # 使用git命令直接检出 git init git remote add origin http://192.168.31.14:14200/${{ gitea.repository }} git config http.extraHeader "Authorization: Bearer ${{ secrets.GITEA_TOKEN }}" if git fetch --depth=1 origin "${{ gitea.ref }}"; then git checkout FETCH_HEAD echo "Checkout successful on retry $i" exit 0 fi echo "Retry $i failed, waiting $RETRY_DELAY seconds..." sleep $RETRY_DELAY done echo "All checkout attempts failed" exit 1 - name: Cleanup old containers run: | docker compose -p $COMPOSE_PROJECT_NAME down || true docker rmi $IMAGE_NAME || true - name: Build new image run: | RETRIES=20 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