diff --git a/npm-install/README.md b/npm-install/README.md index 3e79d10..60d66b8 100644 --- a/npm-install/README.md +++ b/npm-install/README.md @@ -5,8 +5,9 @@ ## ✨ 特性 - 🚀 **智能缓存**: 自动缓存 node_modules,避免重复安装 -- 📦 **多包管理器支持**: 支持 npm、pnpm、yarn +- 📦 **多包管理器支持**: 支持 npm、pnpm、yarn,自动检测标准锁文件 - 🎯 **灵活配置**: 可自定义缓存前缀、安装命令等 +- 🔑 **精确 hash 控制**: 支持自定义缓存 hash,确保依赖变化时缓存失效 - 🔄 **Git 集成**: 可选的 git stash 功能 - 📊 **详细输出**: 提供缓存命中状态和使用的缓存 key @@ -15,12 +16,12 @@ | 参数名 | 描述 | 是否必需 | 默认值 | | ------------------- | ---------------------------- | -------- | -------------- | | `package-manager` | 包管理器类型 (npm/pnpm/yarn) | 否 | `npm` | -| `lockfile-name` | lock 文件名称 | 否 | 自动检测 | | `cache-prefix` | 缓存前缀名称 | 否 | `modules` | | `node-modules-path` | node_modules 目录路径 | 否 | `node_modules` | | `force-install` | 是否强制安装 | 否 | `false` | | `enable-git-stash` | 安装后是否执行 git stash | 否 | `false` | | `install-command` | 自定义安装命令(覆盖默认) | 否 | `''` | +| `cache-hash` | 缓存 hash 值(**推荐使用**) | 否 | 自动计算 | ## 📤 输出参数 @@ -29,6 +30,25 @@ | `cache-hit` | 是否命中缓存 (true/false) | | `cache-key` | 使用的缓存 key | +## 💡 重要提示 + +**强烈推荐使用 `cache-hash` 参数!** + +使用 `cache-hash` 参数有以下优势: + +- ✅ **精确控制**: 让你完全控制缓存失效的条件 +- ✅ **环境兼容**: 避免在不同容器环境中 hash 计算不一致的问题 +- ✅ **灵活组合**: 可以组合多个文件的 hash(如 `package.json` + `package-lock.json` + `.nvmrc`) +- ✅ **调试友好**: 在 workflow 中可以清楚看到使用的 hash 值 + +```yaml +# 推荐用法 +with: + cache-hash: ${{ hashFiles('package-lock.json') }} +``` + +如果不提供 `cache-hash`,action 会自动使用 `package.json` 作为 fallback,但不如手动指定精确。 + ## 🚀 使用方法 ### 基础用法 (npm) @@ -78,6 +98,31 @@ install-command: "npm ci --only=production" ``` +### 使用自定义缓存 hash(推荐用法) + +```yaml +# 推荐:手动指定缓存hash,确保精确的缓存管理 +- name: 安装npm依赖 + uses: actions/xgj/npm-install@v1 + with: + package-manager: "npm" + cache-hash: ${{ hashFiles('package-lock.json') }} + +# pnpm项目 +- name: 安装pnpm依赖 + uses: actions/xgj/npm-install@v1 + with: + package-manager: "pnpm" + cache-hash: ${{ hashFiles('pnpm-lock.yaml') }} + +# 多文件hash组合 +- name: 安装依赖(多文件hash) + uses: actions/xgj/npm-install@v1 + with: + package-manager: "npm" + cache-hash: ${{ hashFiles('package.json', 'package-lock.json', '.nvmrc') }} +``` + ### 检查缓存状态 ```yaml diff --git a/npm-install/action.yml b/npm-install/action.yml index 7ea66c9..3d73a65 100644 --- a/npm-install/action.yml +++ b/npm-install/action.yml @@ -10,11 +10,7 @@ inputs: required: false default: 'npm' - lockfile-name: - description: 'lock文件名称' - required: false - default: 'package-lock.json' - + cache-prefix: description: '缓存前缀名称' required: false @@ -39,6 +35,11 @@ inputs: description: '自定义安装命令(可选,会覆盖默认命令)' required: false default: '' + + cache-hash: + description: '缓存hash值(推荐使用hashFiles计算)' + required: false + default: "hashFiles('pnpm-lock.yaml')" outputs: cache-hit: @@ -56,49 +57,32 @@ runs: id: cache-key shell: bash env: - NPM_HASH: ${{ hashFiles('package-lock.json') }} - PNPM_HASH: ${{ hashFiles('pnpm-lock.yaml') }} - YARN_HASH: ${{ hashFiles('yarn.lock') }} + FALLBACK_HASH: ${{ hashFiles('package.json') }} run: | - # 根据包管理器确定锁文件和对应的hash - case "${{ inputs.package-manager }}" in - "npm") - if [[ "${{ inputs.lockfile-name }}" != "package-lock.json" ]]; then - LOCKFILE="${{ inputs.lockfile-name }}" - LOCKFILE_HASH="${NPM_HASH}" - else - LOCKFILE="package-lock.json" - LOCKFILE_HASH="${NPM_HASH}" - fi - ;; - "pnpm") - LOCKFILE="pnpm-lock.yaml" - LOCKFILE_HASH="${PNPM_HASH}" - ;; - "yarn") - LOCKFILE="yarn.lock" - LOCKFILE_HASH="${YARN_HASH}" - ;; - *) - LOCKFILE="${{ inputs.lockfile-name }}" - # 对于自定义情况,使用npm hash作为默认 - LOCKFILE_HASH="${NPM_HASH}" - ;; - esac - - # 截取hash的前12位 - if [[ -n "${LOCKFILE_HASH}" && "${LOCKFILE_HASH}" != "" ]]; then - LOCKFILE_HASH_SHORT=$(echo "${LOCKFILE_HASH}" | head -c 12) + # 确定使用的hash值 + if [[ -n "${{ inputs.cache-hash }}" && "${{ inputs.cache-hash }}" != "" ]]; then + CACHE_HASH="${{ inputs.cache-hash }}" + echo "✅ 使用用户传入的hash值" + elif [[ -n "${FALLBACK_HASH}" && "${FALLBACK_HASH}" != "" ]]; then + CACHE_HASH="${FALLBACK_HASH}" + echo "📝 未提供hash,使用package.json作为fallback" else - echo "⚠️ 警告: 无法计算锁文件hash,使用默认值" - LOCKFILE_HASH_SHORT="no-lockfile" + CACHE_HASH="" + echo "⚠️ 警告: 无法获取hash值,使用默认值" fi - CACHE_KEY="${{ runner.os }}-${{ inputs.cache-prefix }}-${LOCKFILE_HASH_SHORT}" + # 截取hash的前12位 + if [[ -n "${CACHE_HASH}" && "${CACHE_HASH}" != "" ]]; then + CACHE_HASH_SHORT=$(echo "${CACHE_HASH}" | head -c 12) + echo "✅ 成功计算缓存hash: ${CACHE_HASH_SHORT}" + else + CACHE_HASH_SHORT="no-hash" + echo "⚠️ 使用默认hash值: ${CACHE_HASH_SHORT}" + fi + + CACHE_KEY="${{ runner.os }}-${{ inputs.cache-prefix }}-${CACHE_HASH_SHORT}" echo "key=${CACHE_KEY}" >> $GITHUB_OUTPUT - echo "lockfile=${LOCKFILE}" >> $GITHUB_OUTPUT - echo "使用锁文件: ${LOCKFILE}" - echo "文件hash: ${LOCKFILE_HASH}" + echo "使用hash: ${CACHE_HASH}" echo "缓存key: ${CACHE_KEY}" - name: 拉取缓存依赖 diff --git a/npm-install/examples/custom-cache-hash.yml b/npm-install/examples/custom-cache-hash.yml new file mode 100644 index 0000000..be9c4d7 --- /dev/null +++ b/npm-install/examples/custom-cache-hash.yml @@ -0,0 +1,107 @@ +# 自定义缓存hash示例(推荐用法) +name: 自定义缓存hash示例 + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + +jobs: + test: + runs-on: ubuntu-latest + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + # 推荐用法:手动计算hash并传入 + - name: 安装npm依赖(使用package-lock.json hash) + uses: actions/xgj/npm-install@v1 + with: + package-manager: 'npm' + cache-hash: ${{ hashFiles('package-lock.json') }} + + - name: 运行linting + run: npm run lint + + - name: 运行测试 + run: npm test + + test-pnpm: + runs-on: ubuntu-latest + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Node.js和pnpm + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: 安装pnpm + run: npm install -g pnpm + + # pnpm项目示例 + - name: 安装pnpm依赖 + uses: actions/xgj/npm-install@v1 + with: + package-manager: 'pnpm' + cache-hash: ${{ hashFiles('pnpm-lock.yaml') }} + + - name: 运行测试 + run: pnpm test + + test-yarn: + runs-on: ubuntu-latest + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Node.js和Yarn + uses: actions/setup-node@v4 + with: + node-version: '18' + + - name: 启用Yarn + run: corepack enable yarn + + # Yarn项目示例 + - name: 安装yarn依赖 + uses: actions/xgj/npm-install@v1 + with: + package-manager: 'yarn' + cache-hash: ${{ hashFiles('yarn.lock') }} + + - name: 运行测试 + run: yarn test + + # 多个锁文件的复杂项目示例 + test-multi-lockfiles: + runs-on: ubuntu-latest + + steps: + - name: 检出代码 + uses: actions/checkout@v4 + + - name: 设置Node.js + uses: actions/setup-node@v4 + with: + node-version: '18' + + # 组合多个文件的hash,确保任何文件变化都会使缓存失效 + - name: 安装依赖(多文件hash) + uses: actions/xgj/npm-install@v1 + with: + package-manager: 'npm' + cache-hash: ${{ hashFiles('package.json', 'package-lock.json', '.nvmrc') }} + + - name: 运行测试 + run: npm test