Наследование через extends
Дочерний сервис type: app наследует все поля у указанного родителя. Затем потомок переопределяет только те поля, которые объявляет сам. Многоуровневые цепочки поддерживаются и разрешаются в топологическом порядке — внук получает значения родителя косвенно через своего прямого родителя.
Содержание
Заголовок раздела «Содержание»Защита «только app»
Заголовок раздела «Защита «только app»»extends: отклоняется при загрузке для любой записи type: tool или type: infra. Дискриминатор проверяется до слияния, поэтому межтиповые цепочки никогда не разрешаются.
flowchart LR A[main<br/>defaults: dir, dirs, cli] --> B[main-debug<br/>extends: main] A --> C[main-stage<br/>extends: main] C --> D[main-stage-debug<br/>extends: main-stage]
Правила разрешения
Заголовок раздела «Правила разрешения»- Скалярные поля (
dir,dir_internal,work_dir_internal,cli.mode,cli.shell,cli.user,cli.workdir) — потомок побеждает, если задан, родитель заполняет только когда значение потомка пусто.typeобязателен в каждомservice.ymlи никогда не наследуется. dirs— список родителя идёт первым; записи потомка дописываются; дубликаты удаляются (порядок родителя сохраняется).configs— потомок полностью заменяет родителя, если задан (у потомка свой список); список родителя используется только когда потомок опускает ключ.cli.env— рекурсивное слияние карт: родитель даёт значения по умолчанию, потомок переопределяет по ключу.render.ide.enabled,render.ide.template,render.ai.enabled,render.ai.template,render.git.enabledиrender.git.template— наследуются как скалярные поля. Явныеenabled: true|falseили непустойtemplateпотомка переопределяют родительские; опущенные значения наследуются от родителя. Это позволяет внукам наследовать настройки косвенно.render.config— наследуется целиком, когда потомок не объявляет собственного блокаrender.config:(блок родителя клонируется); потомок с собственнымrender.config:сохраняет его и не сливается с родительским.generated— наследуется, когда потомок не объявляет собственной картыgenerated:(карта родителя клонируется); потомок с собственной картойgenerated:полностью заменяет родительскую, не сливается.compose— наследуется, когда потомок не объявляет собственного спискаcompose:(список родителя клонируется); собственный список потомка полностью заменяет родительский, не сливается.container,required,depends_on— никогда не наследуются. Потомок, опускающийcontainer, по умолчанию получает имя папки сервиса при загрузке. Каждый потомок указывает собственныйdepends_on.
Топологическая сортировка
Заголовок раздела «Топологическая сортировка»Граф extends: разрешается в топологическом порядке, поэтому многоуровневые цепочки (C → B → A) сливаются корректно независимо от порядка обхода карты. Циклы и неизвестные родители сообщаются как ошибки загрузки. Для каждого потомка от родителя наследуются только поля с нулевым значением; при конфликтах поля потомка имеют приоритет. Наследуемые слайсы и карты копируются защитно, поэтому мутация потомка никогда не повреждает родителя.
Разбор примера
Заголовок раздела «Разбор примера»type: appcontainer: app-mainrequired: truedir: ./services/maindirs: [logs, home, runtime]cli: shell: bash user: www-datarender: ide: enabled: truetype: appextends: main # наследует dir, dirs, cli, render и т.д.container: app-main-debugrequired: falsecompose: - compose/services/main/debug.ymlcli: env: - XDEBUG_CONFIG="cli_color=1"render: ide: template: main-debug # переопределить template, оставить enabled: true от родителяmain-debug получает dir, dirs, базовый cli и render.ide.enabled: true от main. Он переопределяет render.ide.template, чтобы использовать пользовательский подкаталог шаблона (workspace/templates/ide/main-debug/), и добавляет собственный оверлей compose и дополнительные env. Когда запускается dwe render ide, оба сервиса разделяют dir: ./services/main, поэтому самый дочерний (main-debug) побеждает и рендерит свой пользовательский шаблон; main пропускается с предупреждением о коллизии.