#gitlab #gitlab-ci
#gitlab #gitlab-ci
Вопрос:
Представьте, что у вас есть следующий конвейер:
Job A (deploy) -> Job B (test) -> Job C (remove test deployment)
Конвейер должен развернуть тестовый образ и протестировать его после успешного развертывания. После теста я хочу запустить скрипт очистки независимо от результатов теста, но только в том случае, если тестовый образ (задание A) был развернут.
Подводя итог: я хочу, чтобы Gitlab выполнял задание C только в том случае, если задание A выполнено успешно, но после задания B.
Вещи, которые не будут работать:
when: on-failure
(Задание A или задание B может завершиться с ошибкой, но важно только задание A)when: always
(возможно, задание A завершилось с ошибкой, что приводит к сбою задания C)when: on-success
(требуется, чтобы все задания выполнялись успешно)
Я знаю, что в GitLab есть функция, называемая конвейерами DAG, которая позволяет вам указывать несколько зависимостей от других заданий с needs
помощью ключевого слова, но, к сожалению when
, ключевое слово всегда распространяется на все предыдущие задания. Итак, вы не можете сказать что-то вроде:
when:
on-success: job-a
always: job-b
Я что-то пропустил или нет способа добиться такого поведения?
Комментарии:
1. Чтобы уточнить — вы хотите , чтобы задание B (задание тестирования) выполнялось, даже если задание A (развертывание) завершается с ошибкой?
2. Нет, его следует пропустить. Я хочу запустить задание C после завершения или сбоя задания B. Но задание A должно было быть выполнено.
Ответ №1:
Поле needs
DAG можно использовать для условного выполнения очистки (задание C), если задание B завершается неудачно или успешно, но НЕ тогда, когда оно пропущено из-за сбоя задания A.
Создайте 2 задания очистки, которые соответствуют следующим логическим условиям:
(Job A succeeds and Job B succeeds)
: Если все предыдущие задачи завершились успешно (задание A и задание B), мы можем запустить очистку сwhen: on_success
помощью . Однако это не сработает, если задание A завершается успешно, а задание B завершается с ошибкой.(Job A succeeds and Job B fails)
: Чтобы обойти предыдущий сценарий с необработанной очисткой (задание C), мы используем тот факт, что если задание B завершается с ошибкой, это означает, что задание A выполнено успешно в конвейере. Создав повторяющуюся задачу очистки и указавneeds
тег для задания B иwhen: on_failure
, задача очистки будет выполняться только в случае успешного выполнения задания A и сбоя задания B.
Повторяю: задание очистки будет выполняться, если (Job A succeeds and Job B succeeds)
или (Job A succeeds and Job B fails)
, что по логическому выражению эквивалентно (Job A succeeds)
.
Очевидным предостережением здесь является то, что теперь в конвейере отображаются 2 задания очистки; однако они являются взаимоисключающими, и только одно может быть выполнено.
Вот пример конфигурации:
stages:
- deploy
- test
- cleanup
deploy_job:
stage: deploy
script:
- echo Deployed
- "true"
when: always
test_job:
stage: test
script:
- echo Executing tests
- "true"
when: on_success
# a YAML anchor reduces repetition
.cleanup_job: amp;cleanup_job
stage: cleanup
script:
- echo Cleaned up deployment
cleanup_deployment_success:
when: on_success
<<: *cleanup_job
cleanup_deployment_failure:
needs: ["test_job"]
when: on_failure
<<: *cleanup_job
При различных преднамеренных условиях сбоя создаются следующие состояния конвейера:
Логически это указывает на то, что независимо от того, выполнено задание B успешно или неудачно, задание C выполняется, если задание A выполнено успешно. Кроме того, состояние сбоя сохраняется во всем конвейере.
Комментарии:
1. Не приведет ли это к тому, что конвейер будет находиться в переданном состоянии, даже если тесты завершились неудачей? Я хочу, чтобы конвейер находился в состоянии сбоя, если одно задание завершается с ошибкой.
2. @Sebi2020 К сожалению, это так. Если задание завершается с ошибкой, но конвейер «проходит», вместо зеленой галочки «передано» используется восклицательный знак оранжевого цвета с надписью «передано». Я обновил свой ответ, чтобы продемонстрировать, как это выглядит. Триггеры
when
условий не очень сложны в GitLab CI. Я посмотрю еще раз и посмотрю, смогу ли я разрешить состояние сбоя конвейера, но у меня есть серьезные сомнения.3. @Sebi2020 Я обновил свой ответ, чтобы использовать
needs
базы данных и тег. Дайте мне знать, удовлетворяет ли это вашим ограничениям / условиям.4. @Sebi2020 К сожалению, система CI GitLab очень жесткая в своем подходе к конвейерам. Для этого указанного 3-этапного конвейера единственным предостережением здесь является дубликат пропущенного задания очистки, который отображается в конвейере. Если я найду другое решение, я обновлю свой ответ. Однако, прочитав документацию более часа, я не особенно уверен, что будет более чистое решение, пока GitLab не добавит более расширенное сопоставление для
when
тега. Чаще всего большинство моих конфигураций GitLab CI заканчиваются грязными решениями / взломами из-за их незаинтересованности в поддержке нетривиальных вариантов использования.5. Отличные мысли, мой друг. В настоящее время пытаюсь использовать artifacts:when:always для сохранения кода выхода тестового скрипта и вывода его в файл build.env, чтобы я мог прочитать результат в следующем задании. Если это сработает, я тоже опубликую ответ здесь. Мне нравится GitLab, но, милорд, это неуместно.
Ответ №2:
Поле базы данных потребностей может использоваться для условного выполнения очистки (задания
C
), если заданиеB
завершается неудачно или успешно, но НЕ тогда, когда оно пропущено изA
-за сбоя задания.
Это могло измениться с GitLab 13.11 (апрель 2021)
Необязательные задания DAG (‘needs:’) в конвейерах CI / CD
Ориентированный ациклический граф (DAG) в GitLab CI / CD позволяет использовать
needs
синтаксис для настройки запуска задания раньше его этапа (как только завершатся зависимые задания). > У нас также естьrules
ключевые слова ,only
, илиexcept
, которые определяют, добавлено ли задание в конвейер вообще.К сожалению, если вы объедините
needs
эти другие ключевые слова, возможно, что ваш конвейер может завершиться сбоем, когда зависимое задание не будет добавлено в конвейер.В этом выпуске мы добавляем
optional
ключевое слово вneeds
синтаксис заданий DAG.
- Если зависимое задание помечено как
optional
, но отсутствует в конвейере,needs
задание игнорирует его.- Если задание находится
optional
и присутствует в конвейере,needs
задание ожидает его завершения перед запуском.Это значительно упрощает безопасное объединение
rules
,only
, иexcept
с ростом популярности DAG.Смотрите Документацию и проблему.
Ответ №3:
Я хотел бы добавить еще одну альтернативу. В настоящее время я ищу возможность реализовать именно этот вариант использования для e2e-тестов, и я, вероятно, предпочту отложить представление результатов тестирования с помощью артефактов. Настройка будет примерно такой:
Job A (deploy) -> Job B (run test, collect results into artifact) -> Job C (undeploy) -> Job D (publish test results from artifact)
Задание B будет настроено так, чтобы всегда быть успешным, и сохранять свои результаты только как артефакт (например, JUnit xml). Затем задание D опубликует результаты, и конвейер завершится с ошибкой, если тесты не увенчались успехом. Это должно сохранить состояние сбоя конвейера, даже если задание C и задание D выполняются безоговорочно с использованием ранее упомянутого метода дублирования задания с несколькими when:
условиями.