Как избежать переустановки зависимостей для каждого задания в GitLab CI

Я использую GitLab CI 8.0 с gitlab-ci-multi-runner 0.6.0. У меня есть .gitlab-ci.yml файл похож на следующий:

before_script:
  - npm install

server_tests:
  script: mocha

client_tests:
  script: karma start karma.conf.js

это работает, но это означает, что зависимости устанавливаются независимо перед каждым тестовым заданием. Для больших проектов со многими зависимостями это добавляет значительные накладные расходы.

в Jenkins я бы использовал одно задание для установки зависимостей, а затем TAR их и создать артефакт сборки, который затем копируется в рабочие места ниже по течению. Будет ли что-то подобное работать с GitLab CI? Есть ли рекомендуемый подход?

4 ответов


лучший подход в эти дни, чтобы использовать артефакты.

в следующем примере node_modules/ каталог немедленно доступен для lint работу после build этап успешно завершен.

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

обновление: теперь я рекомендую использовать artifacts С коротким expire_in. Это превосходит cache потому что он должен писать артефакт только один раз на конвейер, тогда как кэш обновляется после каждого задания. Кроме того, кэш для каждого бегуна, поэтому, если вы выполняете свои задания параллельно на нескольких бегунах, он не будет заполнен, в отличие от артефактов, которые хранятся централизованно.


GitLab CI 8.2 добавляет бегунок кэширование что позволяет повторно использовать файлы между сборками. Однако я обнаружил, что это очень медленно.

вместо этого я реализовал свою собственную систему кэширования, используя немного сценариев оболочки:

before_script:
  # unique hash of required dependencies
  - PACKAGE_HASH=($(md5sum package.json))
  # path to cache file
  - DEPS_CACHE=/tmp/dependencies_${PACKAGE_HASH}.tar.gz
  # Check if cache file exists and if not, create it
  - if [ -f $DEPS_CACHE ];
    then
      tar zxf $DEPS_CACHE;
    else
      npm install --quiet;
      tar zcf - ./node_modules > $DEPS_CACHE;
    fi

это будет работать перед каждым заданием в вашем .gitlab-ci.yml и только установить зависимости, если package.json изменился или файл кэша отсутствует (например, первый запуск или файл был удален вручную). Обратите внимание, что если у вас есть несколько бегунов на разных серверах, каждый из них будет иметь свой собственный файл кэша.

вы можете хотите очистить файл кэша на регулярной основе, чтобы получить последние зависимости. Мы делаем это со следующей записью cron:

@daily               find /tmp/dependencies_* -mtime +1 -type f -delete

Я думаю, что это не рекомендуется, потому что все задания одного этапа могут выполняться параллельно.

  1. сначала все задания сборки выполняются параллельно.
  2. Если все задания сборки выполняются успешно, тестовые задания выполняются параллельно.
  3. Если все задания теста выполнены успешно, задания развертывания выполняются параллельно.
  4. если все задания развертывания выполнены успешно, фиксация помечается как успешная.
  5. Если какое-либо из предыдущих заданий завершается неудачно, фиксация помечается как failed и никакие задания дальнейшего этапа не выполняются.

Я прочитал это здесь:

http://doc.gitlab.com/ci/yaml/README.html


Я предпочитаю использовать кэш, потому что удаляет файлы когда производство завершено.

пример

image: node

stages:
 - install
 - test
 - compile

cache:
 key: modules
 paths:
  - node_modules/

install:modules:
 stage: install
 cache:
  key: modules
  paths:
    - node_modules/
  after_script:
   - node -v && npm -v
  script:
  - npm i

test:
 stage: test
 cache:
   key: modules
   paths:
     - node_modules/
   policy: pull
 before_script:
  - node -v && npm -v
 script:
- npm run test

compile:
 stage: compile
 cache:
 key: modules
 paths:
   - node_modules/
 policy: pull
 script:
  - npm run build