name: 'pnpm依赖安装与缓存' description: '专注于pnpm的依赖缓存与安装,加速重复执行' branding: icon: 'package' color: 'yellow' inputs: cache-prefix: description: '缓存前缀名称' required: false default: 'modules' force-install: description: '是否强制安装 (true/false)' required: false default: 'false' install-command: description: '自定义安装命令(若设置则完全覆盖默认命令)' required: false default: '' install-args: description: '附加到默认安装命令的参数(当未提供 install-command 时生效)' required: false default: '' cache-hash: description: '缓存hash值(推荐使用hashFiles)' required: false default: '' clean-project-store: description: '安装后清理项目根目录的 .pnpm-store (true/false)' required: false default: 'false' outputs: cache-hit: description: '是否命中缓存 (true/false)' value: ${{ steps.cache.outputs.cache-hit }} cache-key: description: '使用的缓存key' value: ${{ steps.cache-key.outputs.key }} cache-path: description: '缓存路径(用于调试与复用)' value: ${{ steps.cache-path.outputs.path }} runs: using: 'composite' steps: - name: 检查pnpm id: detect shell: bash run: | if ! command -v pnpm >/dev/null 2>&1; then echo "pnpm 未安装" exit 1 fi VERSION=$(pnpm --version | tr -d '\n') if [[ -z "$VERSION" ]]; then echo "无法获取pnpm版本" exit 1 fi echo "pnpm-version=${VERSION}" >> "$GITHUB_OUTPUT" echo "PNPM_VERSION=${VERSION}" >> "$GITHUB_ENV" - name: 生成缓存key id: cache-key shell: bash env: PNPM_VERSION: ${{ steps.detect.outputs.pnpm-version }} FALLBACK_HASH: ${{ hashFiles('pnpm-lock.yaml') }} PACKAGE_HASH: ${{ hashFiles('package.json') }} run: | set -euo pipefail if [[ -n "${{ inputs.cache-hash }}" ]]; then CACHE_HASH="${{ inputs.cache-hash }}" elif [[ -n "${FALLBACK_HASH}" ]]; then CACHE_HASH="${FALLBACK_HASH}" elif [[ -n "${PACKAGE_HASH}" ]]; then CACHE_HASH="${PACKAGE_HASH}" else CACHE_HASH="" fi if [[ -n "$CACHE_HASH" ]]; then CACHE_HASH_SHORT=$(echo "$CACHE_HASH" | head -c 12) else CACHE_HASH_SHORT="no-hash" fi PNPM_VERSION="${PNPM_VERSION}" CACHE_KEY="${{ runner.os }}-pnpm-v${PNPM_VERSION}-store-${{ inputs.cache-prefix }}-${CACHE_HASH_SHORT}" RESTORE_PREFIX="${{ runner.os }}-pnpm-v${PNPM_VERSION}-store-${{ inputs.cache-prefix }}-" echo "key=${CACHE_KEY}" >> "$GITHUB_OUTPUT" echo "restore-prefix=${RESTORE_PREFIX}" >> "$GITHUB_OUTPUT" echo "hash=${CACHE_HASH}" >> "$GITHUB_OUTPUT" - name: 确定缓存路径 id: cache-path shell: bash run: | set -euo pipefail if ! command -v pnpm >/dev/null 2>&1; then echo "❌ 未找到 pnpm,请先通过 pnpm/action-setup 安装" >&2 exit 1 fi STORE_DIR_CANDIDATE=$(pnpm store path --silent 2>/dev/null || true) STORE_DIR_CANDIDATE=$(echo "$STORE_DIR_CANDIDATE" | tail -n1 | tr -d '\r') if [[ -z "$STORE_DIR_CANDIDATE" ]]; then echo "❌ pnpm store path 未返回有效路径。可在运行前设置 PNPM_STORE_DIR=/path/to/store 或检查 pnpm 配置" >&2 exit 1 fi echo "pnpm store path: $STORE_DIR_CANDIDATE" echo "PNPM_STORE_DIR=${STORE_DIR_CANDIDATE}" >> "$GITHUB_ENV" echo "path=${STORE_DIR_CANDIDATE}" >> "$GITHUB_OUTPUT" - name: 拉取缓存 id: cache uses: actions/cache@v4 with: path: ${{ steps.cache-path.outputs.path }} key: ${{ steps.cache-key.outputs.key }} restore-keys: | ${{ steps.cache-key.outputs.restore-prefix }} - name: 显示缓存状态 shell: bash run: | if [[ "${{ steps.cache.outputs.cache-hit }}" == "true" ]]; then echo "缓存命中" else echo "缓存未命中" fi - name: 安装依赖 shell: bash run: | set -euo pipefail STORE_DIR="${PNPM_STORE_DIR:-${{ steps.cache-path.outputs.path }}}" export PNPM_STORE_DIR="$STORE_DIR" export npm_config_store_dir="$PNPM_STORE_DIR" export PNPM_CONFIG_STORE_DIR="$PNPM_STORE_DIR" echo "📦 Using PNPM_STORE_DIR=$PNPM_STORE_DIR" if [[ -n "${{ inputs.install-command }}" ]]; then echo "🔧 使用自定义安装命令: ${{ inputs.install-command }}" eval "${{ inputs.install-command }}" exit 0 fi if [[ "${{ steps.cache.outputs.cache-hit }}" == "true" ]]; then FLAGS=("--offline" "--frozen-lockfile") else FLAGS=("--prefer-offline" "--frozen-lockfile") fi if [[ "${{ inputs.force-install }}" == "true" ]]; then FLAGS+=("--force") fi INSTALL_ARGS="${{ inputs.install-args }}" echo "🔧 执行 pnpm install ${FLAGS[*]} ${INSTALL_ARGS}" if [[ -n "$INSTALL_ARGS" ]]; then pnpm install "${FLAGS[@]}" $INSTALL_ARGS else pnpm install "${FLAGS[@]}" fi if [[ "${{ inputs.clean-project-store }}" == "true" && -d ".pnpm-store" && "$(cd "$PNPM_STORE_DIR" 2>/dev/null && pwd)" != "$(cd .pnpm-store 2>/dev/null && pwd)" ]]; then rm -rf .pnpm-store || true fi echo "🧾 git status --short" CHANGES=$(git status --short || true) if [[ -n "$CHANGES" ]]; then echo "$CHANGES" echo "❌ 安装依赖后检测到工作区存在未提交变更。请检查上述文件,必要时更新配置或在调用前设置 PNPM_STORE_DIR。" >&2 exit 1 else echo "✅ 工作区保持干净" fi - name: 总结 shell: bash run: | echo "pnpm版本: $PNPM_VERSION" echo "缓存命中: ${{ steps.cache.outputs.cache-hit }}" echo "缓存key: ${{ steps.cache-key.outputs.key }}"