Как сделать так, чтобы Gitlab CI Pipeline всегда запускал одни задания, а другие - только по мерж-реквестам?

TL/DR: Моя цель состоит в том, чтобы иметь конвейер Gitlab (CE-12.4.2), который всегда выполняет некоторые задания только в запросах на слияние, а другие задания всегда (в запросах слияния и при всех обычных пушах). Как должен.gitlab-ci.yml смотреть, чтобы сделать это?

Мой вариант использования: у меня есть большой конвейер, на котором выполняется множество заданий (тесты, проверка, dep, build, doc, ...). Теперь я добавил промежуточную среду (с использованием кубернетов), и конвейер построил новый образ и развернул его в промежуточной среде. Это позволяет мне мгновенно открыть измененное (веб-) приложение и посмотреть, как изменения ведут себя и выглядят, без необходимости проверять их локально. Теперь создание образа и его развертывание в промежуточной среде потребовало бы слишком больших ресурсов для выполнения каждого толчка, поэтому мне нужны развертывания в промежуточной среде только тогда, когда кто-то создает для меня запрос на слияние.

Очень упрощенный пример:

install:
  script: ...

test:
  script: ...

build-image:
  script: ...
  only: [merge_requests]

deploy-staging:
  script: ...
  only: [merge_requests]

Для всех обычных толчков рабочие места install а также test должен быть выполнен.

Для мерж-реквестов вакансии install, test, build-image а также deploy-staging должен быть выполнен.

Что я пробовал: в Gitlab есть эта функция для определенияonly: [merge_requests]в задании это приводит к тому, что задание будет выполняться только тогда, когда конвейер выполняется для запроса слияния. Похоже, именно то, что я ищу, но есть большая загвоздка. После того, как этот атрибут применяется к одному заданию в конвейере, все другие задания в этом конвейере, у которых нет этого атрибута, будут удалены из конвейера при выполнении внутри запросов на слияние. Сначала это показалось мне ошибкой, но на самом деле это задокументированное поведение:

In the above example, the pipeline contains only a test job. Since the build and deploy jobs don’t have the only: [merge_requests] parameter, they will not run in the merge request.

Чтобы повторно ввести все остальные задания в конвейер для мерж-реквестов, я должен применить only: [merge_requests]ко всем другим работам. Проблема с этим подходом в том, что теперь эти обычные задания больше не выполняются для обычных git-push. И у меня нет возможности повторно ввести эти регулярные задания в конвейеры для обычных push, потому что Gitlab не поддерживаетonly: [always] или что-нибудь в этом роде.

Я также заметил, что only синтаксис является кандидатом на устаревание, и следует предпочесть rulesсинтаксис вместо этого, поэтому я взглянул на это. У такого подхода есть несколько проблем:

  • Единственный способ обнаружить с помощью rules выполняется ли конвейер для мерж-реквеста или нет, заключается в оценке переменных, связанных с мерж-запросами, например $CI_MERGE_REQUEST_ID. К сожалению, эти переменные существуют только тогда, когдаonly: [merge_requests] используется, что вновь вызовет указанные выше проблемы.
  • Правила разрешают только условное применение других атрибутов, поэтому мне все равно придется использовать only, except или whenатрибуты для фактического удаления или добавления заданий из конвейера или в него. К сожалению, Gitlab не поддерживает ничего подобногоonly: [never] или when: never, поэтому у меня нет возможности удалить или добавить вакансии.

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

Последнее, что я отчаянно пробовал, - это всегда включать все вакансии и просто отмечать их как when: manualзапускаться вручную нажатием кнопки. Это в некоторой степени работает, но очень утомительно, потому что развертывание в промежуточную стадию - это процесс, состоящий из нескольких заданий, и каждое задание занимает некоторое время. Итак, я бы увидел мерж-реквест, нажал кнопку для первого задания, подождал 5 минут, нажал следующую кнопку, снова подождал 5 минут, и только после этого смог бы использовать постановку. Для многих небольших запросов на слияние это заняло бы у меня много времени и не было бы эффективным решением. Я также не могу просто пометить первое из этих заданий как ручное, потому что Gitlab тогда просто пропустит это задание и выполнит последующие не по порядку (И сноваneeds а также dependencies похоже, не влияют на это при работе с заданиями, запускаемыми вручную).

Что меня немного сбивает с толку, так это то, что после поиска в сети я не нашел никого с такой же проблемой. Либо я единственный пользователь Gitlab, который хочет выполнять некоторые задания только для запросов на слияние без исключения всех других заданий (что кажется маловероятным), либо мне не хватает чего-то очевидного (что кажется более вероятным). Я что-то упустил или Gitlab действительно не поддерживает этот вариант использования?

4 ответа

Из предыдущего ответа :

Но есть проблема. В этом примере после создания MR запускаются два конвейера для каждой отправки. Один для only: [branch], один для only: [merge_requests]

Проверьте, может ли помочь последний GitLab 13.8 (январь 2021 г.):

Используйте как ответвления, так и конвейеры MR без дублирования

Ранее было невозможно сначала запускать конвейеры для веток, а затем переключаться на конвейеры мерж-реквестов при создании MR.

Следовательно, в некоторых конфигурациях отправка в ветку могла привести к дублированию конвейеров, если в ветке уже был открыт мерж-реквест: один конвейер в ветке, а другой — для мерж-реквеста.

Теперь вы можете использовать новый $CI_OPEN_MERGE_REQUESTSпредопределенную переменную среды в конфигурациях CI, чтобы переключаться с ответвленных конвейеров на конвейеры MR в нужное время и предотвращать избыточные конвейеры.

См. Документацию и выпуск .

user2993689 указывает в комментариях к документации на аналогичный пример:

Избегайте дублирования конвейера

В трубопроводы MR можно добавлять задания. У меня есть пример отсюда: https://docs.gitlab.com/ee/ci/merge_request_pipelines/index.html

Общая идея: вы определяете only: [branch, merge_requests] для каждого задания, а для задания развертывания перепишите его с only: [merge_requests].

.only-default: &only-default
  only:
    - branches
    - merge_requests

build:
  stage: build
  tags:
    - build
  <<: *only-default
  script:
    - echo build

deploy mr:
  stage: deploy
  tags:
    - build
  only:
    - merge_requests
  script:
    - echo "deploy on MR"

Но существует проблема. В этом примере запускаются два конвейера для каждого нажатия после создания MR. Один дляonly: [branch], один для only: [merge_requests]. Вот какonly: [merge_requests]работа, он запускает работу при каждой смене MR. Новый коммит - это определенно изменение.

Кажется, не существует решения, которое могло бы запускать конвейер ТОЛЬКО для определенного события - например, создания MR.

Но я думаю, что возможен обходной путь:

  1. Развернуть существующие промежуточные задания для каждого конвейера
  2. Скрипт задания проверяет, создан ли MR для текущей ветви
  3. Если MR создается, скрипт устанавливает метку для этого MR, например 'staging deployed'
  4. Если этот ярлык уже существует или MR не создан, ничего не делайте.

В этом могут помочь GitLab API, curl и jq. Если будет свободное время, обязательно постараюсь написать:).

Следующее сработало для меня. Идея состоит в том, чтобы определить значение по умолчанию для всех заданий CI с помощью ключевого слова. Затем для задания CI, которое вы хотите запускать только на MR, определите отдельный запуск (оно перезаписываетworkflowправила этой работы).

      workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
    - if: $CI_PIPELINE_SOURCE == "push"

install:
  script: ...

test:
  script: ...

build-image:
  script: ...
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

deploy-staging:
  script: ...
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"

У меня такая же проблема.

Как описано в GitLab Docs , вам необходимо настроить весь конвейер для работы в конвейерах мерж-реквестов.

Этого можно добиться, добавив следующее поверх файла .gitlab-ci.yml.

      workflow:
  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'

Надеюсь, я смог помочь!

Другие вопросы по тегам