Github Action: Split Long Command into Multiple Lines

31,862

Solution 1

I have a multi line command using backslash to separate the lines as follows:

- name: Configure functions
  run: |
    firebase functions:config:set \
      some.key1="${{ secrets.SOME_KEY_1 }}" \
      some.key2="${{ secrets.SOME_KEY_2 }}" \
    ...    

Note the preceding '|' character.

Solution 2

You can use the YAML folded style with > which is supported by GitHub Actions.

For example,

run: >
  xvfb-run
  ./mvnw -f my/pom.xml
  clean verify
  -DskipTests

newlines will be replaced with spaces so the above is equivalent to

run: xvfb-run ./mvnw -f my/pom.xml clean verify -DskipTests

Solution 3

Going to share this in since it has not been mentioned.

You can use:

  • | called a Literal Block Scalar which preserves new lines and trailing spaces
  • > called a Folded Block Scalar which converts new lines into spaces
  • plain old strings, either unquoted, single-quoted or double-quoted

I found the site yaml-multiline.info useful for understanding how yaml strings are interpreted.

For my use case, I ended up doing the following:

run: >-
  for i in $(find . -type f -name "*.log");
  do
   echo "File: ${i} \n";
   cat $i;
   printf '%*s\n' "${COLUMNS:-$(tput cols)}" '' | tr ' ' -;
  done

Solution 4

This was not possible using backslashes, earlier. See the accepted answer on how to do it now.


As far as I know, GitHub Actions does not support that.

However, you can use environment variables for that.

For example, this script splits your command in 3 lines of code and executes it as one line.

steps:
  - name: Install Prerequisites
    run: |
      sudo apt-get update
      bash -c "$line1 $line2 $line3"
    env:
    - line1='sudo apt-get install -y --no-install-recommends '
    - line2='a very very long list'
    - line3='of prerequisites'

It creates the environment variables line1, line2 and line3 and concats and executes them in a bash session.

Solution 5

The above answers all had pieces, but this is what worked for me in a github composite action. It should work in a regular workflow too.

As @lorenzo-bettini said, if you want everything to be on one line, use what @Josue Alexander Ibarra called a Folded Block Scalar.

run: >
  xvfb-run
  ./mvnw -f my/pom.xml
  clean verify
  -DskipTests

newlines will be replaced with spaces so the above is equivalent to

run: xvfb-run ./mvnw -f my/pom.xml clean verify -DskipTests

If you want new lines to be preserved, use what @Josue Alexander Ibarra called a Literal Block Scalar.

run: |
  FILE=./package.json
  if test -f "$FILE"
  then
    echo "$FILE exists."
  else
    echo "File does not exist"
  fi

When you do a multi-line run, though, you have to make sure you indent correctly, otherwise step will think that shell: bash is part of the run: | string.

WRONG:

  steps:
    - run: |
      FILE=./package.json
      if test -f "$FILE"
      then
        echo "$FILE exists."
      else
        echo "File does not exist"
      fi
      shell: run

RIGHT:

  steps:
    - run: |
        FILE=./package.json
        if test -f "$FILE"
        then
          echo "$FILE exists."
        else
          echo "File does not exist"
        fi
      shell: run
Share:
31,862

Related videos on Youtube

Bojian Zheng
Author by

Bojian Zheng

Updated on July 08, 2022

Comments

  • Bojian Zheng
    Bojian Zheng 6 months

    I have a Github action command that is really long:

    name: build
    on: [push]
    jobs:
        build:
            runs-on: ubuntu-18.04
            steps:
                - uses: actions/[email protected]
                - name: Install Prerequisites
                  run: |
                    sudo apt-get update
                    sudo apt-get install -y --no-install-recommends "a very very long list of prerequisites"
    

    May I know whether it is possible to split the long command into multiple lines for better readability? I have tried the separator '\' but it does not work. Thanks in advance.

  • tom
    tom over 2 years
    This is the correct answer and would be a better accepted answer. The backslashes work the same as a multiline command in bash. (I'd recommend a hanging indent for readability though.)
  • dan1st
    dan1st over 2 years
    Does anyone know since when this is possible? (I think it was not possible when I wrote my answer but I fully agree with that answer being accepted, now)
  • Bojian Zheng
    Bojian Zheng over 2 years
    @dan1st I also do not think this is possible by the time I asked this, but it seems that Github people have added the support for backslash.
  • mcserep
    mcserep almost 2 years
    I don't know how did it work previously for anyone, but adding a backslash does not work right now with GitHub Actions. This shouldn't be the accepted answer.
  • sschuberth
    sschuberth almost 2 years
    Also see yaml-multiline.info to play around with the different scalar / chomping styles.
  • IvanD
    IvanD almost 2 years
    I confirm: this does not work on GitHub Actions as of now. You need to use ">" instead of "I" (see other answers)
  • Johnny Oshika
    Johnny Oshika over 1 year
    This works, thank you! Important note: per yml spec, white space is important here, so any extra tabs before the lines will cause problems.
  • ruohola
    ruohola over 1 year
    @JohnnyOshika Thank you for that comment! It cleared a long standing misunderstanding for me.
  • Waldir Leoncio
    Waldir Leoncio over 1 year
    Just a quick note about this being for the default shell. For example, my YML file had some bits running R code with shell: Rscript {0}, and line breaking in those cases don't need any special characters (just like in R).
  • silkfire
    silkfire about 1 year
    What does the hyphen in >- do?
  • Cocoatype
    Cocoatype about 1 year
    @silkfire According to the linked website, it appears to strip newlines from the end of the block, so that there's not an extra trailing \n at the end.
  • Cocoatype
    Cocoatype about 1 year
    That said, this is not supported by GitHub Actions: github.com/actions/runner/issues/418

Related