🐛 fix(workflow): manage Node versions with fnm

This commit is contained in:
csh
2026-08-13 17:33:55 +08:00
parent f90faa10c3
commit fac69aafbd
6 changed files with 126 additions and 5 deletions
+25
View File
@@ -26,6 +26,8 @@ env:
SOURCE_SHA: ${{ github.event.workflow_run.head_sha }}
SOURCE_EVENT: ${{ github.event.workflow_run.event }}
COMMIT_LINT_REQUIRE_EMOJI: "1"
FNM_BIN: "/data/bin/fnm"
FNM_DIR: "/data/fnm"
jobs:
checks:
@@ -131,6 +133,29 @@ jobs:
echo "========================================"
cd "$REPO_DIR"
node_version=$(tr -d '[:space:]' < .node-version)
if ! [[ "$node_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo ".node-version 必须是完整的 Node.js 版本号: $node_version" >&2
exit 1
fi
if [ ! -x "$FNM_BIN" ]; then
echo "Prepare 未安装 fnm: $FNM_BIN" >&2
exit 1
fi
eval "$("$FNM_BIN" env --shell bash)"
exec 9>"${FNM_DIR}.install.lock"
flock 9
"$FNM_BIN" use --install-if-missing "$node_version"
flock -u 9
if [ "$(node --version)" != "v$node_version" ]; then
echo "Node.js 切换后版本不符合要求: $(node --version)" >&2
exit 1
fi
node --version
npm --version
echo "📦 安装锁定的 Node.js 校验工具"
npm ci --ignore-scripts --no-audit --no-fund --no-bin-links
+81 -3
View File
@@ -23,6 +23,10 @@ concurrency:
env:
ACCESS_TOKEN: ${{ secrets.WORKFLOW }}
FNM_ARCHIVE_SHA256: "7807664f39d39fc518da1c35ba0181e4b3267603c4b1dedeb4b5fc6ae440a224"
FNM_BIN: "/data/bin/fnm"
FNM_DIR: "/data/fnm"
FNM_VERSION: "1.39.0"
WORKSPACE_ROOT: "/data/workspace"
jobs:
@@ -45,10 +49,9 @@ jobs:
[curl]="curl"
[flock]="util-linux"
[realpath]="coreutils"
[node]="nodejs"
[npm]="npm"
[unzip]="unzip"
)
required_commands=(git python3 python3.11 curl flock realpath node npm)
required_commands=(git python3 python3.11 curl flock realpath unzip)
missing_commands=()
missing_packages=()
declare -A seen_packages=()
@@ -94,6 +97,34 @@ jobs:
python3.11 -c 'import sys; raise SystemExit(0 if sys.version_info >= (3, 11) else "Python 3.11 or newer is required")'
fnm_installed=false
expected_fnm_version="fnm $FNM_VERSION"
current_fnm_version=""
if [ -x "$FNM_BIN" ]; then
current_fnm_version=$($FNM_BIN --version 2>/dev/null || true)
fi
if [ "$current_fnm_version" != "$expected_fnm_version" ]; then
echo "准备安装 $expected_fnm_version"
mkdir -p "$(dirname "$FNM_BIN")"
fnm_tmp_dir=$(mktemp -d)
trap 'rm -rf "$fnm_tmp_dir"' EXIT
fnm_archive="$fnm_tmp_dir/fnm-linux.zip"
curl -fsSL --retry 5 --retry-all-errors \
"https://github.com/Schniz/fnm/releases/download/v${FNM_VERSION}/fnm-linux.zip" \
-o "$fnm_archive"
printf '%s %s\n' "$FNM_ARCHIVE_SHA256" "$fnm_archive" | sha256sum -c -
unzip -q "$fnm_archive" -d "$fnm_tmp_dir"
install -m 0755 "$fnm_tmp_dir/fnm" "${FNM_BIN}.new"
mv -f "${FNM_BIN}.new" "$FNM_BIN"
fnm_installed=true
fi
if [ "$($FNM_BIN --version)" != "$expected_fnm_version" ]; then
echo "fnm 安装后版本不符合要求: $($FNM_BIN --version 2>&1)" >&2
exit 1
fi
{
echo "## Prepare 环境"
echo ""
@@ -105,12 +136,18 @@ jobs:
version_line=${version_line//|/\\|}
printf '| `%s` | `%s` |\n' "$command" "$version_line"
done
printf '| `%s` | `%s` |\n' "fnm" "$($FNM_BIN --version)"
echo ""
if [ "$installed" = true ]; then
echo "安装的包:\`${missing_packages[*]}\`"
else
echo "安装的包:无,所有命令已存在。"
fi
if [ "$fnm_installed" = true ]; then
echo "安装的版本管理器:\`$expected_fnm_version\`"
else
echo "安装的版本管理器:无,\`$expected_fnm_version\` 已存在。"
fi
} >> "$GITHUB_STEP_SUMMARY"
echo "installed=$installed" >> "$GITHUB_OUTPUT"
@@ -205,6 +242,8 @@ jobs:
fi
resolved_sha=$(git --git-dir="$REPOSITORY_DIR" rev-parse "${HEAD_SHA}^{commit}")
echo "PREPARED_REPOSITORY_DIR=$REPOSITORY_DIR" >> "$GITHUB_ENV"
echo "PREPARED_SHA=$resolved_sha" >> "$GITHUB_ENV"
{
echo ""
echo "## Prepare 仓库"
@@ -215,3 +254,42 @@ jobs:
} >> "$GITHUB_STEP_SUMMARY"
echo "Prepare 完成: $REPOSITORY_DIR @ $resolved_sha"
- name: 🟢 准备 Node.js
shell: bash
run: |
set -euo pipefail
node_version=$(git --git-dir="$PREPARED_REPOSITORY_DIR" show "${PREPARED_SHA}:.node-version" | tr -d '[:space:]')
if ! [[ "$node_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo ".node-version 必须是完整的 Node.js 版本号: $node_version" >&2
exit 1
fi
node_major=${node_version%%.*}
if [ "$node_major" -lt 20 ]; then
echo "Node.js 版本必须不低于 20: $node_version" >&2
exit 1
fi
mkdir -p "$FNM_DIR"
exec 9>"${FNM_DIR}.install.lock"
flock 9
"$FNM_BIN" install "$node_version"
flock -u 9
actual_node_version=$($FNM_BIN exec --using="$node_version" node --version)
actual_npm_version=$($FNM_BIN exec --using="$node_version" npm --version)
if [ "$actual_node_version" != "v$node_version" ]; then
echo "Node.js 安装后版本不符合要求: $actual_node_version" >&2
exit 1
fi
{
echo ""
echo "## Prepare Node.js"
echo ""
echo "- fnm\`$($FNM_BIN --version)\`"
echo "- Node.js\`$actual_node_version\`"
echo "- npm\`$actual_npm_version\`"
echo "- 缓存目录:\`$FNM_DIR\`"
} >> "$GITHUB_STEP_SUMMARY"