27

I have a line like this:

sed -i 's/"host: TND_HOST"/"host: process.env.TND_HOST"/g' services/management/tnd.js

and the option above causes linting error:

This GitLab CI configuration is invalid: (<unknown>): mapping values are not allowed in this context at line [...]

Other options that do not work are:

sed -i 's/host: TND_HOST/host: process.env.TND_HOST/g' services/management/tnd.js

sed -i "s/host: TND_HOST/host: process.env.TND_HOST/g" services/management/tnd.js

Any way to overcome the issue and keep it as a one-liner?

AbreQueVoy
  • 1,748
  • 8
  • 31
  • 52

2 Answers2

26

Since you are using both types of quotes it is probably easiest to put your command in a yaml template. That way you don't need to escape anything:

stages:
  - lint

.sed_template: &sed_template |
 sed -i 's/"host: TND_HOST"/"host: process.env.TND_HOST"/g' services/management/tnd.js

some_job:
  image: someImage:latest
  stage: lint
  except:
    - master
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - frontend/node_modules/
  script:
    - echo "firstLine"
    - *sed_template
    - echo "lastLine"

It's not quite a one liner anymore but I guess its the cleanest option as it keeps the command itself rather readable. Another option would be using folding style which shrinks it down a bit:

stages:
  - lint

some_job:
  image: someImage:latest
  stage: lint
  except:
    - master
  cache:
    key: ${CI_COMMIT_REF_SLUG}
    paths:
      - frontend/node_modules/
  script:
    - echo "firstLine"
    - >
        sed -i 's/"host: TND_HOST"/"host: process.env.TND_HOST"/g' services/management/tnd.js
    - echo "lastLine" 
Daniel
  • 20,420
  • 10
  • 92
  • 149
pat
  • 1,765
  • 8
  • 22
9

You do not have to formally escape colons. See the examples below.

One approach is to put your command's argument with colons wrapped in single quotes into a variable. You can use variables inside your argument string.

Then eval that "stringified' command with the variables like the following (the example is for curl to trigger external deployment, but should work for every command):

deploy_job:
  variables:
    DEPLOY_CURL_COMMAND: 'curl -X POST -H "Content-Type: application/json" -H "Authorization: Bearer $DO_APP_PLATFORM_API_TOKEN" https://api.digitalocean.com/v2/apps/$DO_APP_PLATFORM_STAGE_FRONT_APP_ID/deployments'
  script:
    - echo "Stage Deploy to DigitalOcean App Platform"
    - echo $DEPLOY_CURL_COMMAND
    - 'eval "$DEPLOY_CURL_COMMAND"'

There are also some other ways to avoid : (colon followed by space) issue:

  script:
    # 1. Note how the single quotes eliminate colon+space issue.
    - 'MESSAGE="Tests finished with status: ${CI_JOB_STATUS}"'
    # 2. Here pipe operator allows using colon+space on the next line.
    - |
      curl -X POST -H 'Content-type: application/json' --data "{\"text\":\"$MESSAGE\"}" "$SOME_URL"
    # 3. Here we refrain from using pipe operator and instead wrap the entire command in sigle quotes as in 1. 
    # Note that I replaced single with double quotes on HTTP header.
    - 'curl -X POST -H "Content-type: application/json" --data "{\"text\":\"$MESSAGE\"}" "$SOME_URL"'

Be very precise with all the quotes, dashes and spaces along the script. YAML is quite unforgiving. Check the syntax with GitLab pipeline editor and linter. Actually it is much quicker to develop your pipeline in the editor first.

If you use the project / repository level variables do not forget to uncheck protected checkbox (checked by default) when setting a variable and using it in unprotected branch (which is a branch default state).

Valentine Shi
  • 6,604
  • 4
  • 46
  • 46