diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 59380d2c..897c9efd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -100,7 +100,8 @@ jobs: needs: pre-check if: | needs.pre-check.outputs.can_deploy == 'true' && - inputs.skip_font_subset != 'true' + inputs.skip_font_subset != 'true' && + (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') outputs: font_updated: ${{ steps.update.outputs.font_updated }} char_count: ${{ steps.stats.outputs.char_count }} @@ -326,6 +327,7 @@ jobs: name: hugo-public path: public/ retention-days: 1 + compression-level: 0 - name: Push Image Optimizations continue-on-error: true @@ -358,30 +360,75 @@ jobs: permissions: contents: read needs: build + outputs: + deployed: ${{ steps.check.outputs.deployed }} steps: - name: Start timing id: start-edgeone run: echo "start_time=$(date +%s)" >> $GITHUB_OUTPUT + - name: Check build hash cache + id: cache-check + uses: actions/cache/restore@v4 + with: + path: .last_deploy_hash + key: ${{ runner.os }}-deploy-edgeone-${{ needs.build.outputs.build_hash }} + restore-keys: | + ${{ runner.os }}-deploy-edgeone- + + - name: Check if deployment is needed + id: check + run: | + CURRENT_HASH="${{ needs.build.outputs.build_hash }}" + echo "当前 build_hash: $CURRENT_HASH" + + if [ -f .last_deploy_hash ]; then + LAST_HASH=$(cat .last_deploy_hash) + echo "上次部署 hash: $LAST_HASH" + if [ "$CURRENT_HASH" = "$LAST_HASH" ]; then + echo "✅ 构建产物无变化,跳过 EdgeOne 部署" + echo "deployed=false" >> $GITHUB_OUTPUT + echo "skip_reason=hash_match" >> $GITHUB_OUTPUT + exit 0 + fi + fi + + echo "🔄 构建产物有变化,需要部署到 EdgeOne" + echo "deployed=true" >> $GITHUB_OUTPUT + - name: Checkout code (for scripts) + if: steps.check.outputs.deployed == 'true' uses: actions/checkout@v4 with: fetch-depth: 0 - name: Download build artifact + if: steps.check.outputs.deployed == 'true' uses: actions/download-artifact@v4 with: name: hugo-public path: public/ - name: Deploy to EdgeOne Pages + if: steps.check.outputs.deployed == 'true' env: EDGEONE_API_TOKEN: ${{ secrets.EDGEONE_API_TOKEN }} run: | chmod +x scripts/deploy_edgeone.sh ./scripts/deploy_edgeone.sh hugo-blog ./public overseas + - name: Save deploy hash + if: steps.check.outputs.deployed == 'true' + run: echo "${{ needs.build.outputs.build_hash }}" > .last_deploy_hash + + - name: Save build hash cache + if: steps.check.outputs.deployed == 'true' + uses: actions/cache/save@v4 + with: + path: .last_deploy_hash + key: ${{ runner.os }}-deploy-edgeone-${{ needs.build.outputs.build_hash }} + - name: End timing id: end-edgeone run: | @@ -389,7 +436,12 @@ jobs: start_time=${{ steps.start-edgeone.outputs.start_time }} duration=$((end_time - start_time)) echo "duration=${duration}" >> $GITHUB_OUTPUT - echo "## ⏱️ Deploy EdgeOne 耗时: ${duration}秒" >> $GITHUB_STEP_SUMMARY + if [ "${{ steps.check.outputs.deployed }}" = "true" ]; then + echo "## ⏱️ Deploy EdgeOne 耗时: ${duration}秒" >> $GITHUB_STEP_SUMMARY + else + echo "## EdgeOne 部署已跳过(构建产物无变化)" >> $GITHUB_STEP_SUMMARY + echo "总耗时: ${duration}秒" >> $GITHUB_STEP_SUMMARY + fi # ============================================================ # Job 4: Deploy to UpYun (并行) @@ -400,19 +452,72 @@ jobs: permissions: contents: read needs: build + outputs: + deployed: ${{ steps.check.outputs.deployed }} steps: - name: Start timing id: start-upyun run: echo "start_time=$(date +%s)" >> $GITHUB_OUTPUT + - name: Check build hash cache + id: cache-check + uses: actions/cache/restore@v4 + with: + path: .last_deploy_hash + key: ${{ runner.os }}-deploy-upyun-${{ needs.build.outputs.build_hash }} + restore-keys: | + ${{ runner.os }}-deploy-upyun- + + - name: Check if deployment is needed + id: check + run: | + CURRENT_HASH="${{ needs.build.outputs.build_hash }}" + echo "当前 build_hash: $CURRENT_HASH" + + if [ -f .last_deploy_hash ]; then + LAST_HASH=$(cat .last_deploy_hash) + echo "上次部署 hash: $LAST_HASH" + if [ "$CURRENT_HASH" = "$LAST_HASH" ]; then + echo "✅ 构建产物无变化,跳过 UpYun 部署" + echo "deployed=false" >> $GITHUB_OUTPUT + echo "skip_reason=hash_match" >> $GITHUB_OUTPUT + exit 0 + fi + fi + + echo "🔄 构建产物有变化,需要部署到 UpYun" + echo "deployed=true" >> $GITHUB_OUTPUT + + - name: Start artifact download timing + if: steps.check.outputs.deployed == 'true' + id: start-upyun-download + run: echo "start_time=$(date +%s)" >> $GITHUB_OUTPUT + - name: Download build artifact + if: steps.check.outputs.deployed == 'true' uses: actions/download-artifact@v4 with: name: hugo-public path: public/ + - name: End artifact download timing + if: steps.check.outputs.deployed == 'true' + id: end-upyun-download + run: | + end_time=$(date +%s) + start_time=${{ steps.start-upyun-download.outputs.start_time }} + duration=$((end_time - start_time)) + echo "duration=${duration}" >> $GITHUB_OUTPUT + echo "## UpYun artifact download duration: ${duration}s" >> $GITHUB_STEP_SUMMARY + + - name: Start UpYun upload timing + if: steps.check.outputs.deployed == 'true' + id: start-upyun-upload + run: echo "start_time=$(date +%s)" >> $GITHUB_OUTPUT + - name: Deploy to UpYun + if: steps.check.outputs.deployed == 'true' uses: her-cat/upyun-deployer@v1.0.4 with: bucket: ${{ secrets.UPYUN_BUCKET }} @@ -421,24 +526,46 @@ jobs: dir: 'public' publish_dir: '/' + - name: Save deploy hash + if: steps.check.outputs.deployed == 'true' + run: echo "${{ needs.build.outputs.build_hash }}" > .last_deploy_hash + + - name: Save build hash cache + if: steps.check.outputs.deployed == 'true' + uses: actions/cache/save@v4 + with: + path: .last_deploy_hash + key: ${{ runner.os }}-deploy-upyun-${{ needs.build.outputs.build_hash }} + - name: End timing id: end-upyun run: | end_time=$(date +%s) - start_time=${{ steps.start-upyun.outputs.start_time }} - duration=$((end_time - start_time)) - echo "duration=${duration}" >> $GITHUB_OUTPUT - echo "## ⏱️ Deploy UpYun 耗时: ${duration}秒" >> $GITHUB_STEP_SUMMARY + total_start_time=${{ steps.start-upyun.outputs.start_time }} + total_duration=$((end_time - total_start_time)) + echo "duration=${total_duration}" >> $GITHUB_OUTPUT + + if [ "${{ steps.check.outputs.deployed }}" = "true" ]; then + upload_start_time=${{ steps.start-upyun-upload.outputs.start_time }} + upload_duration=$((end_time - upload_start_time)) + echo "upload_duration=${upload_duration}" >> $GITHUB_OUTPUT + echo "## Deploy UpYun total duration: ${total_duration}s" >> $GITHUB_STEP_SUMMARY + echo "## UpYun upload duration: ${upload_duration}s" >> $GITHUB_STEP_SUMMARY + else + echo "## UpYun 部署已跳过(构建产物无变化)" >> $GITHUB_STEP_SUMMARY + echo "总耗时: ${total_duration}s" >> $GITHUB_STEP_SUMMARY + fi # ============================================================ - # Job 5: CDN Refresh & Notifications (在所有部署完成后) + # Job 5: CDN Refresh & Notifications (after all deployments) # ============================================================ finalize: runs-on: ubuntu-latest timeout-minutes: 5 permissions: contents: read - needs: [deploy-edgeone, deploy-upyun] + needs: [pre-check, subset-fonts, build, deploy-edgeone, deploy-upyun] + if: always() && needs.build.result == 'success' && needs.deploy-edgeone.result == 'success' && needs.deploy-upyun.result == 'success' steps: - name: Start timing @@ -459,7 +586,23 @@ jobs: - name: Install Node.js dependencies run: npm ci + - name: Determine deployment status + id: deploy-status + run: | + EDGEONE_DEPLOYED="${{ needs.deploy-edgeone.outputs.deployed }}" + UPYUN_DEPLOYED="${{ needs.deploy-upyun.outputs.deployed }}" + + echo "EdgeOne deployed: $EDGEONE_DEPLOYED" + echo "UpYun deployed: $UPYUN_DEPLOYED" + + if [ "$EDGEONE_DEPLOYED" = "true" ] || [ "$UPYUN_DEPLOYED" = "true" ]; then + echo "any_deployed=true" >> $GITHUB_OUTPUT + else + echo "any_deployed=false" >> $GITHUB_OUTPUT + fi + - name: Refresh DogeCloud CDN + if: steps.deploy-status.outputs.any_deployed == 'true' env: DOGECLOUD_ACCESS_KEY: ${{ secrets.DOGECLOUD_ACCESS_KEY }} DOGECLOUD_SECRET_KEY: ${{ secrets.DOGECLOUD_SECRET_KEY }} @@ -467,6 +610,7 @@ jobs: run: node scripts/refresh_cdn.js - name: Generate Notification Report + if: steps.deploy-status.outputs.any_deployed == 'true' continue-on-error: true run: node scripts/generate_notification_report.js @@ -480,7 +624,17 @@ jobs: exit 0 fi - MESSAGE="✅ **部署成功** + EDGEONE_STATUS="${{ needs.deploy-edgeone.outputs.deployed == 'true' && '✅' || '⏭️ 跳过' }}" + UPYUN_STATUS="${{ needs.deploy-upyun.outputs.deployed == 'true' && '✅' || '⏭️ 跳过' }}" + CDN_STATUS="${{ steps.deploy-status.outputs.any_deployed == 'true' && '✅' || '⏭️ 跳过' }}" + + if [ "${{ steps.deploy-status.outputs.any_deployed }}" = "true" ]; then + TITLE="✅ **部署成功**" + else + TITLE="ℹ️ **无变化,跳过部署**" + fi + + MESSAGE="${TITLE} 📦 项目: ${{ github.repository }} 🌿 分支: ${{ github.ref_name }} @@ -488,9 +642,9 @@ jobs: 🕐 时间: $(date +'%Y-%m-%d %H:%M:%S') 📊 部署目标: - - EdgeOne Pages ✓ - - UpYun ✓ - - CDN 刷新 ✓" + - EdgeOne Pages ${EDGEONE_STATUS} + - UpYun ${UPYUN_STATUS} + - CDN 刷新 ${CDN_STATUS}" curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \ -d chat_id="${TELEGRAM_CHAT_ID}" \ @@ -506,21 +660,33 @@ jobs: exit 0 fi + EDGEONE_STATUS="${{ needs.deploy-edgeone.outputs.deployed == 'true' && '✅' || '⏭️ 跳过' }}" + UPYUN_STATUS="${{ needs.deploy-upyun.outputs.deployed == 'true' && '✅' || '⏭️ 跳过' }}" + CDN_STATUS="${{ steps.deploy-status.outputs.any_deployed == 'true' && '✅' || '⏭️ 跳过' }}" + + if [ "${{ steps.deploy-status.outputs.any_deployed }}" = "true" ]; then + TITLE="✅ **部署成功**" + else + TITLE="ℹ️ **无变化,跳过部署**" + fi + CURRENT_TIME=$(date +'%Y-%m-%d %H:%M:%S') curl -s -X POST "${FEISHU_WEBHOOK_URL}" \ -H "Content-Type: application/json" \ -d '{ "msg_type": "text", "content": { - "text": "✅ **部署成功**\n\n📦 项目: ${{ github.repository }}\n🌿 分支: ${{ github.ref_name }}\n🔗 Commit: ${{ github.sha }}\n🕐 时间: '"${CURRENT_TIME}"'\n\n📊 部署目标:\n- EdgeOne Pages ✓\n- UpYun ✓\n- CDN 刷新 ✓" + "text": "'"${TITLE}"'\n\n📦 项目: ${{ github.repository }}\n🌿 分支: ${{ github.ref_name }}\n🔗 Commit: ${{ github.sha }}\n🕐 时间: '"${CURRENT_TIME}"'\n\n📊 部署目标:\n- EdgeOne Pages '"${EDGEONE_STATUS}"'\n- UpYun '"${UPYUN_STATUS}"'\n- CDN 刷新 '"${CDN_STATUS}"'" } }' - name: Get current date (CN) + if: steps.deploy-status.outputs.any_deployed == 'true' id: date run: echo "date=$(date +'%Y-%m-%d %H:%M:%S')" >> $GITHUB_OUTPUT - name: Send deployment notification + if: steps.deploy-status.outputs.any_deployed == 'true' uses: dawidd6/action-send-mail@v3 with: server_address: smtp.qq.com @@ -541,18 +707,33 @@ jobs: start_time=${{ steps.start-finalize.outputs.start_time }} finalize_duration=$((end_time - start_time)) + EDGEONE_DEPLOYED="${{ needs.deploy-edgeone.outputs.deployed }}" + UPYUN_DEPLOYED="${{ needs.deploy-upyun.outputs.deployed }}" + + if [ "$EDGEONE_DEPLOYED" = "true" ]; then + EDGEONE_DISPLAY="✅ 已部署" + else + EDGEONE_DISPLAY="⏭️ 跳过(无变化)" + fi + + if [ "$UPYUN_DEPLOYED" = "true" ]; then + UPYUN_DISPLAY="✅ 已部署" + else + UPYUN_DISPLAY="⏭️ 跳过(无变化)" + fi + echo "## ⏱️ 部署耗时统计" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "| 阶段 | 耗时 |" >> $GITHUB_STEP_SUMMARY + echo "| 阶段 | 状态 |" >> $GITHUB_STEP_SUMMARY echo "|------|------|" >> $GITHUB_STEP_SUMMARY - echo "| Pre-check | ${{ needs.pre-check.result == 'success' && '✅' || '⏭️' }} |" >> $GITHUB_STEP_SUMMARY - echo "| Subset-fonts | ${{ needs.build.result == 'success' && '✅' || '⏭️' }} |" >> $GITHUB_STEP_SUMMARY - echo "| Build | ${{ needs.build.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY - echo "| Deploy EdgeOne | ${{ needs.deploy-edgeone.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY - echo "| Deploy UpYun | ${{ needs.deploy-upyun.result == 'success' && '✅' || '❌' }} |" >> $GITHUB_STEP_SUMMARY - echo "| Finalize | ✅ (${finalize_duration}秒) |" >> $GITHUB_STEP_SUMMARY + echo "| Pre-check | ${{ needs.pre-check.result == 'success' && '✅ 成功' || needs.pre-check.result == 'skipped' && '⏭️ 跳过' || '❌ 失败' }} |" >> $GITHUB_STEP_SUMMARY + echo "| Subset-fonts | ${{ needs.subset-fonts.result == 'success' && '✅ 成功' || needs.subset-fonts.result == 'skipped' && '⏭️ 跳过' || '❌ 失败' }} |" >> $GITHUB_STEP_SUMMARY + echo "| Build | ${{ needs.build.result == 'success' && '✅ 成功' || '❌ 失败' }} |" >> $GITHUB_STEP_SUMMARY + echo "| Deploy EdgeOne | ${EDGEONE_DISPLAY} |" >> $GITHUB_STEP_SUMMARY + echo "| Deploy UpYun | ${UPYUN_DISPLAY} |" >> $GITHUB_STEP_SUMMARY + echo "| Finalize | ✅ 成功 (${finalize_duration}秒) |" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY - echo "**总计耗时:** ${finalize_duration}秒 (finalize 阶段)" >> $GITHUB_STEP_SUMMARY + echo "**Finalize 阶段耗时:** ${finalize_duration}秒" >> $GITHUB_STEP_SUMMARY # ============================================================ # Job 6: Failure Notification (失败通知) @@ -562,8 +743,8 @@ jobs: timeout-minutes: 3 permissions: contents: read - needs: [build, deploy-edgeone, deploy-upyun, finalize] - if: failure() + needs: [pre-check, subset-fonts, build, deploy-edgeone, deploy-upyun, finalize] + if: always() && (needs.pre-check.result == 'failure' || needs.build.result == 'failure' || needs.deploy-edgeone.result == 'failure' || needs.deploy-upyun.result == 'failure' || needs.finalize.result == 'failure') steps: - name: Send Telegram failure notification diff --git a/scripts/__pycache__/subset-font-safe.cpython-312.pyc b/scripts/__pycache__/subset-font-safe.cpython-312.pyc new file mode 100644 index 00000000..fb772214 Binary files /dev/null and b/scripts/__pycache__/subset-font-safe.cpython-312.pyc differ