From 1f568bbfd1b7e76a40a2cdc514544668299523d7 Mon Sep 17 00:00:00 2001 From: zqlit Date: Sun, 4 Oct 2026 11:08:40 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20artifact=20=E6=94=B9=E4=B8=BA=E5=8D=95?= =?UTF-8?q?=E6=96=87=E4=BB=B6=20tar=20=E4=BC=A0=E9=80=92=EF=BC=88v3=20?= =?UTF-8?q?=E9=80=90=E6=96=87=E4=BB=B6=E4=B8=8A=E4=BC=A0=E6=97=B6=20Gitea?= =?UTF-8?q?=20finalize=20500=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 实测 run #56:upload-artifact@v3 传 public/ 目录时会逐文件上传 3216 个 blob(376MB),文件全部传完后 finalize 调用被 Gitea 拒绝: Finalize artifact upload - Attempt 1..5 of 5 failed: Request timeout ::error::Finalize artifact upload failed: Artifact service responded with 500 整轮 build 白跑约 30 分钟(v3 已越过 v4 的 'not supported on GHES' 报错点, 这是另一个独立问题)。 改法:build 侧先把 public/ 打成单个 public.tar.zst(无 zstd 时退 gzip), 只上传这 1 个文件 -> 上传是 1 次 PUT、finalize 常数级开销。 deploy-edgeone 侧下载后解包,产物结构因此完全确定(不再有「多一层 public/」的歧义),原 Normalize 步骤随之删除。 配套:中转机 sync.sh.new 增加「artifact 内 tar 包二次解包」(已上传服务器, 未生效)。 --- .github/workflows/deploy.yml | 65 ++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 18 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 97011cae..ff30344b 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -226,21 +226,44 @@ jobs: echo "file_count=${FILE_COUNT}" >> $GITHUB_OUTPUT echo "total_size=${TOTAL_SIZE}" >> $GITHUB_OUTPUT - - name: Upload build artifact (public/) + - name: Pack build output (single tarball) + id: pack + # ★ 必须打成「单文件」再上传,不能让 upload-artifact 直接传 public/ 目录。 + # + # run #56 实测(2026-10-04):archive v3 收目录时会「逐文件」上传 —— + # 3216 个文件、376MB 全部传完(日志可见 Processed file #3216 / 100%), + # 但紧接着的 finalize 调用被 Gitea 拒绝: + # Finalize artifact upload - Attempt 1..5 of 5 failed: Request timeout + # ::error::Finalize artifact upload failed: Artifact service responded with 500 + # 于是整轮 build 白跑约 30 分钟。文件一多,Gitea 侧的合并/登记就扛不住。 + # 打包成 1 个文件后,上传是 1 次 PUT、finalize 是常数级开销。 + # 顺带:tar.zst 也正是原 COS 链路用过的形态,中转机侧解包逻辑可直接复用。 + run: | + if command -v zstd >/dev/null 2>&1; then + tar -c public | zstd -3 -T0 -o public.tar.zst + F=public.tar.zst + else + # 兜底:万一 runner 镜像没带 zstd(gzip 一定在) + tar -czf public.tar.gz public + F=public.tar.gz + fi + echo "file=$F" >> $GITHUB_OUTPUT + ls -lh "$F" + + - name: Upload build artifact # 2026-10-04 起产物不再上传腾讯云 COS,改用 Gitea artifact 传递: # - deploy-edgeone 用 actions/download-artifact 直接拿(同 runner,零跨境) - # - 国内中转机用 Gitea API 下载 artifact zip(替代原先的「从 COS 下载」) + # - 国内中转机用 Gitea API 下载 artifact(替代原先的「从 COS 下载」) # # ★ 必须用 v3,不能用 v4:实测 v4 在 Gitea 上直接失败 —— # "@actions/artifact v2.0.0+, upload-artifact@v4+ and download-artifact@v4+ # are not currently supported on GHES."(Gitea 被识别为 GHES,未实现新版 # artifact 服务)。v3 走的是 Gitea 已实现的旧 artifact API。 - # v3 也没有 include-hidden-files 选项;隐藏文件能不能进 artifact 不可靠, - # 所以 hash 另外写了一份非隐藏的 public/build_hash.txt 兜底。 + # ★ path 只指向上一步打好的那 1 个文件(见上方 finalize 500 的教训)。 uses: actions/upload-artifact@v3 with: name: hugo-public - path: public/ + path: ${{ steps.pack.outputs.file }} retention-days: 7 - name: Report deploy status (built) @@ -430,28 +453,34 @@ jobs: - name: Download build artifact id: download-files - # 从 Gitea artifact 下载 public/(build job 上传的,同 runner 零跨境、零费用) + # 从 Gitea artifact 下载(build job 上传的,同 runner 零跨境、零费用) # ★ 必须与上传端同为 v3:v4 在 Gitea(被识别为 GHES)上不受支持。 uses: actions/download-artifact@v3 with: name: hugo-public - path: public/ + path: . - - name: Normalize artifact layout - # upload-artifact 对「目录路径」的打包语义存在版本/实现差异: - # 解出来的可能是 public/index.html(内容直接在根),也可能是 - # public/public/index.html(多一层目录)。这里统一拍平成 public/index.html, - # 免得 EdgeOne 部署时找不到入口、或站点多出一层 /public/ 前缀。 + - name: Unpack build artifact + # artifact 里只有 1 个打包文件(public.tar.zst / .tar.gz),解出来就是 + # public/index.html 在根。不再有 upload-artifact「目录语义」导致的 + # 「多一层 public/」问题,产物结构完全确定。 run: | - if [ ! -f public/index.html ] && [ -f public/public/index.html ]; then - echo "ℹ️ 检测到产物多一层 public/,已拍平" - mv public/public public__flat - rm -rf public - mv public__flat public + set -o pipefail + T=$(find . -maxdepth 1 -type f \( -name 'public.tar.zst' -o -name 'public.tar.gz' \) -print -quit) + if [ -z "$T" ]; then + echo "❌ artifact 里没找到 public.tar.zst / public.tar.gz" + ls -la + exit 1 fi + echo "ℹ️ 解包 $T ($(du -h "$T" | cut -f1))" + rm -rf public + case "$T" in + *.zst) zstd -dc "$T" | tar -x ;; + *) tar -xzf "$T" ;; + esac if [ ! -f public/index.html ]; then echo "❌ 产物结构异常:public/index.html 不存在" - find public -maxdepth 2 | head -20 + find . -maxdepth 2 | head -20 exit 1 fi echo "✅ public/index.html 就位,文件数 $(find public -type f | wc -l)"