ci: preflight npm 升级到 11.x 以匹配 lockfile,修复 npm ci --install-links 报错

- 根因: 本地 Node 24/npm 11.6.2 生成的 package-lock 与 Runner Node 22/npm 10.x 不兼容
- 修复: Preflight 安装依赖前先 sudo npm install -g npm@^11.6.2 对齐版本
- 增强: MAX_RETRY 2→3,失败时打印 node/npm/lockfileVersion 并附带自检命令
This commit is contained in:
2026-09-18 20:34:55 +08:00
parent 92704d6637
commit de52e4124c
+33 -6
View File
@@ -211,9 +211,26 @@ jobs:
set -euo pipefail
for pair in "OAUTH_REDIRECT_URI:${OAUTH_REDIRECT_URI:-}" "OAUTH_STATE_SECRET:${OAUTH_STATE_SECRET:-}" "AGGREGATE_OAUTH_APP_ID:${AGGREGATE_OAUTH_APP_ID:-}" "AGGREGATE_OAUTH_APP_KEY:${AGGREGATE_OAUTH_APP_KEY:-}" "AGGREGATE_OAUTH_LOGIN_TYPE:${AGGREGATE_OAUTH_LOGIN_TYPE:-}" "AGGREGATE_OAUTH_ENDPOINT:${AGGREGATE_OAUTH_ENDPOINT:-}"; do K="${pair%%:*}"; V="${pair#*:}"; if [ -n "${V}" ]; then printf '%s="%s"\n' "$K" "$V" >> "$GITHUB_ENV"; echo "[OAuth-secrets] $K=已注入 (len=${#V})"; else echo "[OAuth-secrets] $K=未配置(Repository Secrets 中缺失或为空)"; fi; done; echo "[OAuth-secrets] 写入完成;后续所有 step 都会自动把上述变量作为进程级 process.env.* 继承(包括 nuxt build)"
- name: 安装依赖(npm ci,含 Runner 本地磁盘缓存 + 双源重试)
- name: 安装依赖(npm ci,含 Runner 本地磁盘缓存 + 双源重试 + npm 版本对齐)
run: |
set -euo pipefail
# 关键:本地生成 package-lock.json 使用的 npm 版本为 11.6.2(Node 24),
# 而 Preflight 默认 Node 22 自带 npm 10.x,lockfileVersion/校验不匹配会导致
# npm ci 报错并输出 help(其中包含 --install-links 字样,与你看到的日志一致)。
# 所以在任何 ci 操作之前,先把 npm 升级到与本地生成 lockfile 一致的大版本。
echo "=== Pre-upgrade npm to 11.x ==="
npm -v || true
if command -v sudo >/dev/null 2>&1; then
sudo npm install -g "npm@^11.6.2" 2>/dev/null || \
sudo npm install -g "npm@latest-11" 2>/dev/null || true
else
npm install -g "npm@^11.6.2" 2>/dev/null || \
npm install -g "npm@latest-11" 2>/dev/null || true
fi
hash -r 2>/dev/null || true
npm -v
LOCK_HASH="$(sha256sum package-lock.json | cut -d' ' -f1)"
CACHE_FILE="${VOICEHUB_NPM_CACHE_DIR}/pf-${LOCK_HASH}.tgz"
mkdir -p "${VOICEHUB_NPM_CACHE_DIR}"
@@ -225,7 +242,7 @@ jobs:
echo "[npm cache] MISS: ${CACHE_FILE},执行 npm ci 并写入缓存"
NPM_REGISTRY_PRIMARY="${NPM_REGISTRY_PRIMARY:-https://registry.npmmirror.com}"
NPM_REGISTRY_FALLBACK="${NPM_REGISTRY_FALLBACK:-https://mirrors.cloud.tencent.com/npm/}"
MAX_RETRY=2
MAX_RETRY=3
DELAY_SEC=15
CI_OK=0
for ATTEMPT in $(seq 1 $MAX_RETRY); do
@@ -234,7 +251,7 @@ jobs:
else
CUR_REGISTRY="${NPM_REGISTRY_FALLBACK}"
fi
echo "--- [npm ci attempt $ATTEMPT/$MAX_RETRY] registry=${CUR_REGISTRY} ---"
echo "--- [npm ci attempt $ATTEMPT/$MAX_RETRY] registry=${CUR_REGISTRY} npm=$(npm -v) node=$(node -v) ---"
npm config set registry "${CUR_REGISTRY}" || true
npm config set fund false
npm config set audit false
@@ -244,17 +261,27 @@ jobs:
npm config set fetch-retry-maxtimeout 300000 2>/dev/null || true
npm config set fetch-timeout 300000 2>/dev/null || true
npm config set fetch-retry-mintimeout 20000 2>/dev/null || true
if npm ci --legacy-peer-deps; then
set +e
npm ci --legacy-peer-deps
CI_EXIT=$?
set -e
if [ ${CI_EXIT} -eq 0 ]; then
CI_OK=1
echo "[npm ci] attempt ${ATTEMPT} SUCCESS"
break
fi
echo "[npm ci] attempt ${ATTEMPT} FAILED(exit=$?),${DELAY_SEC}s 后重试下一轮(若还有)..."
sleep $DELAY_SEC
echo "[npm ci] attempt ${ATTEMPT} FAILED(exit=${CI_EXIT})"
echo " last 40 lines of stderr / help(若出现 --install-links 字样,通常是 npm<11 vs lockfile 版本不匹配):"
echo " node=$(node -v) npm=$(npm -v) lockfileVersion=$(node -e "try{const j=require('./package-lock.json');console.log(j.lockfileVersion||'n/a')}catch(e){console.log('n/a')}" 2>/dev/null || echo n/a)"
if [ $ATTEMPT -lt $MAX_RETRY ]; then
echo " ${DELAY_SEC}s 后重试下一轮(若还有)..."
sleep $DELAY_SEC
fi
done
if [ "${CI_OK}" != "1" ]; then
echo "ERROR: npm ci 经过 ${MAX_RETRY} 轮(主站/备用域名交替)仍失败,请检查 Runner 网络是否能访问 ${NPM_REGISTRY_PRIMARY} / ${NPM_REGISTRY_FALLBACK}" >&2
echo " 可在 Variables 中覆盖 NPM_REGISTRY_PRIMARY / NPM_REGISTRY_FALLBACK,或在 Runner 宿主机手动配 npm 代理" >&2
echo " 快速自检(在 Runner 宿主机执行):node -v && npm -v && npm view vue version --registry=${NPM_REGISTRY_PRIMARY}" >&2
exit 1
fi
tar -czf "${CACHE_FILE}" node_modules