【问题标题】:Gitlab CI - How to skip job if cache existsGitlab CI - 如果缓存存在,如何跳过作业
【发布时间】:2021-06-07 04:06:07
【问题描述】:

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

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

目前,如果 repo-hash 在两个管道之间没有变化,则作业成功下载现有缓存,但仍运行 yarn install --frozen-lockfile

如何改变这个行为,如果缓存存在,这个作业会被跳过?

【问题讨论】:

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

标签: caching gitlab gitlab-ci yarnpkg


【解决方案1】:

尝试退出?

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

【讨论】:

    【解决方案2】:

    根据官方参考,这在工作级别是不可能的。但是,您可以向作业脚本添加条件并检查是否存在应该缓存的文件。

    这是我设置的相关部分的样子:

    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+ 和带有 node-modules 纱线链接器和 dependency 模块提升限制的纱线工作空间
    • 使用pull 策略的所有作业共享缓存,renew-cache 作业是唯一写入缓存的作业
    • test -d node_modules || &lt;COMMAND&gt; 仅在未找到 node_modules 目录时运行 &lt;COMMAND&gt; - 作业没有缓存
    • 仅当没有缓存或修改任何yarn.lock 时才会推送新缓存
    • 相同的缓存会被重复使用,直到它过期并且yarn.lock 文件不会改变
    • 缓存的node_modules 的测试必须存在于依赖缓存的所有其他构建脚本中 - 缓存可能已过期,并且管道必须是确定性可重复的

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

    希望这会有所帮助:-)

    【讨论】:

      【解决方案3】:

      现在在基于 NPM 的 Preact 项目中,如果 package-lock.json 有任何更改,我正在使用 gitlab-ci.yml 的 only 功能运行安装作业(如果没有,则跳过安装) .然后我的构建作业从安装作业中获取 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,您只需将此处看到的任何 package-lock.json 替换为 yarn.lock,并将 npm ci 替换为 yarn install --frozen-lockfile

      以前,我都是在这样的构建工作中完成的(类似于此处的其他答案之一):

      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 已经减少了大约一分半钟的部署时间。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-30
        • 1970-01-01
        • 1970-01-01
        • 2021-07-02
        • 1970-01-01
        • 2016-03-13
        • 2016-02-02
        • 2020-12-08
        相关资源
        最近更新 更多