github actions开箱即用但易在npm ci、actions/checkout@v3或缓存策略上失败:checkout需显式设submodules: recursive;npm ci报错多因package-lock.json与package.json不一致;多node版本缓存须用hashfiles动态生成key。

GitHub Actions 做 CI/CD 不需要额外托管 runner,开箱即用,但默认配置容易在 npm ci、actions/checkout@v3 或缓存策略上失败——尤其当你本地能过、CI 报错时,八成是环境或路径没对齐。
为什么 actions/checkout@v3 有时拉不到子模块?
默认不递归拉取子模块,git clone 行为被封装了,但没开开关。如果你的项目依赖子模块,必须显式加参数:
- 加
submodules: recursive到actions/checkout@v3步骤里 - 如果只想要特定子模块,用
submodules: true+ 后续手动git submodule update --init - 注意:子模块的 commit hash 必须已推送到远端,否则 checkout 会静默失败(日志里只显示 “submodule path not found”)
npm ci 在 CI 里报错 “cannot read property 'name' of null” 怎么办?
这通常不是 npm 问题,而是 package-lock.json 和 package.json 不一致,或锁文件损坏。Actions 环境比本地更严格:
- 确保
package-lock.json已提交,且和package.json版本字段完全匹配(包括空格、引号) - 不要在 workflow 中混用
npm install和npm ci;CI 流程必须只用npm ci - 若用 pnpm/yarn,别硬套 npm 模板:改用
pnpm install --frozen-lockfile或yarn install --frozen-lockfile
多 Node.js 版本测试时,cache: 'npm' 为什么没生效?
因为 cache key 默认没包含 matrix.node-version,导致所有版本共用一个缓存目录,互相污染:
- 显式写 cache key:
cache: 'npm'→ 改成cache: 'npm'+cache-dependency-path: package-lock.json+ 自定义 key:key: ${{ runner.os }}-node-${{ matrix.node-version }}-${{ hashFiles('**/package-lock.json') }} - 不加
hashFiles就等于没缓存;只靠 os + node 版本不够,lock 文件变了也得更新缓存 - Ubuntu runner 上 npm 缓存路径是
~/.npm,但 Actions 的 cache 动作不自动映射它——必须靠 key 触发命中
最常被跳过的细节是:workflow 文件名(如 .github/workflows/ci.yml)一旦有语法错误,整个文件会被 GitHub 忽略,且不会报任何 warning —— 表现就是“push 后动作没触发”,得去 Settings → Actions → Runners 页面手动点 “Re-run all jobs” 才能看到真实错误。











