我在gitlab中有一个monorepo,它带有有角度的前端和nestjs后端。我每个人都有package.json,根目录中有1个。我的管道包括以下多个阶段:
stages:
- build
- verify
- test
- deploy
我在.pre
阶段有一份工作,它会安装依赖项。我想在作业之间以及分支之间(如果package-lock.json
中的任何一个已更改,但也要在当前没有缓存的node_modules
中)将它们缓存。
我有一份看起来像这样的工作:
prepare:
stage: .pre
script:
- npm run ci-deps # runs npm ci in each folder
cache:
key: $CI_PROJECT_ID
paths:
- node_modules/
- frontend/node_modules/
- backend/node_modules/
only:
changes:
- '**/package-lock.json'
现在的问题是,如果以某种方式清除了高速缓存,或者如果我没有在第一次推送时对package-lock.json
进行更改,那么我将根本无法运行此作业,因此其他所有操作都会失败,因为这需要node_modules
。如果我从此处删除changes:
,则它将为每个管道运行作业。当然,我仍然可以在作业之间共享它,但是如果我再进行一次提交并推送,即使我没有更改应该存在的内容,安装所有依赖项也要花费近2分钟的时间。我该如何缓存它,使其仅在缓存已过期或不存在时才重新安装依赖项?
答案 0 :(得分:2)
最后,我发现我可以不依赖gitlab ci功能就可以做到这一点,但是可以像这样进行自己的检查:
prepare:
stage: .pre
image: node:12
script:
- if [[ ! -d node_modules ]] || [[ -n `git diff --name-only HEAD~1 HEAD | grep "\package.json\b"` ]];
then
npm ci;
fi
- if [[ ! -d frontend/node_modules ]] || [[ -n `git diff --name-only HEAD~1 HEAD | grep "\frontend/package.json\b"` ]];
then
npm run ci-deps:frontend;
fi
- if [[ ! -d backend/node_modules ]] || [[ -n `git diff --name-only HEAD~1 HEAD | grep "\backend/package.json\b"` ]];
then
npm run ci-deps:backend;
fi
cache:
key: '$CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR'
paths:
- node_modules/
- frontend/node_modules
- backend/node_modules
这样做的好处是,如果它尚未安装node_modules或更改package.json时,它将仅安装项目特定部分的依赖项。但是,如果我推送多个提交,而package.json不会在最后一个提交中更改,则这可能是错误的。在那种情况下,我仍然可以手动清除缓存并重新运行管道,但是我将尝试进一步改善脚本并更新答案。
答案 1 :(得分:2)
我遇到了同样的问题,我能够使用关键字rules
而不是only|except
来解决它。使用它,您可以声明更复杂的情况,例如使用if
,exists
,changes
。另外,这个:
规则不能仅与// 结合使用,因为是该功能的替代品。如果尝试执行此操作,则linter返回的键可能不会与规则错误一起使用。
所有更多原因切换到rules
。这是我的解决方案,它执行npm ci
:
package-lock.json
文件已被修改OR
node-modules
文件夹不存在(如果有新分支或清理缓存):npm-ci:
image: node:lts
cache:
key: $CI_COMMIT_REF_SLUG-$CI_PROJECT_DIR
paths:
- node_modules/
script:
- npm ci
rules:
- changes:
- package-lock.json
- exists:
- node_modules
when: never
希望有帮助!
答案 2 :(得分:1)
Rules:Exists 在缓存被拉下之前运行,所以这对我来说不是一个可行的解决方案。
在 GitLab v12.5 中,我们现在可以使用 cache:key:files
如果我们将其与 Blind Despair 的部分条件逻辑结合起来,我们会得到一个很好的解决方案
prepare:
stage: .pre
image: node:12
script:
- if [[ ! -d node_modules ]];
then
npm ci;
fi
cache:
key:
files:
- package-lock.json
prefix: nm-$CI_PROJECT_NAME
paths:
- node_modules/
然后我们可以在后续的构建作业中使用它
# let's keep it dry with templates
.use_cached_node_modules: &use_cached_node_modules
cache:
key:
files:
- package-lock.json
prefix: nm-$CI_PROJECT_NAME
paths:
- node_modules/
policy: pull # don't push unnecessarily
build:
<<: *use_cached_node_modules
stage: build
image: node:12
script:
- npm run build
我们通过共享缓存在多个分支中成功地使用了它。