47

Is there a way to export environment variables from one stage to the next in GitLab CI? I'm looking for something similar to the job artifacts feature, only for environment variables instead of files.

Let's say I'm configuring the build in a configure stage and want to store the results as (secret, protected) environment variables for the next stages to use. I could safe the configuration in files and store them as job artifacts but I'm concerned about secrets being made available in files than can be downloaded by everyone.

Bastian Venthur
  • 12,515
  • 5
  • 44
  • 78

4 Answers4

54

Since Gitlab 13 you can inherit environment variables like this:

build:
  stage: build
  script:
    - echo "BUILD_VERSION=hello" >> build.env
  artifacts:
    reports:
      dotenv: build.env

deploy:
  stage: deploy
  script:
    - echo $BUILD_VERSION # => hello
  dependencies:
    - build

Note: for GitLab < 13.1 you should enable this first in Gitlab Rails console:

Feature.enable(:ci_dependency_variables)
jbaptperez
  • 656
  • 6
  • 20
hd.deman
  • 1,268
  • 12
  • 17
  • 7
    GitLab 13.1 removed the feature flag (cf [this merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34495)) – cbenz Jun 26 '20 at 11:04
  • 1
    I have two separates services which I need to build. In first step I use reports dotenv with some exported environment variables and I consume it in the next step. The issue is that I have two services built at the same time and it looks like it doesn't matter if you specify dependencies, all these env vars are shared in next steps. So what happens is that second service variables are overriding first service variables. Any solution for that? – MistyK Sep 09 '21 at 10:47
  • yeah the `dependencies:` is not required. I was able to handle that package.json and its not required – Adiii Feb 17 '22 at 07:43
  • @MistyK Hello, did you figure it out? – Pedro A Jul 12 '22 at 15:24
17

Although not exactly what you wanted since it uses artifacts:reports:dotenv artifacts, GitLab recommends doing the below in their guide: 'Pass an environment variable to another job':

build:
  stage: build
  script:
    - echo "BUILD_VERSION=hello" >> build.env
  artifacts:
    reports:
      dotenv: build.env

deploy:
  stage: deploy
  script:
    - echo "$BUILD_VERSION"  # Output is: 'hello'
  needs:
    - job: build
      artifacts: true

I believe using the needs keyword is preferable over the dependencies keyword (as used in hd-deman's top answer) since:

When a job uses needs, it no longer downloads all artifacts from previous stages by default, because jobs with needs can start before earlier stages complete. With needs you can only download artifacts from the jobs listed in the needs: configuration.

Furthermore, you could minimise the risk by setting the build's artifacts:expire_in time to be very small.

JakeParis
  • 11,056
  • 3
  • 42
  • 65
followingell
  • 413
  • 6
  • 12
8

No this feature is not here yet, but there is already an issue for this topic.

My suggestion would be that you are saving the variables in a files and cache them, as these will be not downloadable and will be removed on finish of the job. If you want to be 100% sure you can delete it manually. See the clean_up stage.

e.g.

cache:
 paths:
  - save_file

stages: 
 - job_name_1
 - job_name_2
 - clean_up

job_name_1:
 script:
  - (your_task) >> save_file

job_name_2:
 script:
  - cat save_file | do_something_with_content

clean_up:
 script:
  - rm save_file
 when: always 
Cometchaser
  • 117
  • 2
  • 12
secustor
  • 3,001
  • 2
  • 14
  • 20
  • 1
    The problem with cache is, that there is [no guarantee](https://docs.gitlab.com/ee/ci/yaml/#cache) the cached data will be in the next stage. Would be nice if there was a way to re-run the command that generated the contents of the cache when the cache is not available -- similar to a dependency in a Makefile. – Bastian Venthur Jun 28 '17 at 06:56
  • true, I have overread this little important part, but you can still use my example with artifacts as it will delete the file before the artifacts are offered to the user. But a maybe better solution would be to use the `expire_in` command and set it to `0 sec`. This will prevent the download from the point on the build is finished and the actual file will be deleted within an hour. https://docs.gitlab.com/ee/ci/yaml/README.html#artifacts-expire_in – secustor Jun 28 '17 at 08:06
  • 1
    Don't use ccahe for this purpose. Just use artifacts, store the values in file then pass it to next job. Sure it is not a best practice solution, you are storing the maybe secrets in file.. This is still an issue in Gitlab, we are not able to share variables between stages/jobs. – Ferhat S. R. Mar 30 '20 at 09:22
2

You want to use Artefacts for this.

stages: 
 - job_name_1
 - job_name_2
 - clean_up

job_name_1:
 script:
  - (your_task) >> save_file
 artifacts:
  paths:
   - save_file
# Hint: You can set an expiration for them too.

job_name_2:
 needs:
  - job: job_name_1
    artifacts: true
 script:
  - cat save_file | do_something_with_content
WhyNotHugo
  • 9,423
  • 6
  • 62
  • 70