Search code examples
node.jsgitlabgitlab-cigitlab-ci-runner

How to pass global variable value to next stage in GitLab CI/CD


Based on GitLab documentation You can use the variables keyword to pass CI/CD variables to a downstream pipeline. I have a global variable DATABASE_URL The init stage retrieves connection string from the AWS Secret manager and sets it to DATABASE_URL
Then in the deploy stage I want to use that variable to deploy database. However in the deploy stage variable's value is empty.

variables:
  DATABASE_URL: ""
  
default:  
  tags:
    - myrunner
stages:
  - init 
  - deploy

init-job:
  image: docker.xxxx/awscli
  stage: init  
  script:     
    - SECRET_VALUE="$(aws secretsmanager get-secret-value --secret-id my_secret --region us-west-2 --output text --query SecretString)"
    - DATABASE_URL="$(jq -r .DATABASE_URL <<< $SECRET_VALUE)"      
    - echo "$DATABASE_URL" 


deploy-dev-database:      
  image: node:14
  stage: deploy 
  environment: 
    name: development
  script:    
    - echo "$DATABASE_URL"
    - npm install
    - npx sequelize-cli db:migrate    
  rules: 
    - if: $CI_COMMIT_REF_NAME == "dev"

Init Job. echos the DATABASE_URL

enter image description here

However DATABASE_URL is empty in deploy stage

enter image description here

Questions
1> How do I pass the global variable across the stages.
2> NodeJS database deployment process will be using this variable as process.env.DATABASE_URL will it be available to nodejs environment?


Solution

  • Variables are set by precedence, and when you print a variable inside of a job, it will look for the variable inside itself (the same job), and then start moving up to what's defined in the CI YAML file (variables: section), then the project, group, and instance. The job will never look at other jobs.

    If you want to pass a variable from one job to another, you would want to make sure you don't set the variable at all and instead pass the variable from one job to another following the documentation on passing environment variables to another job.

    Basically,

    1. Make sure to remove DATABASE_URL: "" from the variables section.
    2. Make the last line of your init-job script - echo "$DATABASE_URL" >> init.env. You can call your .env file whatever you want of course.
    3. Add an artifacts: section to your init-job.
    4. Add a dependencies: or needs: section to your deploy-dev-database job to pull the variable.

    You should end up with something like this:

    stages:
      - init 
      - deploy
    
    init-job:
      image: docker.xxxx/awscli
      stage: init  
      script:     
        - SECRET_VALUE="$(aws secretsmanager get-secret-value --secret-id my_secret --region us-west-2 --output text --query SecretString)"
        - DATABASE_URL="$(jq -r .DATABASE_URL <<< $SECRET_VALUE)"      
        - echo "$DATABASE_URL" >> init.env
      artifacts:
        reports:
          dotenv: init.env
    
    deploy-dev-database:      
      image: node:14
      stage: deploy 
      dependencies:
        - init-job
      environment: 
        name: development
      script:    
        - echo "$DATABASE_URL"
        - npm install
        - npx sequelize-cli db:migrate    
      rules: 
        - if: $CI_COMMIT_REF_NAME == "dev"