Как избежать переустановки зависимостей для каждой работы в 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? Есть ли рекомендуемый подход?

Ответы

Ответ 1

В наши дни лучше использовать artifacts.

В следующем примере каталог 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

Ответ 2

Обновить. Теперь я рекомендую использовать 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

Ответ 3

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

пример

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

Ответ 4

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

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

Я читал, что здесь:

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

Ответ 5

Из документов:

  • cache: используется для временного хранения зависимостей проекта. Не полезно для хранения промежуточных результатов сборки, таких как файлы jar или apk. Кэш-память была разработана для ускорения вызовов последующих запусков заданного задания, сохраняя такие вещи, как зависимости (например, пакеты npm, пакеты Go-вендора и т.д.), Чтобы их не нужно было повторно загружать из общедоступного Интернета. Хотя кэш-память может использоваться для передачи промежуточных результатов сборки между этапами, могут быть случаи, когда артефакты лучше подходят.

  • artifacts: используйте для результатов этапа, которые будут передаваться между этапами. Артефакты были разработаны для загрузки некоторых скомпилированных/сгенерированных битов сборки, и они могут быть выбраны любым числом одновременных бегунов. Они гарантированно доступны и предназначены для передачи данных между заданиями. Они также могут быть загружены из пользовательского интерфейса. Артефакты могут существовать только в каталогах, относящихся к каталогу сборки, и указание путей, которые не соответствуют этому правилу, приводит к появлению неинтуитивного и нелогичного сообщения об ошибке (расширение обсуждается на https://gitlab.com/gitlab-org/gitlab-ce/issues./15530). Артефакты должны быть загружены в экземпляр GitLab (не только GitLab Runner), прежде чем запускать задания следующего этапа, поэтому вам необходимо тщательно оценить, позволяет ли ваша пропускная способность получать прибыль от распараллеливания с этапами и общими артефактами, прежде чем тратить время в изменениях в настройках.

Итак, я использую cache. Когда не нужно обновлять де-кеш (например, создавать папку в тестовом задании), я использую policy: pull (см. Здесь).