Многострочная строка YAML для GitLab CI (.gitlab-ci.в формате YML)
Я пытаюсь написать gitlab-ci.yml
файл, который использует многострочную строку для команды. Однако, похоже, что он не анализируется. Я пробовал оба - |
и - >
с одинаковыми результатами.
stages:
- mystage
Build:
stage: mystage
script:
- |
echo -e "
echo 'hi';
echo 'bye';
"
когда он пытается запустить, он показывает только echo -e '
как скрипт для запуска, а не вся многострочная строка. Это вызывает проблемы для меня.
каков был бы правильный синтаксис для написания чего-то подобного?
3 ответов
поскольку проблема, похоже, связана с многострочные скрипты не поддерживается в GitLab CI (как указано @Jordan), и ваш "скрипт" на самом деле является одной командой, вы должны просто переписать его на одну строку:
- echo -e "\n echo 'hi';\n echo 'bye';\n"
поскольку ваш скаляр не цитируется (т. е. он начинается с echo
) вам не нужно делать ничего особенного в YAML для обратных косых черт или кавычек.
результат скрипта тот же (печать пустой строки, печать echo 'hi';
на строке с отступом четыре пробела, печать echo 'bye';
в строке с отступом в четыре пробела.)
если вы хотите использовать многострочный вход для удобства чтения, лучшим вариантом является предварительная обработка ввода. Я рекомендую использовать Python и ruamel.yaml (отказ от ответственности: я автор), который позволяет сохранять такие функции, как цитаты и комментарии при этом.
при этом gitlab-ci.in.yml
:
stages:
- 'mystage'
Build:
stage: mystage
# the following is rewritten
script:
- |
echo -e "
echo 'hi';
echo 'bye';
"
и следующий Python (версия 3) программа:
from pathlib import Path
import ruamel.yaml
def flatten_multi_line(d):
if isinstance(d, list):
for idx, elem in enumerate(d):
if isinstance(elem, (list, dict)):
flatten_multi_line(elem)
elif isinstance(elem, ruamel.yaml.scalarstring.PreservedScalarString):
d[idx] = ruamel.yaml.scalarstring.DoubleQuotedScalarString(elem)
elif isinstance(d, dict):
for key in d:
if isinstance(d[key], (list, dict)):
flatten_multi_line(d[key])
elif isinstance(d[key], ruamel.yaml.scalarstring.PreservedScalarString):
d[key] = ruamel.yaml.scalarstring.DoubleQuotedScalarString(elem)
in_file = Path('gitlab-ci.in.yml')
out_file = Path('gitlab-ci.yml')
with in_file.open() as fp:
data = ruamel.yaml.round_trip_load(fp, preserve_quotes=True)
flatten_multi_line(data)
with out_file.open('w') as fp:
ruamel.yaml.round_trip_dump(data, fp)
дает следующее gitlab-ci.yml
:
stages:
- 'mystage'
Build:
stage: mystage
# the following is rewritten
script:
- "echo -e \"\n echo 'hi';\n echo 'bye';\n\"\n"
(без flatten_multi_line()
многострочная строка также будет сохранена).
из программы вы также можете запустить обработку вновь созданного файла YAML (например, с помощью subprocess.check_output()
убедитесь, что бросить out_file
используя str()
если вы хотите, чтобы это было аргументом check_output()
)
Я пришел сюда, заранее ожидая, что это будет проблемой, но для меня работает следующая команда "многострочная" для удобочитаемости:
Гитлаб Бегунок: Shell Runner версия 1.11.0 / версия Gitlab: 8.17.2
myjob:
stage: deploy
script:
# Single line command
- az component update --add sql
# Multi-line command
- az sql server create -n ${variable} -g ${variable} -l ${variable}
--administrator-login ${variable} --administrator-login-password ${variable}
извиняется, если я неправильно понял вопрос или я испытываю некоторую грацию крайнего случая.
вы можете использовать любые многострочные скрипты / команды через функцию yaml literal_block и anchors. Пример:
.build: &build |
echo -e "\n$hl Building $green$build_path/$build_assets_dir/*.js $nl\n"
echo -e "javascript-obfuscator $build_path/$build_assets_dir/*.js"
[...]
build:master:
stage: build
script:
- *rsync
- *build
[...]