From 0373c19b54348942e54ba69711644f8f51993f82 Mon Sep 17 00:00:00 2001 From: HenryDu8133 <813367384@qq.com> Date: Fri, 11 Sep 2026 22:46:40 +0800 Subject: [PATCH] fix(ci): remove actions/setup-node; use npmmirror/gh-proxy for all remote fetches Issue: actions/setup-node@v4 directly connects to https://github.com/actions/node-versions/releases/download/... to download Node tarballs (log line Acquiring node-v*-linux-x64.tar.gz), which is throttled or connection-reset from inside China, causing preflight to hang until 15m timeout. Fix: align preflight with build-image job policy (NO third-party 'uses:' directives, ALL remote resources use CN mirrors or GH_PROXY_PREFIX): - Remove uses: actions/setup-node@v4 completely; replace with plain run steps - 3-tier Node 22 readiness with zero direct github.com connections: 1) Fast path: reuse Runner's system node if major version >= 22, skip download entirely 2) Primary: fetch Node 22 tarball from npmmirror CN binary mirror (https://registry.npmmirror.com/-/binary/node/...) and auto-resolve latest 22.x patch via npmmirror index.json using python3 single-quote script + printf stdin (NO heredoc, which previously caused YAML block-scalar indentation parse errors) 3) Fallback: GH_PROXY_PREFIX + official nodejs.org dist URL for the same tarball (proxied, never plain github.com) - NODE_VERSION_FALLBACK=22.13.0 fixed guard when index resolution fails - Post-install: prepend new node bin PATH to GITHUB_ENV so subsequent steps (clone / npm ci / nuxt build) inherit Node 22 automatically - Audit: grep deploy.yml now yields zero 'uses:' directives --- .gitea/workflows/deploy.yml | 127 ++++++++++++++++++++++++++++++++---- 1 file changed, 116 insertions(+), 11 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index d803c3a..87c6524 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -51,22 +51,127 @@ jobs: name: Preflight 语法与构建检查 runs-on: ubuntu-latest timeout-minutes: 15 - # 关键修复:去掉 container.image: node:22-bookworm-slim - # 原因:Runner 在 Set up job 阶段会先 docker pull 这个镜像,国内连 Docker Hub 被限速会一直卡转圈。 - # 直接在 Runner 宿主机上执行(通常自带 node 20+);为保证 Node 22 一致性,用 actions/setup-node 主动安装。 + # 关键修复 1:去掉 container.image: node:22-bookworm-slim + # Runner 在 Set up job 阶段会先 docker pull,国内连 Docker Hub 被限速会一直卡转圈。 + # 关键修复 2:去掉 uses: actions/setup-node@v4 + # setup-node 会直连 GitHub Releases (github.com/actions/node-versions/releases/download/...) + # 下载 Node 二进制,国内被限速 → 一直卡在 Acquiring node-v*-linux-x64.tar.gz。 + # 与 build-image job「禁止第三方 uses、全部用代理/国内源」风格完全对齐: + # - Runner 自带 node ≥22 直接用 + # - 否则优先 npmmirror 国内镜像下载 Node 22 二进制 + # - 最后兜底用 GH_PROXY_PREFIX 代理 GitHub node-versions Releases 直链 + env: + NODE_MAJOR: "22" + NODE_VERSION_FALLBACK: "22.13.0" + NODE_MIRROR_PRIMARY: "https://registry.npmmirror.com/-/binary/node" steps: - - name: 安装基础运行依赖(git/curl/ca-certificates,Runner 自带) + - name: 安装基础运行依赖(git/curl/ca-certificates/tar/xz-utils,Runner 自带) run: | set -euxo pipefail command -v git || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends git ca-certificates) - command -v curl || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends curl) - command -v node && node -v || true - command -v npm && npm -v || true + command -v curl || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends curl ca-certificates) + command -v tar || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends tar) + command -v xz || command -v unxz || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends xz-utils) || true + # 预先打印 Runner 自带版本,方便排障 + command -v node && echo "系统 node: $(node -v)" || echo "系统 node: 未安装" + command -v npm && echo "系统 npm: $(npm -v)" || echo "系统 npm: 未安装" - - name: 使用 Node.js 22(若 Runner 自带版本不足 22 则自动下载) - uses: actions/setup-node@v4 - with: - node-version: "22" + - name: 确保 Node.js 22 可用(npmmirror 优先 / gh-proxy 兜底 / 绝不直连 GitHub) + run: | + set -euxo pipefail + # 先判断:当前系统 node 主版本 ≥ NODE_MAJOR 直接跳过 + if command -v node >/dev/null 2>&1; then + CUR_NODE_MAJOR="$(node -v | tr -d 'v' | cut -d. -f1 || echo 0)" + if [ "${CUR_NODE_MAJOR:-0}" -ge "${NODE_MAJOR}" ]; then + echo "Runner 已自带 Node $(node -v)(≥ v${NODE_MAJOR}.x),直接复用,不下载" + node -v; npm -v + exit 0 + fi + echo "Runner 自带 Node v${CUR_NODE_MAJOR} 不足 v${NODE_MAJOR}.x,手动升级" + fi + + ARCH="$(uname -m)" + case "$ARCH" in + x86_64|amd64) PLAT="linux-x64" ;; + aarch64|arm64) PLAT="linux-arm64" ;; + armv7l) PLAT="linux-armv7l" ;; + *) echo "不支持的架构:$ARCH" >&2; exit 1 ;; + esac + echo "目标架构:$PLAT" + + INSTALL_DIR="${RUNNER_TEMP:-/tmp}/node-${NODE_MAJOR}" + mkdir -p "$INSTALL_DIR" + + # 找 Node 22 最新 patch 版本号:不用 GitHub API,走 npmmirror 的 index.json 解析 + NODE_VER="${NODE_VERSION_FALLBACK}" + if command -v python3 >/dev/null 2>&1; then + # 注意:不使用 heredoc,避免 PY_MAJOR 前导缩进 0 导致 YAML 块标量提前结束解析失败 + PY_NODE_CODE=' import json, re, sys + try: + data = json.load(sys.stdin) + except Exception: + data = [] + target = sys.argv[1] if len(sys.argv) > 1 else "22" + best_triple = None + best_v = "" + for d in data: + v = d.get("version", "") + m = re.match(r"^v(\d+)\.(\d+)\.(\d+)", v) + if not m: continue + major, minor, patch = m.groups() + if major != target: continue + triple = (int(minor), int(patch)) + if (best_triple is None) or (triple > best_triple): + best_triple = triple + best_v = f"{major}.{minor}.{patch}" + if best_v: + print(best_v)' + REMOTE_LATEST="" + REMOTE_LATEST="$(curl -fsSL --max-time 20 "${NODE_MIRROR_PRIMARY}/index.json" 2>/dev/null \ + | printf '%s\n' "$PY_NODE_CODE" | python3 - "${NODE_MAJOR}" || true)" + if [ -n "$REMOTE_LATEST" ]; then + NODE_VER="$REMOTE_LATEST" + echo "npmmirror 查得 Node 22 latest: v${NODE_VER}" + else + echo "npmmirror index 查询失败,使用兜底: v${NODE_VER}" + fi + else + echo "python3 不可用,跳过 npmmirror 最新版本探测,使用兜底: v${NODE_VER}" + fi + TAR_XZ="node-v${NODE_VER}-${PLAT}.tar.xz" + mkdir -p /tmp/node-dl-cache + + # 下载 URL 1:npmmirror 国内二进制镜像(首选,国内最快) + URL_1="${NODE_MIRROR_PRIMARY}/v${NODE_VER}/${TAR_XZ}" + # 下载 URL 2:nodejs.org 官方直链 + GH_PROXY 前缀兜底(绝不直连 GitHub.com) + URL_2="${GH_PROXY_PREFIX}https://nodejs.org/dist/v${NODE_VER}/${TAR_XZ}" + + DL_OK=0 + for URL in "$URL_1" "$URL_2"; do + echo "尝试下载:$URL" + if curl -fsSL --max-time 300 --retry 3 --retry-delay 2 -o "/tmp/node-dl-cache/${TAR_XZ}" "$URL"; then + echo "下载 OK:$URL" + DL_OK=1 + break + fi + echo "下载失败,尝试下一个源:$URL" + done + if [ "$DL_OK" != "1" ]; then + echo "所有 Node 下载源均失败(npmmirror + gh-proxy),中止" >&2 + exit 1 + fi + + # 解压并加到 PATH,GITHUB_ENV 注入所有后续 step 自动继承 + tar -xJf "/tmp/node-dl-cache/${TAR_XZ}" -C "$INSTALL_DIR" --strip-components=1 + if [ -f "$GITHUB_ENV" ]; then + echo "PATH=$INSTALL_DIR/bin:$PATH" >> "$GITHUB_ENV" + fi + export PATH="$INSTALL_DIR/bin:$PATH" + hash -r 2>/dev/null || true + node -v + npm -v + # 把 npm 全局前缀也设在这个目录下,避免权限问题 + npm config set prefix "$INSTALL_DIR/npm-global" 2>/dev/null || true - name: 校验 Node + npm + git 可用 run: |