GitLab pipeline не создаётся из-за needs: условные jobs и optional

В основной ветке pipeline проходит, а в feature-ветке GitLab отказывается его создавать: job needs another job, but it was not added to the pipeline. Скрипты даже не начали выполняться. GitLab собрал конфигурацию, применил правила добавления jobs и обнаружил ссылку на отсутствующий узел графа.

Типичный пример — расширенный анализ только для main и задача сводки, которая выполняется всегда. Сводка перечисляет анализ в needs, хотя в остальных ветках его нет. Прежде чем добавлять optional, надо решить, действительно ли потребитель умеет работать без этой проверки или её результата.

Две разные зависимости

Если сборка использует файл, произведённый другой job, отсутствие производителя делает сборку невозможной. Тогда согласуйте rules обеих jobs: потребитель должен появляться только там, где есть обязательный производитель. Если же анализ только дополняет общий процесс и его отсутствие допустимо, связь можно объявить необязательной.

Следующий полный .gitlab-ci.yml показывает второй случай. Здесь summary читает идентификатор commit и ничего не требует от extra_check. Обязательная проверка base_check остаётся в любом pipeline.

stages: [test, report]
default:
  image: alpine:3.21

base_check:
  stage: test
  script: test -n "$CI_COMMIT_SHA"

extra_check:
  stage: test
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
  script: test -n "$CI_PROJECT_PATH"

summary:
  stage: report
  needs:
    - job: base_check
    - job: extra_check
      optional: true
  script:
    - printf '%s\n' "$CI_COMMIT_SHA"

В основной ветке summary ждёт обе проверки. В feature-ветке она ждёт base_check, а отсутствие extra_check не мешает созданию pipeline. Это и есть смысл needs:optional: опционально наличие job в графе. Если extra_check присутствует и завершается ошибкой, optional сам по себе не разрешает игнорировать эту ошибку.

Почему задача неожиданно стартовала раньше

Needs задаёт непосредственные зависимости выполнения. Если перечислены только optional jobs и ни одна не добавлена, зависимостей не остаётся: задача может стартовать сразу, подобно needs: []. Номер stage тогда не создаёт ожидаемый барьер перед ней. В примере обязательная base_check оставлена намеренно, чтобы сводка не начиналась до базовой проверки.

Особенно внимательно смотрите на jobs публикации. Исправление ошибки создания графа не должно превращать обязательный security scan в необязательное украшение. Если политика требует его в release pipeline, сохраните обязательную связь и добейтесь появления scan в этом же источнике запуска.

Проверим именно тот состав, который видит GitLab

Откройте Pipeline editor и итоговую объединённую конфигурацию вместе с include. Найдите точное имя нужной job, её rules и правила потребителя. Похожее имя из другого шаблона не считается той же зависимостью. Скрытая job с точкой в начале имени служит шаблоном и не становится выполняемым узлом автоматически.

Проверьте условие на том источнике, где появляется ошибка. Правило по CI_COMMIT_BRANCH может срабатывать в branch pipeline и не срабатывать в merge request pipeline. Наличие одинакового commit SHA не означает одинаковый набор переменных и jobs. Сопоставляйте source, ветку, тег и изменённые файлы, если используется changes.

Если необязательная job всё-таки публикует дополнительный отчёт, скрипт потребителя должен обработать отсутствие файла явно. Optional не создаёт пустой artifact и не подставляет результат из предыдущего pipeline. Опишите ветку без отчёта, либо сделайте производителя обязательным. Иначе ошибка просто переместится со стадии создания графа на чтение файла.

Как убедиться, что граф исправлен

Проверьте YAML через CI Lint, затем создайте pipeline в основной и в обычной ветке. В первом должны быть все три jobs, во втором — base_check и summary. В тестовом проекте отдельно сломайте extra_check для основной ветки и убедитесь, что требуемая политика ошибок сохраняется. Успешное создание pipeline проверяет целостность графа; порядок и реакцию на ошибку проверяют уже его выполнением.

После изменения причина каждой связи должна читаться из конфигурации: base_check необходим всегда, extra_check нужен только при наличии, summary способна выполнить свою задачу в обоих случаях. Тогда следующий условный include не заставит наугад помечать optional весь список needs.

Ещё по теме

Продолжить изучение

Хотите собрать проверяемый путь от коммита до релиза? Jobs, runners, артефакты и деплой — темы программы «GitLab CI/CD: автоматизация сборки и деплоя».

Продолжить на практике

  • GitLab CI/CD: автоматизация сборки и деплоя ↗

    От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.