Files
composite-actions/setup-node-environment/action.yml

231 lines
10 KiB
YAML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🔗 链接:
# 源文件: https://github.com/obytes/react-native-template-obytes/blob/master/.github/actions/setup-node-pnpm-install/action.yml
# 复合操作文档: https://docs.github.com/en/actions/creating-actions/creating-a-composite-action
# ✍️ 描述:
# 这是一个复合操作,意味着它可以在其他操作中使用。
# 它几乎用于所有工作流中,以设置环境并安装依赖项。
# 在此处更新包管理器或 Node 版本将反映在所有工作流中。
# 👀 使用示例:
# - name : 📦 设置 Node + PNPM + 安装依赖
# uses: ./.github/actions/setup-node-pnpm-install
name: '设置 Node 环境'
description: '设置 pnpm + Node.js + 安装依赖项'
inputs:
pnpm_standalone: # 是否将 pnpm 用作独立包 https://github.com/pnpm/action-setup?tab=readme-ov-file#standalone
description: '是否将 pnpm 用作独立包'
required: false
default: 'false'
# https://github.com/pnpm/action-setup/blob/d648c2dd069001a242c621c8306af467f150e99d/action.yml#L18C3-L18C20
working-directory:
description: '工作目录'
required: false
default: '.'
runs:
using: 'composite'
steps:
- id: check-git-folder
shell: bash
run: |
# 🤖----判断是否存在 .git 文件夹----🤖 #
[ -d ${{ github.workspace }}/.git ] && { echo "🤖 找到 .git 文件夹"; echo "git-folder-exists=true" >> $GITHUB_OUTPUT; } || { echo "🤖 未找到 .git 文件夹"; echo "git-folder-exists=false" >> $GITHUB_OUTPUT; }
- uses: actions/checkout@v4.2.2
if: steps.check-git-folder.outputs.git-folder-exists == 'false'
with:
# fetch-depth: 0 # 0 代表完整检出semantic-release 需要
filter: blob:none # 我们不需要所有 blob只需要完整的树
show-progress: false
- id: prepare
shell: bash
working-directory: ${{ inputs.working-directory }}
run: |
# 🤖---- 准备环境变量 ----🤖 #
# --- 1. 包管理器 ---
echo "::group::📦 获取包管理器信息"
pkg_manager=$(node -p "try { require('./package.json').packageManager } catch(e) { '' }")
echo "从 package.json 获取的包管理器: $pkg_manager"
echo "::endgroup::"
# --- 2. 确定 PNPM 版本 ---
echo "::group::🔧 确定 PNPM 版本"
pnpm_version=""
# 如果 packageManager 为空、undefined 或 null则使用最新的 pnpm
if [ -z "$pkg_manager" ] || [ "$pkg_manager" == "undefined" ] || [ "$pkg_manager" == "null" ]; then
pnpm_version="latest"
echo "未指定或无效的 packageManager使用 pnpm 版本: latest"
else
# 如果指定了 pnpm 版本(例如 "pnpm@8.6.0"),则提取版本号
if [[ "$pkg_manager" == pnpm* ]]; then
pnpm_version=$(echo "$pkg_manager" | cut -d '@' -f 2)
echo "使用 package.json 中的 pnpm 版本: $pnpm_version"
else
echo "指定了非 pnpm 包管理器: $pkg_manager。将由 pnpm/action-setup 处理版本。"
# 让 pnpm/action-setup 根据 corepack 或其默认设置决定版本
pnpm_version="" # 如果不是 pnpm 或未正确指定,则显式设置为空
fi
fi
echo "::endgroup::"
# --- 3. 检查 PNPM 安装情况 ---
echo "::group::🔍 检查 PNPM 安装情况"
is_pnpm_installed="false"
pnpm_executable_path=""
installed_pnpm_version="无法获取" # 版本检查失败时的默认值
# 使用 command -v 检查 pnpm 是否在 PATH 中并且可执行
if command -v pnpm >/dev/null 2>&1; then
pnpm_executable_path=$(command -v pnpm)
echo "找到 PNPM 可执行文件于: $pnpm_executable_path"
# 尝试获取版本号,但不因失败而退出
if pnpm_version_output=$(pnpm --version 2>/dev/null); then
installed_pnpm_version="$pnpm_version_output"
is_pnpm_installed="true" # 确认 pnpm 可执行且能获取版本
echo "已安装的 PNPM 版本: $installed_pnpm_version"
else
# pnpm 命令存在但获取版本失败,可能安装不完整或有问题
is_pnpm_installed="true" # 标记为已安装,因为命令存在
echo "警告PNPM 命令存在,但无法获取版本号。可能安装不完整或存在问题。"
echo "将继续执行,后续步骤可能会重新安装或修复。"
fi
else
echo "PNPM 未在 PATH 中找到或不可执行。"
is_pnpm_installed="false"
fi
echo "::endgroup::"
# --- 4. 检查 PNPM Lock 文件 ---
echo "::group::📄 检查 PNPM Lock 文件"
has_pnpm_lock="false"
if [ -f pnpm-lock.yaml ]; then
has_pnpm_lock="true"
echo "找到 pnpm-lock.yaml。"
else
echo "未找到 pnpm-lock.yaml。"
fi
echo "::endgroup::"
# --- 5. 确定 Node.js 版本并清理 .npmrc ---
echo "::group::⚙️ 确定 Node.js 版本并清理 .npmrc"
node_version="lts/*" # 默认 Node 版本
if [ ! -f .npmrc ]; then
echo "未找到 .npmrc创建一个空文件。"
touch .npmrc
else
echo "找到 .npmrc 文件。"
fi
# 从 .npmrc 读取 use-node-version
node_version_in_npmrc=$(sed -n 's/.*use-node-version=\([0-9.]*\).*/\1/p' .npmrc)
if [ -n "$node_version_in_npmrc" ]; then
node_major_version_in_npmrc=$(echo "$node_version_in_npmrc" | cut -d. -f1)
if [ -n "$node_major_version_in_npmrc" ]; then
node_version="$node_major_version_in_npmrc"
echo ".npmrc 中指定的 Node 版本: $node_version_in_npmrc -> 使用主版本: $node_version"
else
echo "无法从 .npmrc ($node_version_in_npmrc) 提取主 Node 版本。使用默认值: $node_version"
fi
else
echo ".npmrc 中未找到 'use-node-version'。使用默认值: $node_version"
fi
# 清理 .npmrc删除 use-node-version 和 node-mirror 行
echo "正在清理 .npmrc..."
# 使用 -i.bak 以兼容不同 sed 版本,并在创建备份后删除
sed -i.bak -e '/use-node-version/d' -e '/node-mirror/d' .npmrc
[ -f .npmrc.bak ] && rm .npmrc.bak
echo ".npmrc 已清理。"
echo "::endgroup::"
# --- 6. 设置输出 ---
echo "::group::🚀 设置 GitHub Actions 输出"
echo "packageManager=${pkg_manager}" >> $GITHUB_OUTPUT
echo "pnpmVersion=${pnpm_version}" >> $GITHUB_OUTPUT
echo "pnpmInstalled=${is_pnpm_installed}" >> $GITHUB_OUTPUT
echo "pnpmLockExists=${has_pnpm_lock}" >> $GITHUB_OUTPUT
echo "nodeVersion=${node_version}" >> $GITHUB_OUTPUT
echo "输出已设置:"
printf " %-16s %s\n" "packageManager:" "${pkg_manager}"
printf " %-16s %s\n" "pnpmVersion:" "${pnpm_version}"
printf " %-16s %s\n" "pnpmInstalled:" "${is_pnpm_installed}"
printf " %-16s %s\n" "pnpmLockExists:" "${has_pnpm_lock}"
printf " %-16s %s\n" "nodeVersion:" "${node_version}"
echo "::endgroup::"
- uses: pnpm/action-setup@v4 # https://github.com/pnpm/action-setup?tab=readme-ov-file#inputs
if: steps.prepare.outputs.pnpmInstalled == 'false'
with:
# https://github.com/pnpm/action-setup/blob/master/action.yml
version: ${{ steps.prepare.outputs.pnpmVersion }}
standalone: ${{ inputs.pnpm_standalone }}
package_json_file: ${{ inputs.working-directory }}/package.json
- uses: actions/setup-node@v4 # https://github.com/actions/setup-node?tab=readme-ov-file#usage
with:
node-version: ${{ steps.prepare.outputs.nodeVersion }}
cache: ''
- id: pnpm-store-dir
shell: bash
run: |
echo "🤖---- 获取 PNPM 存储目录 ----🤖"
echo "PNPM 存储目录: $(pnpm store path)"
echo "pnpmStoreDir=$(pnpm store path)" >> $GITHUB_OUTPUT
- id: cache-pnpm-restore
uses: actions/cache/restore@v4 # https://github.com/actions/cache/blob/main/restore/action.yml
with:
path: ${{ steps.pnpm-store-dir.outputs.pnpmStoreDir }}
key: ${{ runner.os }}-pnpm-store-${{ github.repository_id }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-${{ github.repository_id }}-
${{ runner.os }}-pnpm-store-
# https://github.com/pnpm/pnpm/issues/7192#issuecomment-2353298966
- run: echo "package-import-method=hardlink" >> .npmrc
shell: bash
- if: steps.cache-pnpm-restore.outputs.cache-hit == 'true'
working-directory: ${{ inputs.working-directory }}
shell: bash
run: |
echo "🤖---- 缓存命中,安装依赖 ----🤖"
pnpm install --prefer-offline
# --frozen-lockfile
# ERR_PNPM_NO_LOCKFILE Cannot install with "frozen-lockfile" because pnpm-lock.yaml is absent
- if: steps.cache-pnpm-restore.outputs.cache-hit != 'true'
working-directory: ${{ inputs.working-directory }}
shell: bash
run: |
echo "🤖---- 缓存未命中,安装依赖 ----🤖"
set -x;
pnpm fetch # https://pnpm.io/zh/cli/fetch
pnpm install --prefer-offline
# --frozen-lockfile
# ERR_PNPM_NO_LOCKFILE Cannot install with "frozen-lockfile" because pnpm-lock.yaml is absent
pnpm store prune
- name: 📊 显示缓存命中状态
run: |
echo "cache-hit: ${{ steps.cache-pnpm-restore.outputs.cache-hit }}"
shell: bash
- id: cache-pnpm-save
if: always() && steps.cache-pnpm-restore.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ${{ steps.pnpm-store-dir.outputs.pnpmStoreDir }}
key: ${{ steps.cache-pnpm-restore.outputs.cache-primary-key }}
# rm -r node_modules
# pnpm fetch
# pnpm install --offline
# pnpm store prune
# #
# rm -r node_modules
# pnpm install --offline