如何避免在 Gitlab CI 中每个作业重新安装依赖项
.gitlab-ci.yml
before_script:
- npm install
client_script:
script: npm run test
这样写是可以的,但这意味着依赖项是在每个测试job之前独立安装的。对于具有许多依赖项的大型项目,这会增加相当大的开销。 由于国内网络下载 node_modules 包花费很长时间。
在 Jenkins 中,我会使用一个来安装依赖项,然后将它们 TAR 起来并创建一个构建工件,然后将其复制到下游作业。Gitlab CI 会有类似的东西吗?有推荐的方法吗?
解决方案1: 使用 shell 脚本实现缓存系统
before_script:
# 设置唯一 hash
- PACKAGE_HASH=($(md5sum package.json))
# 缓存文件路径
- DEPS_CACHE=/tmp/dependencies_${PACKAGE_HASH}.tar.gz
# 检查缓存文件是否存在,如果不存在,就创建它
- if [ -f $DEPS_CACHE ];
then
tar zxf $DEPS_CACHE;
else
npm install -q;
tar zcf - ./node_modules > $DEPS_CACHE;
fi
这样仅在更改package.json 或缓存文件丢失时 .gitlab-ci.yml 重新安装依赖项 (例如,首次运行或文件被手动删除)。请注意,如果您在不同的服务器上有多个运行器,它们将各自有自己的缓存文件。
如果希望定期清除缓存文件以获取最新的依赖项。我们使用以下计时程序执行此操作:
@daily find /tmp/dependencies_* -mtime +1 -type f -delete
@daily是一个计时程序(cron)命令,指定任务执行的频率。在本例中,@daily表示以下命令应该每天运行一次。
命令本身find /tmp/ dependcies_ * -mtime +1 -type f -delete,搜索/tmp目录下名称以dependcies_开头且在过去24小时内未被修改过的文件。然后,它使用-delete选项删除符合这些条件的任何文件。
下面是find命令中使用的每个选项的解释:
/tmp/ dependcies_ :搜索文件的路径。星号()告诉find查找名称以依赖项_开头的文件。
-mtime +1:将查询结果限制为最近一次修改时间超过一天的文件。
-type f:将搜索限制为常规文件(而不是目录或其他类型的文件)。
-delete:删除通过上述选项找到的任何匹配文件。
总的来说,这个cron作业将每天删除一次/tmp中名称以dependes_开头且超过一天的所有文件。
解决方案2:
-
使用
artifacts来指定需要保存为job artifacts的文件。job artifacts是一个文件目录列表,在job成功、失败或始终附加到job。 -
在作业完成后,工件被发送到GitLab。他们可以在GitLab UI下载。
-
默认情况下,后期阶段的作业会自动下载所创建的所有工件
-
通过早期阶段的工作。可以控制作业中的工件下载行为
在下面的示例中,一旦构建阶段成功完成,node_modules/目录就可以立即用于lint阶段。
build:
stage: build
script:
- npm install -q
- npm run build
artifacts:
paths:
- node_modules/
expire_in: 1 week
lint:
stage: test
script:
- npm run lint
解决方案3:
使用cache 在GitLab 15.0中引入,缓存不会在受保护的分支和不受保护的分支之间共享。
当不需要更新缓存时(例如,在test job中构建文件夹),使用 policy: pull
gitlib cache文档
image: node
stages:
- init_cache
- test
- build
cache:
key: node_modules
paths:
- node_modules/
init_cache:node_modules:
stage: init_cache
# 手动触发
when: manual
cache:
key: node_modules
paths:
- node_modules/
after_script:
- node -v && npm -v
script:
- npm install
test:
stage: test
cache:
key: node_modules
paths:
- node_modules/
policy: pull
before_script:
- node -v && npm -v
script:
- npm run test
build:
stage: build
cache:
key: node_modules
paths:
- node_modules/
policy: pull
script:
- npm run build