diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2c8e117c..804e76a9 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -290,7 +290,7 @@ jobs: - name: Upload to UpYun if: steps.check-upload.outputs.need_upload == 'true' - timeout-minutes: 10 + timeout-minutes: 30 env: UPYUN_SERVICE: ${{ secrets.UPYUN_BUCKET }} UPYUN_OPERATOR: ${{ secrets.UPYUN_OPERATOR }} @@ -358,8 +358,28 @@ jobs: done echo "🔄 开始上传到 UpYun..." - timeout 480 "$UPX_BIN" sync public/ / -w 10 --delete --strong - timeout 30 "$UPX_BIN" put public/.build_hash /__build_hash + # ⚠️ 参数是踩过坑调出来的,别改回 -w 10 / --strong: + # 本 runner 在海外,UpYun 的 v0 接口对并发敏感。2026-10-02 连续两次失败, + # 现象是一批目录的 mkdir 全部 EOF: + # sync .../public/20210212 → /20210212 FAIL mkdir: Post "https://v0.api.upyun.com/...": EOF + # -w 10 + --strong(每文件强校验)把请求量放大到 UpYun 扛不住的量级。 + # 现在:并发 3、去掉 --strong(默认按 mtime/size 增量比对)、 + # 单次超时放宽到 25 分钟、整轮重试 3 次(sync 可重复执行,已传的会跳过)。 + UPYUN_OK=false + for attempt in 1 2 3; do + echo "⬆️ 上传尝试 $attempt/3(并发 3,无 --strong)" + if timeout 1500 "$UPX_BIN" sync public/ / -w 3 --delete; then + UPYUN_OK=true + break + fi + echo "⚠️ 第 $attempt/3 次失败(多为 EOF 瞬断),20 秒后重试" + sleep 20 + done + if [ "$UPYUN_OK" != "true" ]; then + echo "❌ UpYun 连续 3 次上传失败,国内源站仍是旧内容" + exit 1 + fi + timeout 60 "$UPX_BIN" put public/.build_hash /__build_hash echo "✅ UpYun 上传完成" - name: Push Image Optimizations @@ -564,8 +584,18 @@ jobs: echo "any_deployed=false" >> $GITHUB_OUTPUT fi + # 多吉云 CDN 只服务国内线路,回源是又拍云。 + # EdgeOne(境外) 部署成功 ≠ 国内源站已更新 —— UpYun 失败时刷新多吉云, + # 只会把同一份旧内容再拉一遍,看着"刷新成功"却毫无变化(2026-10-02 踩过)。 + if [ "$UPYUN_STATUS" = "success" ]; then + echo "cdn_refresh=true" >> $GITHUB_OUTPUT + else + echo "cdn_refresh=false" >> $GITHUB_OUTPUT + echo "⚠️ UpYun 状态为 $UPYUN_STATUS —— 国内源站(又拍云)未更新,跳过多吉云 CDN 刷新" + fi + - name: Refresh DogeCloud CDN - if: steps.deploy-status.outputs.any_deployed == 'true' + if: steps.deploy-status.outputs.cdn_refresh == 'true' env: DOGECLOUD_ACCESS_KEY: ${{ secrets.DOGECLOUD_ACCESS_KEY }} DOGECLOUD_SECRET_KEY: ${{ secrets.DOGECLOUD_SECRET_KEY }}