How to use multiline command in 'script:' with YAML?

BashContinuous IntegrationYamlTravis Ci

Bash Problem Overview


I have a repository that uses Travis CI, and in the .travis.yml there I have this line:

script:
- vim -Nu <(cat <<-EOF
  set nocompatible |
  filetype off
  EOF
  ) -c 'Script' > /dev/null

Sadly this doesn't work, as this is transformed into a single line and is executed like this:

vim -Nu <(cat <<-EOF set no compatible | filetype off | EOF ) -c 'Script' > /dev/null

This makes the EOF tag not working, as EOF needs to be in a single line. An alternative would be to just use normal quotes like this:

script:
- vim -Nu <(cat 'set nocompatible |
  filetype off
  ) -c 'Script' > /dev/null

Which works, and is fine, but I feel there must be a way to insert newlines into a .travis.yml. I have an alternative now, but I may not in the future. So how do you do it?

Bash Solutions


Solution 1 - Bash

In YAML you can specify newlines in a scalar by using "" quoting and escaping the newlines (\n), or, and that is more natural for your case, by using a literal style block scalar:

script:
- |
  vim -Nu <(cat <<-EOF
  set nocompatible |
  filetype off
  EOF
  ) -c 'Script' > /dev/null

This is a scalar starting with a line with a | (pipe symbol), followed by multiple lines for which the line-breaks are preserved.

  • The lines are normally indented (exception: a single top-level literal style block scalar).

  • After the | there can be modifiers: 1-9, used when your first line starts with spaces; +, - to influence stripping of final newlines (normally collapsed into one).

Solution 2 - Bash

I use the folded block style to achieve exactly the desired effect:

script:
    - >
      valgrind
      --read-var-info=yes
      --error-exitcode=1
      --fullpath-after=
      --track-origins=yes
      --leak-check=full
      --num-callers=20
      --suppressions=$(pwd)/tests/zephir_parser.3.7.0.sup
      $(phpenv which php)
          -d variables_order=EGPCS
          run-tests.php
              -p $(which php)
              -d extension=$(pwd)/modules/zephir_parser.so
              -d variables_order=EGPCS
              -g "FAIL,XFAIL,BORK,WARN,LEAK,SKIP"
              --offline
              --show-diff
              --set-timeout 120

Note: Using Yaml folded block style, each line break is replaced by a space. The indention in each line will be ignored. A line break will be inserted at the end. Thus, you must not use \ here:

script:
    - >
      valgrind \               <- wrong
      --read-var-info=yes

Otherwise it will be treated as valgrind \ --read-var-info=yes.

Another working example is Line Folding. Consider the following example of the Line Folding which is supported by GitHub Actions:

  - name: Configure (x64 Debug)
    run: >-
      cmake
      -S .
      -Bbuild
      -DCMAKE_BUILD_TYPE=Debug
      -DCPPCHECK=ON
      -DWARNINGS_AS_ERRORS=ON
      -DCMAKE_INSTALL_PREFIX=/opt/my-program
      -DCMAKE_EXPORT_COMPILE_COMMANDS=ON

Note: In this example we use >- right after run: and lines are left aligned, using the same indentation at the beginning of the line.

Solution 3 - Bash

What you are looking for is |. Here is a very clear example to refer to.

   build:
     commands:
       - echo "${CODEBUILD_BUILD_ARN}"
       - |
         if expr "${CODEBUILD_BUILD_ARN}" : ".*build/MyProjectDev-" >/dev/null; then
           yarn run build-dev;
         fi
       - |
         if expr "${CODEBUILD_BUILD_ARN}" : ".*build/MyProject-" >/dev/null; then
           yarn run build-prod;
         fi

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionhgieselView Question on Stackoverflow
Solution 1 - BashAnthonView Answer on Stackoverflow
Solution 2 - BashsergheiView Answer on Stackoverflow
Solution 3 - BashShivam AnandView Answer on Stackoverflow