36
variables:
  CUSTOM_NODE_VERSION: '$${cat .nvmrc}'

I'd like for the variable CUSTOM_NODE_VERSION to be populated via the contents of the .nvmrc file (which is located in the projects root directory). How does one do this in the gitlab-ci.yml file?

The example above isn't working. I've also tried the following:

  • CUSTOM_NODE_VERSION: $(cat .nvmrc) -> (cat .nvmrc)
  • CUSTOM_NODE_VERSION: "$(cat .nvmrc)" -> (cat .nvmrc)
  • CUSTOM_NODE_VERSION: '$(cat .nvmrc)' -> (cat .nvmrc)
  • CUSTOM_NODE_VERSION: ${cat .nvmrc} -> (empty string)
  • CUSTOM_NODE_VERSION: '${cat .nvmrc}' -> (empty string)
  • CUSTOM_NODE_VERSION: "${cat .nvmrc}" -> (empty string)

It works if I put it in the before_script like the following:

before_script:
  - CUSTOM_NODE_VERSION=$(cat .nvmrc)

But it isn't accessible to the following part of the gitlab-ci.yml file:

lint:
  stage: Test
  image: node:$CUSTOM_NODE_VERSION
basickarl
  • 37,187
  • 64
  • 214
  • 335
  • 2
    Why can't you try normal command substitution syntax of `$(..)`. Note that `${..}` is for expanding variables, in your case though you needed to run commands. Can you do `CUSTOM_NODE_VERSION: $(cat .nvmrc)` – Inian Feb 28 '18 at 10:04
  • 3
    @Inian Yo! I did try this, however it results in the following: `(cat .nvmrc)` – basickarl Feb 28 '18 at 10:07
  • 1
    https://gitlab.com/gitlab-org/gitlab/issues/34202 please upvote and leave a comment to pull more attention – igagis Nov 04 '19 at 15:43

3 Answers3

8

I also wanted to use a version string in a .gitlab-ci.yml file but for appending it to a Docker image name. I did it like this:

build:
  stage: build_images
  script:
    - API_VERSION=v$(grep -E -o "(version = )(.*)" pyproject.toml | cut -d\" -f2)
    - echo $API_VERSION
    # Build and push new images for staging.
    - docker pull $API_STAGING:latest
    - docker build --cache-from $API_STAGING:latest >-
        -t $API_STAGING:latest >-
        -t $API_STAGING:$CI_COMMIT_SHORT_SHA >-
        -t $API_STAGING:$API_VERSION >-
        -f dockerfiles/Dockerfile.staging .
    - docker push $API_STAGING
  tags:
    - build

The key line here is API_VERSION=v$(grep -E -o "(version = )(.*)" pyproject.toml | cut -d\" -f2).

Explanation: the string I'm trying to read in pyproject.toml is something like version = "0.17.1", and the result I wanted was v0.17.1

  • v is just a string I want to prepend to my version number
  • -E (--extended-regexp) invokes grep as egrep; allows use of special regexp characters
  • -o (--only-matching) doesn't make a difference in my use-case, but might be helpful in other cases (I'm not sure)
  • (version = ) and (.*): the two capture groups; the latter one captures anything after the space after the equal sign
  • Running just $ grep -E -o "(version = )(.*)" pyproject.toml will result in version = "0.1.0", so I'm not using the capture groups; instead, I'm using cut
  • cut "cut[s] out selected portions of each line of a file"
  • -d\" sets the delimiter to a double-quote instead of the default (tab)
  • -f2 specifies the fields to return; a value of 1 would return everything before the first quote, i.e., version = , so 2 returns everything before the second quote and after the first, and 3 returns nothing in this example since there is no third double-quote-separated field
  • echo $API_VERSION just to see that it's working
acetone
  • 156
  • 1
  • 3
  • 8
  • if your using poetry, you just need `poetry version -s` instead of the grep/cut. – ruckc Jan 26 '21 at 19:20
  • Great, thanks for the tip! In the example above, I'm not sure if I was already using Poetry when I first used the grep/cut, but it's clear I didn't know about that command when I started using it. It's not clear to me that the Docker container would have access to the system Poetry install, though. – acetone Jan 26 '21 at 19:44
  • A more direct way is to use awk matching, and print the second field `awk -F\" '/version/ {print $2}' pyproject.toml` – Scott Carlson Mar 04 '22 at 13:47
  • what if grep doesn't return any matching string, then cut command will crash – Rohit Oct 26 '22 at 23:38
7

There are some parts of .gitlab-ci.yml where variables are usable and some parts where they are not.

The .yml file is parsed in Gitlab itself and then the commands are executed by the runner. So setting a variable that is used in the job config is not possible at this point. You could use a pre-defined Secret Variable although that doesnot seem to fix your need.

There are issues tracking the documentation of what you can and cannot do:

Stefan van Gastel
  • 4,330
  • 23
  • 25
6

You might want to try:

before_script:
  - export CUSTOM_NODE_VERSION=$(cat .nvmrc)

In your script to make the variable available to subsequent shells.

NIGHTSCROLLER
  • 89
  • 1
  • 5