Gitlab CI - 如何在缓存存在时跳过作业

11

我在我的CI中有一个setup作业,它安装所有npm软件包并将它们存储在缓存中:

setup:
  stage: pre-build
  cache:
    untracked: true
    when: on_success
    key:
      files:
        - repo-hash
      prefix: workspace
  script:
    - yarn install --frozen-lockfile

目前,如果在两个流水线之间,仓库哈希值没有改变,作业会成功下载现有的缓存,但仍然会运行yarn install --frozen-lockfile命令。

如何更改此行为,以便如果缓存存在,跳过该作业?


你应该缓存.yarn目录,例如 https://classic.yarnpkg.com/en/docs/install-ci/;你仍然需要进行安装,但是大多数(如果不是全部)文件已经在本地了。 - jonrsharpe
谢谢,实际上我不介意下载步骤,主要是我想跳过 yarn install 步骤:/ - Nicoowr
你找到了一种跳过 yarn 安装步骤的方法吗? - Konstanitnos Schoinas
我们最终决定不这样做。但是我认为你可以使用gitlab-ci.yml的changes关键字,仅在指定字段更改时运行作业:https://docs.gitlab.com/ee/ci/yaml/#ruleschanges - Nicoowr
3个回答

9

尝试退出?

install:
  stage: install
  cache:
    key:
      files:
        - package-lock.json
      prefix: $CI_PROJECT_NAME
    paths:
      - node_modules/
  script:
    - |
      if [[ -d node_modules ]]; then
        exit 10
      fi
    - npm ci --cache .npm --prefer-offline
  allow_failure:
    exit_codes: 10

1
最好将错误代码10改为0。 - Fernando Zamperin
1
这个可以运行,但如果在Gitlab层面上实现会更好,因为启动作业可能需要一些时间(例如:在性能不是很强的Windows虚拟机上使用Docker执行器需要1分钟才能达到此退出点)。 - Gabriel Devillers

9

目前在一个基于NPM的Preact项目中,我正在使用gitlab-ci.yml的only功能,如果package-lock.json有任何更改,就运行安装作业(如果没有更改,则跳过安装)。然后我的构建作业从安装作业中获取node_modules缓存:

install:
  stage: setup # gitlab.com shared runners are slow; don't run unless there's a reason to install
  cache:       # even a "echo 'hello world'" script would be about a 30s job, worse if queued
    key:
      files: [package-lock.json] # the key is a hash of package-lock; branches with it will use this cache :D
    paths: [node_modules] # we're not caching npm (ie `npm ci --prefer-offline --cache`) because it's slow
    policy: push # override the default behavior of wasting time downloading and unpacking node_modules
  script: [npm ci] # I believe in package-lock/npm ci's mission
  only:
    changes: [package-lock.json] # our forementioned reason to install
    refs:
      - master
      - develop
      - merge_requests

build: # uses the default behavior, which runs even if install is skipped; but not if install failed
  stage: build
  cache:
    key:
      files: [package-lock.json]
    paths: [node_modules]
    policy: pull # override the default behavior of wasting time packing and uploading node_modules
  script:
    - npm run build
  artifacts:
    paths: [build]
  only:
    changes:
      - src/**/*
      - tsconfig.json
      - preact.config.js
      - package-lock.json
    refs:
      - master
      - develop
      - merge_requests

对于Yarn,您只需使用yarn.lock替换此处看到的任何package-lock.json,并用yarn install --frozen-lockfile替换npm ci

以前,我是这样做的(类似于这里其他答案中的一个):

build:
  stage: build
  cache:
    key:
      files: [package-lock.json]
    paths: [node_modules]
  script:
    - test -d node_modules || npm ci
    - npm run build
  artifacts:
    paths: [build]
  only:
    changes:
      - src/**/*
      - tsconfig.json
      - preact.config.js
      - package-lock.json
    refs:
      - master
      - develop
      - merge_requests

我选择了更为复杂的方法,因为我本以为还要为 npm 缓存实现缓存,但似乎无法改善任何实际的安装时间 - 事实上变得更糟了。尽管如此,我仍然坚持使用它,因为它使我可以从锁定文件未更改的情况下节省另外20秒。我发现这两种方式都是有效的。在我的具体情况中,缓存 node_modules 可以将部署时间缩短约一分半。

3
根据官方参考,这在工作级别上是不可能的。然而,您可以向作业脚本添加条件并检查应该被缓存的文件是否存在。
以下是我设置的相关部分:
stages:
- setup
- test
- build
- release
- publish

cache: &dependency-cache
  key:
    files:
    - "**/yarn.lock"
  paths:
  - node_modules
  - "*/node_modules"
  policy: pull

renew-cache:
  stage: setup
  except:
  - /master.*/
  - tags
  script:
  - test -d node_modules || yarn && yarn workspace app ngcc --properties es2015 browser module main
  cache:
    <<: *dependency-cache
    policy: pull-push

test-app:
  stage: test
  except:
  - /master.*/
  - tags
  script:
  - test -d node_modules || yarn
  - yarn workspace app test

build-app:
  stage: build
  only:
  - /master.*/
  script:
  - test -d node_modules || yarn
  - yarn workspace app build
  # Store build results ...

# The rest of the pipeline
  • 我使用yarn 2+和yarn工作区,使用node-modules yarn链接器和dependency模块提升限制
  • 所有作业共享缓存,使用pull策略,renew-cache作业是唯一可以写入缓存的作业
  • test -d node_modules || <COMMAND>仅在未找到node_modules目录时运行<COMMAND> - 作业无缓存
  • 只有没有缓存或任何yarn.lock被修改时才推送新缓存
  • 相同的缓存将一直重复使用,直到过期并且yarn.lock文件未更改
  • 对于依赖缓存的所有其他构建脚本都必须存在缓存的node_modules测试 - 缓存可能已过期,流水线必须确定性可重复

这种方法并不能完全消除每次运行设置作业的需要,因此仍然存在一些开销。但是,整个流水线的运行时间大大减少。

希望这能有所帮助 :-)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接