Многострочная строка 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
[...]