GitLab CI потерял script после extends: как объединяется конфигурация
В общем CI-шаблоне есть две команды сборки. В проекте добавили третью через extends, а в журнале осталась только новая. YAML синтаксически корректен: ошибка возникла в ожидании, что список script автоматически дополнится. GitLab объединяет словари по ключам, но массив команд в дочерней job заменяет массив родителя.
Чтобы исправить конфигурацию, полезно читать её в два этапа. Include приносит определения из файлов. Extends строит job из шаблонов и её собственных полей. В результате Runner получает одно итоговое описание; порядок файлов в репозитории не превращается в последовательность выполнения команд.
Минимальное наследование
В тестовом репозитории создайте ci/base.yml и основной .gitlab-ci.yml. Первый файл содержит скрытую job .build_base: точка в начале имени исключает её самостоятельный запуск.
# ci/base.yml
.build_base:
image: alpine:3.21
variables:
BUILD_MODE: release
OUTPUT_DIR: dist
script:
- mkdir -p "$OUTPUT_DIR"
- printf '%s\n' "$BUILD_MODE" > "$OUTPUT_DIR/mode.txt"
# .gitlab-ci.yml
include:
- local: ci/base.yml
build:
extends: .build_base
variables:
BUILD_MODE: debug
script:
- printf 'mode=%s output=%s\n' "$BUILD_MODE" "$OUTPUT_DIR"
Ожидаемый вывод — mode=debug output=dist. Переменная BUILD_MODE переопределена, OUTPUT_DIR сохранена из родителя. Но каталог dist не создаётся: собственный script полностью заменил список родителя. Попытка добавить здесь cat dist/mode.txt обнаружит отсутствие файла, а не проблему передачи artifacts.
Сохраним сборку явным действием
Если нужно переиспользовать общий список, его можно явно включить через !reference. В основном файле замените job build следующим определением:
build:
extends: .build_base
variables:
BUILD_MODE: debug
script:
- !reference [.build_base, script]
- cat "$OUTPUT_DIR/mode.txt"
Теперь сначала выполнятся команды базовой сборки, затем чтение файла. Его содержимое должно быть debug, потому что переменные вычисляются для итоговой job. Для достаточно сложной последовательности удобнее вынести команды в версионируемый shell-скрипт репозитория и вызывать его из нескольких jobs: так порядок проще запускать локально и читать в Git diff.
Массивы есть не только у script
Такой же вопрос возникает с rules, tags и before_script. Если переопределить массив, ожидать сохранения элементов родителя нельзя. Особенно опасно незаметно заменить rules релиза: job может начать появляться в источниках, для которых общий шаблон её исключал. Сначала посмотрите конечный набор условий, затем проверяйте, почему конкретный pipeline её добавил.
Когда extends ссылается на несколько родителей, конфликтующие ключи разрешаются с учётом порядка родителей, а собственные поля job имеют приоритет. Несколько уровней наследования делают этот порядок трудным для чтения. Если цепочка требует постоянно открывать четыре файла, сократите её или оставьте явную композицию команд.
YAML anchors и !reference решают разные задачи. Обычные anchors ограничены файлом YAML, а !reference позволяет ссылаться на секции из включённых файлов. При этом такую конструкцию должен понимать GitLab: обычный YAML-парсер без поддержки custom tags не проверяет её семантику.
Проверим конечный результат
Откройте Pipeline editor и посмотрите объединённую конфигурацию, затем запустите CI Lint в контексте проекта. Найдите итоговые image, variables, rules и script именно для build. Если include указывает на другой проект, зафиксируйте ref шаблона: изменение общего файла без изменения прикладного репозитория тоже может поменять поведение следующего pipeline.
В диагностическом запуске сравните итоговую конфигурацию с журналом: появились ли создание каталога, запись mode.txt и чтение файла в нужном порядке. Это отделяет ошибку объединения от ошибки самой команды. Удаление extends ради исправления одного массива дублирует остальные настройки; явное включение нужной последовательности сохраняет общий шаблон и делает порядок видимым.
Ещё по теме
- Cache и artifacts в GitLab CI: как передать результат сборки следующему job
- GitLab CI: job завис в pending — как проверить Runner и теги
Продолжить изучение
Хотите собрать проверяемый путь от коммита до релиза? Jobs, runners, артефакты и деплой — темы программы «GitLab CI/CD: автоматизация сборки и деплоя».
Продолжить на практике
- GitLab CI/CD: автоматизация сборки и деплоя ↗
От первого .gitlab-ci.yml до pipeline, который тестирует код, собирает образ и выкладывает приложение. Runners, artifacts, cache, registry, окружения и безопасный откат — на одном практическом проекте.
