Github Action: Split Long Command into Multiple Lines
GithubYamlGithub ActionsGithub Problem Overview
I have a Github action command that is really long:
name: build
on: [push]
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v1
- 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.
Github Solutions
Solution 1 - Github
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 - Github
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 - Github
Going to share this in since it has not been mentioned.
You can use:
|
called aLiteral Block Scalar
which preserves new lines and trailing spaces>
called aFolded 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 - Github
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
Solution 5 - Github
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.