From 4efdd20ff78a471ae476cb7bdade085ea086bdce Mon Sep 17 00:00:00 2001 From: gouki Date: Mon, 10 Aug 2026 00:01:14 +0000 Subject: [PATCH] =?UTF-8?q?fix(ci):=20=E7=9C=9F=E6=AD=A3=E6=A0=B9=E5=9B=A0?= =?UTF-8?q?=E2=80=94=E2=80=94Node=E4=B8=8B=E8=BD=BD=E6=88=AA=E6=96=AD?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E7=94=A8sha256=E7=A1=AC=E6=A0=A1=E9=AA=8C+?= =?UTF-8?q?=E9=95=9C=E5=83=8F=E6=BA=90=E4=BC=98=E5=85=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因:unofficial-builds.nodejs.org 在亚洲带宽极低,wget --timeout 只限单次读取,慢速断流仍返回成功,CI拿到截断的gzip(15MB/55MB), 解压出损坏二进制报 symbol not found(并非glibc/musl混用)。 修复: 1. sha256 硬校验拦截一切假文件(musl:8d96de02... glibc:e05a4d65...) 2. musl 版优先 npmmirror 镜像(实测与官方sha256一致),unofficial 后备 3. 循环换源重试,全部失败才报错 4. wget 改用 busybox 兼容短参数 -t/-T --- .gitea/workflows/miniapp-preview.yml | 41 +++++++++++++++++++--------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/.gitea/workflows/miniapp-preview.yml b/.gitea/workflows/miniapp-preview.yml index 5ea2c00..35ad481 100644 --- a/.gitea/workflows/miniapp-preview.yml +++ b/.gitea/workflows/miniapp-preview.yml @@ -35,27 +35,42 @@ jobs: echo "复用缓存 Node 工具链" else # 清理旧缓存:Alpine busybox mv 遇已存在目录会合并而非替换, - # 残留的 glibc 版 node 会污染 musl 环境导致 symbol not found + # 残留的旧版 node 会污染环境导致 symbol not found rm -rf "$TOOLDIR" mkdir -p "$TOOLDIR" # 探测 libc:Alpine(musl) 用 unofficial musl 构建,其余用官方 glibc 构建(tar.gz,busybox tar 不支持 xz) + # 关键教训:unofficial-builds 在亚洲带宽极低,wget --timeout 只限单次读取, + # 慢速断流仍返回成功,产生截断的 gzip(解压出损坏二进制报 symbol not found)。 + # 必须用 sha256 硬校验,不匹配则换源重试。 if ldd --version 2>&1 | grep -qi musl || [ ! -e /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ]; then NODE_DIST="node-v22.12.0-linux-x64-musl" - # 多源下载:unofficial-builds 海外源 + npmmirror 镜像(busybox wget 自动跟随 302) - wget -q --tries=2 --timeout=120 -O "$TOOLDIR/node.tgz" \ - "https://unofficial-builds.nodejs.org/download/release/v22.12.0/$NODE_DIST.tar.gz" \ - || wget -q --tries=2 --timeout=120 -O "$TOOLDIR/node.tgz" \ - "https://registry.npmmirror.com/-/binary/node-unofficial-builds/v22.12.0/$NODE_DIST.tar.gz" + NODE_SHA="8d96de0293fc3978d09e2a3fee68c66bca4efcca90f52105e6f7463636e97308" + # 优先 npmmirror(国内/亚洲快),unofficial-builds 作为后备 + URLS="https://registry.npmmirror.com/-/binary/node-unofficial-builds/v22.12.0/$NODE_DIST.tar.gz + https://unofficial-builds.nodejs.org/download/release/v22.12.0/$NODE_DIST.tar.gz" else NODE_DIST="node-v22.12.0-linux-x64" - wget -q --tries=2 --timeout=120 -O "$TOOLDIR/node.tgz" \ - "https://nodejs.org/dist/v22.12.0/$NODE_DIST.tar.gz" \ - || wget -q --tries=2 --timeout=120 -O "$TOOLDIR/node.tgz" \ - "https://mirrors.aliyun.com/nodejs-release/v22.12.0/$NODE_DIST.tar.gz" + NODE_SHA="e05a4d65232ae2b27b3d77da2e368522fb46b923335b8e0d5f77624c32484044" + URLS="https://nodejs.org/dist/v22.12.0/$NODE_DIST.tar.gz + https://mirrors.aliyun.com/nodejs-release/v22.12.0/$NODE_DIST.tar.gz" fi - # 校验下载结果:文件存在且是 gzip 格式(防止半截下载/错误页残留污染缓存) - test -s "$TOOLDIR/node.tgz" - head -c 2 "$TOOLDIR/node.tgz" | od -An -tx1 | grep -q "1f 8b" + DL_OK="" + for url in $URLS; do + echo "尝试下载: $url" + if wget -t 2 -T 120 -q -O "$TOOLDIR/node.tgz" "$url"; then + # sha256 硬校验(busybox 有 sha256sum):拦截截断/错误页等假文件 + if [ "$(sha256sum "$TOOLDIR/node.tgz" | cut -d' ' -f1)" = "$NODE_SHA" ]; then + echo "下载成功且校验通过" + DL_OK=1 + break + fi + echo "sha256 校验失败,文件可能截断,尝试下一源" + else + echo "wget 下载失败,尝试下一源" + fi + rm -f "$TOOLDIR/node.tgz" + done + test -n "$DL_OK" || { echo "::error::所有下载源均失败或校验不通过"; exit 1; } tar -C "$TOOLDIR" -xzf "$TOOLDIR/node.tgz" mv "$TOOLDIR/$NODE_DIST" "$TOOLDIR/node" rm -f "$TOOLDIR/node.tgz"