Deploy scripts not supporting multiline strings

I’m having troubles with using a deployment script that uses a multiline string. When the same script is run through a script stage, the commands work as expected.

Example config:

language: node_js
os:
  - linux
  - osx
  
script:
  - |
    echo building
    if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
      echo "****> linux <****";
    elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
      echo "----> osx <----";
    fi
deploy:
  provider: script
  on:
    all_branches: true
  script: |
    echo deploying
    if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
      echo "****> linux <****";
    elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
      echo "----> osx <----";
    fi

Result:

deployingnif [[ linux == linux ]]
sh: 1: thenn: not found
sh: 1: nelif: not found
sh: 1: thenn: not found
sh: 1: nfi: not found

Even though the JSON view of the job config shows the script having the same \n newline characters inside the script definition, the deploy stage is not interpreting them correctly.

Logs: https://travis-ci.org/github/stephenash/travis-ci-multiline-deploy/jobs/678422508#L232

I do see that https://docs.travis-ci.com/user/deployment/script/#passing-arguments-to-the-script says that “If you need to run multiple commands, write a executable wrapper script that runs them all.” I’m interpreting that to mean that I cannot do

deploy:
  script:
    - echo step 1
    - echo step 2

but that I should still be able to use a multiline string to act as one step

1 Like

Your script value contains \n, which is turning into a single n on the way to the deployment provider. (It is not immediately clear to me where it’s happening.) So the script is:

echo deployingnif [[ "$TRAVIS_OS_NAME" == "linux" ]]; thenn  echo "****> linux <****";nelif [[ "$TRAVIS_OS_NAME" == "osx" ]]; thenn  echo "----> osx <----";nfi

which produces the output you are seeing. You can string all of this together into one line:

echo deploying; if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then echo "****> linux <****"; elif [[ "$TRAVIS_OS_NAME" == "osx" ]]; then  echo "----> osx <----"; fi

Making the script fit on one line is one workaround, but a pretty messy one. It may look alright for this trivial case, but once it starts getting more complex with more (nested) conditional logic, that one line is very hard to maintain. Having the script moved into another file and using script: bash deploy.sh is another workaround that I found, but it makes more sense to me to have all of the logic in the .travis.yml file.

A less ugly workaround would be to write

deploy:
   <...>
   script: >
     <code>

And place semicolons in code at ends of commands where appropriate regardless of newlines.

This will replace newlines with spaces on YAML parsing but retain the readability.

I believe this is happening at https://github.com/travis-ci/travis-build/blob/3b417d42afb21cb9582c73e5ceb9aaf3a5fdfa25/lib/travis/build/addons/deploy/script.rb#L214 . The value is being converted with %p (i.e. inspect) rather than quoted for the shell.

This is a fix:

1 Like

The fix has caused S3 aws deploy access_key_id and was reverted.