Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiline YAML string for GitLab CI (.gitlab-ci.yml)

I'm trying to write a gitlab-ci.yml file which uses a multi-line string for the command. However, it seems like it is not being parsed. I've tried both the - | and - > with identical results.

stages:   - mystage  Build:   stage: mystage   script:     - |         echo -e "             echo 'hi';             echo 'bye';         " 

When it tries to run, it only shows echo -e ' as the script to run, and not the whole multiline string. This causes issues for me.

What would be the correct syntax to write something like this?

like image 371
samanime Avatar asked Mar 02 '17 15:03

samanime


People also ask

How write multi line string in YAML?

If you would like them to be kept as newlines, use the literal style, indicated by a pipe ( | ). If instead you want them to be replaced by spaces, use the folded style, indicated by a right angle bracket ( > ). (To get a newline using the folded style, leave a blank line by putting two newlines in.

Can Gitlab CI Yml have multiple files?

No, you can't have multiple gitlab-ci files per repository.

How do I write a script in Gitlab?

To work around this, run each command as a separate script item, or add an exit 1 command to each command string. You can use the | (literal) YAML multiline block scalar indicator to write commands over multiple lines in the script section of a job description. Each line is treated as a separate command.


2 Answers

I came here preemptively expecting this would be an issue but the following "multi-line" command for readability is working for me:

Gitlab Runner: Shell Runner version 1.11.0 / Gitlab version: 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} 
like image 54
PotatoFarmer Avatar answered Sep 23 '22 18:09

PotatoFarmer


TL;DR; You want to use a multi-line YAML scalar (for readability) that is loaded as a single line string that can be issued as a command by Gitlab-CI. To do so use a plain (without quotes) scalar in YAML that is spread out over multiple lines:

script: - echo -e     "echo 'hi';     echo 'bye';" 

Please be aware that there are some restrictions imposed by YAML on such scalars. What you certainly need to know is that each following line is indented at least one more position than echo -e (which is indented two positions relative to its collection node, which is not indented at all), and that every new-line is replaced by a space when loaded (so you need to take a bit care of where to put newlines).


There are multiple misconceptions in your post, that lead to you asking the wrong question.

There is no such thing as a multi-line YAML string. YAML has scalars and some of these scalars can be loaded by a program as strings, while some others will be loaded as integers, floats, etc.

You are obviously interested in scalar nodes that are being loaded as a string, since that string can be then be interpreted as a command-line. But you don't want to have multi-line command-line (i.e. with embedded newlines), since multi-line scripts are not supported in Gitlab CI (as @Jordan indicated).

For readability you want to use the, standard, capability of YAML to load multi-line scalars as single line string.

If you wouldn't care about readability you could use:

- echo -e "\n    echo 'hi';\n    echo 'bye';\n" 

and since your scalar is not quoted (i.e. it starts with echo) you don't need to do anything special in YAML for the backslashes or quotes.

The result of the script is the same (print an empty line, print echo 'hi'; on a line indented four spaces, print echo 'bye'; on a line indented four spaces.)

If you want to use the multi-line input for readability, that are loaded as a single line, there are essentially two options: use a multi-line plane scalar or use a folded scalar in your YAML.

multi-line plain scalar

Plain means the scalar is non-quoted, and as with any multi-line thing in YAML multi-line means following lines need to be indented appropriately, in this case further than the initial line

script: - echo -e     "echo 'hi';     echo 'bye';" 

newlines are replaced by spaces so don't do:

script: - echo -e     "echo 'hi';     echo '    bye';" 

as you will get a visible space before bye.

There are some restrictions like that you cannot have a colon followed by a space within such a scalar (which would make it look like key-value pair).

There is no need to escape backslashes in plain scalars, as you cannot escape any characters in a plain scalar, but of course you can include a backslash, which will end up in the string loaded from the YAML and can have meaning for the command executed from that string.

folded scalar

A folded scalar is similar to a plain scalar in that all (single) newlines are substituted by a space during loading:

script: - >   echo -e    "echo 'hi';   echo 'bye';" 

You need to indent the actual command information at least as much as the folded scalar indicator (>).

Contrary to plain scalars things like : have no special meaning. So if plain scalars fail by throwing a YAML error, similar folded scalars most likely won't.

like image 26
Anthon Avatar answered Sep 22 '22 18:09

Anthon