Для выполнения действия необходимы учётные данные:
password— пароль (токен) пользователя, от имени которого будет запускаться выполнение действия.username— имя пользователя, от которого будет запускаться выполнение действия.
CreateRepositoryFromTemplate — создаёт новый репозиторий из шаблона в GitLab. Механизм рендеринга основан на Go template и поддерживает все встроенные методы, а также расширения, добавленные в платформу.
Пример запроса
sourceBranch: main
sourceTag: v1.0.0
templateRepositoryUrl: https://gitlab.example.com/example-1.git
targetRepositoryUrl: https://gitlab.example.com/example-2.git
targetBranch: master
additionalIgnoreFiles:
- .ignore
- .example
values:
key1: value1
nested:
enabled: true
subkey: 123Спецификация запроса
| Название | Обязательность | Описание | Значение по умолчанию |
|---|---|---|---|
| templateRepositoryUrl | Да | URL шаблонного репозитория | - |
| targetRepositoryUrl | Да | URL репозитория, который будет создан в результате выполнения действия | - |
| values | Да | Переменные, используемые при шаблонизации, в формате ключ: значение | - |
| additionalIgnoreFiles | Нет | Список файлов, содержащих пути для исключения из целевого репозитория. Заполняется по аналогии с .templateignore | - |
| sourceTag | Нет | Тег шаблонного репозитория, который будет использоваться при шаблонизации. Если не указан, используется ветка шаблонного репозитория | - |
| sourceBranch | Нет | Ветка шаблонного репозитория, которая будет использоваться при шаблонизации | main |
| targetBranch | Нет | Ветка целевого репозитория, которая будет создана в результате выполнения действия | main |
Алгоритм работы
Платформа:
- Клонирует шаблонный репозиторий по указанному URL (
templateRepositoryUrl), используя в качестве ref либоsourceTag, либоsourceBranch, либо веткуmain. - Считывает файл
values.yaml, хранящийся в корне репозитория, и определяет переменные по умолчанию для шаблонизации. - Считывает переменные, передаваемые при запуске действия, и объединяет (merge) их с переменными из
values.yaml. Приоритет при merge отдаётся переменным, передаваемым при запуске действия. - Считывает файл
.templateignoreи определяет директории и файлы, исключаемые из шаблонизации. - Рендерит из шаблонов файлы, учитывая
values.yamlи переданные в действие переменные. - Изменяет удалённый (remote) репозиторий на целевой (
targetRepositoryUrl) и делает git push в целевую ветку (targetBranch), либо в основную веткуmain.
Детали работы
Действие поддерживает шаблонизацию имён директорий и файлов. Для этого необходимо в их название добавить выражение в формате Go template.
Например, директория src/{{ .module }}/utils при наличии value module со значением example будет отрендерена в директорию src/example/utils в целевом репозитории.
Если после рендеринга из шаблона содержимое файла будет отсутствовать, файл не создаётся. Например, файл с содержимым:
{{- if .createContent }}
- Это контент, который будет отображаться, если переменная createContent == true
{{- end }}не будет создан, если переменная createContent имеет значение false. Аналогичным образом, не будут созданы файлы, изначально являющиеся пустыми.
При отсутствии переменных для шаблонизации одновременно в файле values.yaml и в переменных, передаваемых при запуске действия, рендеринг завершится с ошибкой и целевой репозиторий создан не будет.
Переменные шаблонного репозитория
Для добавления переменных по умолчанию, используемых при шаблонизации, необходимо создать в корне репозитория файл values.yaml с соответствующим содержимым.
Пример файла values.yaml:
module: example
createContent: falseФайл values.yaml является опциональным.
Исключение файлов
Некоторые файлы могут содержать переменные в формате Go template, которые необходимо сохранять при рендеринге репозитория из шаблона, например, Helm-чарты в директории helm. Директория .git игнорируется всегда.
Для исключения подобных файлов из механизма рендеринга следует добавить в корень репозитория файл .templateignore с соответствующим содержимым.
В каждой строке .templateignore задаётся одно правило — путь или маска. Если в строке есть {{, вся строка выполняется как один шаблон Go с теми же переменными и функциями, что при подстановке в имена файлов и каталогов (подробнее — «Как обрабатывается строка правила»). Если {{ в строке нет, подстановка переменных из values.yaml и из запроса действия не делается: строка читается как есть и сравнивается с относительным путём на диске, допускаются литералы и символы маски * и **.
Пример файла .templateignore только с масками пути, без шаблонов подстановки, для игнорирования содержимого директорий helm, docs:
helm/**
docs/**Добавление путей в игнорирование
- В корне шаблонного репозитория создайте или отредактируйте файл
.templateignore(по одному правилу на строку). - Каждая строка — это одно правило: путь от корня репозитория. В нём допускаются обычные символы пути и маски: звёздочка
*в имени сегмента, последовательность**— для произвольной глубины вложенных каталогов. Платформа сопоставляет относительный путь с маской по встроенным правилам (аналогично распространённым соглашениям для масок в файлах игнорирования в системах контроля версий). - Чтобы подставить фрагмент пути из
values.yamlили из поляvaluesзапроса действия, используйте в строке конструкции Go template ({{ ... }}). Если в строке есть{{, платформа обрабатывает всю строку от начала до конца как один шаблон Go: нельзя оставить часть строки «простым текстом» и шаблонизировать только середину пути. Примеры — в разделе «Примеры Go template в.templateignore». - Пустые строки и строки, начинающиеся с
#, при разборе файла пропускаются — их можно использовать для комментариев.
Примеры без подстановки (только маски пути)
Отдельные файлы в корне:
package-lock.json
yarn.lock
LICENSE
.env.localКаталоги целиком и типичные артефакты сборки:
vendor/**
node_modules/**
dist/**
build/tmp/**Вложенность по маске:
docs/**/*.pdf
charts/*/values.schema.json
.github/workflows/**Секреты по расширению во всём дереве:
**/*.pem
**/*.keyОбработка строки правила
Переменные для раскрытия правил те же, что объединены из values.yaml в корне шаблонного репозитория и из поля values в запросе действия (приоритет у values в запросе).
Для каждой непустой строки из .templateignore или из файла из additionalIgnoreFiles платформа делает следующее.
- В список правил всегда попадает строка как в файле, без изменений. Именно её потом сравнивают с путём к файлу в первую очередь — это нужно, когда в именах на диске ещё есть фрагменты вроде
{{ .module }}до переименования. - Если в строке есть
{{, платформа один раз прогоняет всю строку через шаблонизатор Go template с теми же возможностями, что при подстановке в имена файлов и каталогов (встроенные функции платформы и набор Sprig). Если{{в строке нет, этот шаг пропускают. - Если шаг подстановки был и полученный текст отличается от строки в файле (включая случай «на выходе пусто»), в список правил добавляют вторую запись — уже с этим полученным текстом. Итого из одной строки файла может получиться две записи в списке. При проверке пути к файлу смотрят обе: достаточно совпадения с любой из них — файл попадает под правило.
Дальше при обходе дерева для каждого пути к файлу вычисляется путь относительно корня клонированной копии (с прямыми слешами). Путь сравнивается с каждым правилом: сначала по правилам сопоставления с маской (в том числе с использованием * и **), при необходимости — по точному совпадению строки правила и относительного пути.
Так одна строка в файле может задать два правила: например, исходное charts/{{ .name }}/** (чтобы не трогать путь до переименования каталогов), и раскрытое charts/billing/** (чтобы совпадало с путём после подстановки переменных в имена на диске). Поэтому правила работают и «до», и «после» этапа переименования каталогов по шаблону.
Если шаблон в строке синтаксически неверен или обращается к отсутствующему полю, раскрытие правил завершается ошибкой, и рендер репозитория не продолжается.
Поле additionalIgnoreFiles в действии задаёт имена дополнительных файлов в корне репозитория; в каждом из них — такие же строки-правила, как в .templateignore, с тем же раскрытием шаблонов. Но смысл другой: совпавшие пути убирают из рабочей копии (каталог или файл удаляют), и делают это дважды — в начале и в конце цепочки обработки, чтобы эти объекты не участвовали в дальнейших шагах и не попали в итоговый репозиторий.
Файл .templateignore, наоборот, означает «не шаблонизировать»: для совпавших путей платформа не подставляет переменные в содержимое файлов и не применяет к соответствующим каталогам переименование по шаблону в пути. Сами файлы и каталоги при этом не удаляются только из‑за записи в .templateignore — они остаются в копии, но обрабатываются как обычный текст и обычные имена, без шага шаблонизации.
Примеры Go template в .templateignore
Ниже в каждом примере показаны фрагменты values.yaml (или эквивалентные поля в values запроса) и строки .templateignore. Несколько независимых правил задают несколькими строками файла: результат одной строки-шаблона — одна строка с маской; перевод строк внутри результата шаблона не делит правило на несколько.
Имя каталога в правиле берётся из values.yaml или из values действия:
values.yaml:
project: payment-gateway.templateignore:
{{ .project }}/legacy/**В набор правил попадут строки {{ .project }}/legacy/** и payment-gateway/legacy/**.
Сегмент пути из переменной и фиксированная часть, которая сохраняется после подстановки значения переменной:
values.yaml:
lang: ru.templateignore:
apps/{{ .lang }}/messages.yamlУсловное правило в одной строке работает следующим образом: при skipGenerated: false подстановка даёт пустую строку, которая всё равно добавляется вторым правилом. Исходная строка с {{ используется как маска пути и обычно не совпадает с реальными путями. При skipGenerated: true вторым правилом становится generated/**):
values.yaml:
skipGenerated: false.templateignore:
{{- if .skipGenerated }}generated/**{{- end }}Вариант «игнорировать только не production»:
values.yaml:
tier: staging.templateignore:
{{- if ne .tier "prod" }}mock/**{{- end }}Использование printf для сборки строки маски (удобно, если имя чарта в переменной):
values.yaml:
chartName: wordpress.templateignore:
{{ printf "charts/%s/**" .chartName }}Значение по умолчанию для «пустого» значения — функция default из набора Sprig. Поле в данных должно существовать (иначе при раскрытии сработает missingkey=error); для «не задано в YAML» заведите ключ с пустой строкой или используйте условие if / index:
values.yaml:
envName: "".templateignore:
{{ default "dev" .envName }}/secrets/**При пустом envName в правило попадёт и {{ default "dev" .envName }}/secrets/**, и dev/secrets/**.
Опциональный сегмент пути (with):
values.yaml:
analyticsModule: tracking.templateignore:
{{ with .analyticsModule }}{{ . }}/vendor/**{{ end }}Если analyticsModule пусто, шаблон даёт пустую строку (правила раскрытия приведены выше).
Доступ к полю вложенной структуры по строковому ключу index:
values.yaml:
regions:
primary: eu-west.templateignore:
configs/{{ index .regions "primary" }}/bootstrap.yamlУдаление пробелов в сегменте имени — функция trim из набора Sprig:
values.yaml:
serviceName: " billing-api ".templateignore:
{{ trim .serviceName " " }}/logs/**Несколько фрагментов в одной маске:
values.yaml:
base: services
variant: canary.templateignore:
{{ .base }}/{{ .variant }}/**/*.tmpПримеры для additionalIgnoreFiles
В спецификации действия перечисляются имена файлов в корне репозитория (например, .ship-ignore, .ci-remove). Формат строк внутри таких файлов тот же: комментарии #, пустые строки, маски пути, при необходимости — шаблоны Go в строках.
Файл .ship-ignore в шаблоне:
# не попадает в целевой репозиторий
local/fixtures/**
scratchpad.mdФрагмент запроса действия:
additionalIgnoreFiles:
- .ship-ignoreШаблон в файле для additionalIgnoreFiles (удаление каталога, имя из переменных):
Файл .env-drop в корне шаблона:
{{ .obsoleteDir }}/**При obsoleteDir: legacy-ui из values после раскрытия в списке удаления окажутся и {{ .obsoleteDir }}/**, и legacy-ui/** — совпавшие пути будут удалены из копии перед финальными шагами.
Учитывайте различия:
.templateignoreоставляет файлы на диске, но отключает для них переименование пути и рендер содержимого;- списки из
additionalIgnoreFilesудаляют совпавшие пути из рабочей копии.
Пример структуры директорий шаблонного репозитория
├── example-folder-01
│ ├── example-file-01
│ └── {{ .example }}-file-02
├── {{ .example }}-folder-02
│ └── ...
├── values.yaml
└── .templateignoreЕсли переменная example при рендере репозитория примет значение new, то итоговая структура после рендера будет выглядеть следующим образом:
├── example-folder-01
│ ├── example-file-01
│ └── new-file-02
├── new-folder-02
│ └── ...
├── values.yaml
└── .templateignoreЛокальная отладка
Для локальной отладки шаблонов доступна утилита ddp-render-dir.
Утилита:
- Создаёт копию исходной директории.
- Выполняет рендеринг файлов в этой директории по тем же правилам, что и действие создания репозиториев из шаблонов.
Ключи командной строки для запуска:
--source-dir— исходная директория, которую необходимо отрендерить.--target-dir— директория, в которую будет помещен результат рендеринга.--values(опционально) — путь к файлуvalues.yamlс переменными, которые будут использоваться при рендеринге.--ignore-files(опционально) — список файлов, содержащих пути для исключения из целевого репозитория.