Pass Variables From Top .gitlab-ci.yml file to lower levels

Infrastructure Versions:

  • Gitlab (on-prem): “14.3.2”
  • Gitlab Runner: "14.3.2 "

Description:
Currently have a setup as below, and need to apply two variables at the top level, to propagate down for versioning and publishing purposes. The versions get parsed from a proget repo, and then modified in relation to what is needing to happen at the Powershell module repository. There are three outcomes to this process, which update a Module.nuspec file’s tag. As we build alot of modules/code, and looking to utilize Gitlab CI, need a way to keep versioning in the developers hands, but also force incremental updates as they push to this repo… dont want them to have to think about what their patch level is, only major/minor.

  1. Package doesnt exist, and create as 0.0.1
  2. Package exists, but major, and minor versions are the same, so only increment.
  3. Package exists, but major, or minor versions are changing, so set patch to 1 (should be 0, but haven’t got that far yet…)

Variables:
- MAJOR_PACKAGE_VERSION: “0”
- MINOR_PACKAGE_VERSION: “0”

Files:
/powershell/Module-Name/.gitlab-ci.yml

# .gitlab-ci.yml
variables:
  MAJOR_PACKAGE_VERSION: "0"
  MINOR_PACKAGE_VERSION: "0"
include:
  - project: "devops/continuous-integration/powershell"
    ref: master
    file: 'gitlab-pipeline.yml'

/devops/continuous-itegration/powershell/.gitlab-ci.yml

image: docker:latest
stages:
  - test
  - pack
variables:
  DOCKER_DRIVER: overlay2
before_script:
  # Add required packages
  - apk add git --quiet --no-progress --no-cache
  # Set default git branch
  - git config --global init.defaultBranch master
  # Get continuous integration shared library
  - git clone -b master https://${GITLAB_CI_USER}:${GITLAB_CI_ACCESS_TOKEN}@${GITLAB_SERVER_URI}/devops/continuous-integration/powershell.git ${CI_SHARED_DIRECTORY}
  # Set permissions for continuous integration shared library
  - chmod -R +x ${CI_SHARED_DIRECTORY}/scripts/
  - cd ${CI_PROJECT_DIR}
  - echo "${CI_PROJECT_NAME}.${CI_COMMIT_BRANCH}.${CI_COMMIT_SHORT_SHA}.${CI_JOB_ID}.$(date "+%Y%m%d")"

version:powershell:
  stage: test
  image: ${DOCKER_USERNAME}/alpine-powershell:latest
  script:
    - ${CI_SHARED_DIRECTORY}/scripts/version.sh
  artifacts:
    reports:
      dotenv: .package_version.env
    expire_in: 30 seconds
  allow_failure: false

/devops/continuous-itegration/powershell/scripts/version.sh

#!/bin/sh

echo "+ Obtaining last package version from [$PROGET_SERVER_URI] at this uri [http://$PROGET_SERVER_URI/nuget/private-nuget/Packages()?\$format=json&\$filter=Id eq '$CI_PROJECT_NAME']"
PREVIOUS_PACKAGE_VERSION=$(pwsh -Command "Invoke-RestMethod -Uri \"http://$PROGET_SERVER_URI/nuget/private-nuget/Packages()?\$format=json&\$filter=Id eq '$CI_PROJECT_NAME'\" -ContentType 'application/json' | Select-Object -Expand properties | Select-Object -Expand version | Select-object -Last 1")
PREVIOUS_MAJOR_PACKAGE_VERSION=$(echo "$PREVIOUS_PACKAGE_VERSION" | cut -d "." -f1)
PREVIOUS_MINOR_PACKAGE_VERSION=$(echo "$PREVIOUS_PACKAGE_VERSION" | cut -d "." -f2)
PREVIOUS_PATCH_PACKAGE_VERSION=$(echo "$PREVIOUS_PACKAGE_VERSION" | cut -d "." -f3)

# Determine if $MAJOR_VERSION is undefined
if [ -z "$MAJOR_PACKAGE_VERSION" ]; then
  echo "+ [MAJOR_PACKAGE_VERSION] variable undefined setting to [0]"
  MAJOR_PACKAGE_VERSION="0"
fi

# Determine if $MINOR_VERSION is undefined
if [ -z "$MINOR_PACKAGE_VERSION" ]; then
  echo "+ [MINOR_PACKAGE_VERSION] variable undefined setting to [0]"
  MINOR_PACKAGE_VERSION="0"
fi

echo "Variables:"
echo "======================================================"
echo "DOCKER_USERNAME           = $DOCKER_USERNAME"
echo "CI_PROJECT_NAME           = $CI_PROJECT_NAME"
echo "CI_SHARED_DIRECTORY       = $CI_SHARED_DIRECTORY"
echo "PROGET_SERVER_URI         = $PROGET_SERVER_URI"
echo "PROGET_TOKEN              = $PROGET_TOKEN"
echo "VAULT_SERVER_URI          = $VAULT_SERVER_URI"
echo "VAULT_TOKEN               = $VAULT_TOKEN"
echo "======================================================"

if [ -z "$PREVIOUS_PACKAGE_VERSION" ]; then
    echo "+ PREVIOUS_PACKAGE_VERSION variable undefined setting [NEW_MAJOR_PACKAGE_VERSION] to [0] and setting [NEW_MINOR_PACKAGE_VERSION] to [0] and setting [NEW_PATCH_PACKAGE_VERSION] to [1]"
    NEW_MAJOR_PACKAGE_VERSION="0"
    NEW_MINOR_PACKAGE_VERSION="0"
    NEW_PATCH_PACKAGE_VERSION="1"
else
    if [ "$MAJOR_PACKAGE_VERSION" != "$PREVIOUS_MAJOR_PACKAGE_VERSION" ]; then
        NEW_MAJOR_PACKAGE_VERSION=$(echo "$MAJOR_PACKAGE_VERSION")
    else
        NEW_MAJOR_PACKAGE_VERSION=$(echo "$PREVIOUS_MAJOR_PACKAGE_VERSION")
    fi

    if [ "$MINOR_PACKAGE_VERSION" != "$PREVIOUS_MINOR_PACKAGE_VERSION" ]; then
        NEW_MINOR_PACKAGE_VERSION=$(echo "$MINOR_PACKAGE_VERSION")
    else
        NEW_MINOR_PACKAGE_VERSION=$(echo "$PREVIOUS_MINOR_PACKAGE_VERSION")
    fi

    if [ "$NEW_MAJOR_PACKAGE_VERSION" = "$PREVIOUS_MAJOR_PACKAGE_VERSION" ] && [ "$NEW_MINOR_PACKAGE_VERSION" = "$PREVIOUS_MINOR_PACKAGE_VERSION" ]; then
        INCREMENT_PATCH_PACKAGE_VERSION=true
    fi
fi

echo "INCREMENT_PATCH_PACKAGE_VERSION = $INCREMENT_PATCH_PACKAGE_VERSION"
echo "MAJOR_PACKAGE_VERSION           = $MAJOR_PACKAGE_VERSION"
echo "MINOR_PACKAGE_VERSION           = $MINOR_PACKAGE_VERSION"
echo "NEW_MAJOR_PACKAGE_VERSION       = $NEW_MAJOR_PACKAGE_VERSION"
echo "NEW_MINOR_PACKAGE_VERSION       = $NEW_MINOR_PACKAGE_VERSION"
echo "PREVIOUS_MAJOR_PACKAGE_VERSION  = $PREVIOUS_MAJOR_PACKAGE_VERSION"
echo "PREVIOUS_MINOR_PACKAGE_VERSION  = $PREVIOUS_MINOR_PACKAGE_VERSION"
echo "PREVIOUS_PATCH_PACKAGE_VERSION  = $PREVIOUS_PATCH_PACKAGE_VERSION"

if [ "$INCREMENT_PATCH_PACKAGE_VERSION" = true ]; then
    NEW_PATCH_PACKAGE_VERSION="$(expr $(echo "$PREVIOUS_PATCH_PACKAGE_VERSION") + 1)" 
fi

NEW_PACKAGE_VERSION="$NEW_MAJOR_PACKAGE_VERSION.$NEW_MINOR_PACKAGE_VERSION.$NEW_PATCH_PACKAGE_VERSION"

echo "+ Exporting NEW_PACKAGE_VERSION variable [$NEW_PACKAGE_VERSION] to [.package_version.env]"
echo "NEW_PACKAGE_VERSION=$NEW_PACKAGE_VERSION" >> ".package_version.env"

Gitlab-CI Output:

Running with gitlab-runner 14.3.2 (e0218c92)
  on gitlab-runner AXUcv82y
Preparing the "kubernetes" executor 00:00
Using Kubernetes namespace: gitlab-ce
Using Kubernetes executor with image condoamanti/alpine-powershell:latest ...
Using attach strategy to execute scripts...
Preparing environment 00:07
Waiting for pod gitlab-ce/runner-axucv82y-project-55-concurrent-17xhcc to be running, status is Pending
	ContainersNotInitialized: "containers with incomplete status: [init-permissions]"
	ContainersNotReady: "containers with unready status: [build helper]"
	ContainersNotReady: "containers with unready status: [build helper]"
Waiting for pod gitlab-ce/runner-axucv82y-project-55-concurrent-17xhcc to be running, status is Pending
	ContainersNotReady: "containers with unready status: [build helper]"
	ContainersNotReady: "containers with unready status: [build helper]"
Running on runner-axucv82y-project-55-concurrent-17xhcc via gitlab-runner-5465555d88-2944l...
Getting source from Git repository 00:00
Fetching changes with git depth set to 50...
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
Initialized empty Git repository in /builds/AXUcv82y/1/devops/powershell/GoCD/.git/
Created fresh repository.
Checking out 5e4dce02 as master...
Skipping Git submodules setup
Executing "step_script" stage of the job script 00:06
$ apk add git --quiet --no-progress --no-cache
$ git config --global init.defaultBranch master
$ git clone -b master https://${GITLAB_CI_USER}:${GITLAB_CI_ACCESS_TOKEN}@${GITLAB_SERVER_URI}/devops/continuous-integration/powershell.git ${CI_SHARED_DIRECTORY}
Cloning into '/tmp/shared_directory'...
$ chmod -R +x ${CI_SHARED_DIRECTORY}/scripts/
$ cd ${CI_PROJECT_DIR}
$ echo "${CI_PROJECT_NAME}.${CI_COMMIT_BRANCH}.${CI_COMMIT_SHORT_SHA}.${CI_JOB_ID}.$(date "+%Y%m%d")"
GoCD.master.5e4dce02.1895.20211006
$ ${CI_SHARED_DIRECTORY}/scripts/version.sh
+ Obtaining last package version from [proget.domain.local] at this uri [http://proget.domain.local/nuget/private-nuget/Packages()?$format=json&$filter=Id eq 'GoCD']
+ [MAJOR_PACKAGE_VERSION] variable undefined setting to [0]
+ [MINOR_PACKAGE_VERSION] variable undefined setting to [0]
Variables:
======================================================
DOCKER_USERNAME           = condoamanti
CI_PROJECT_NAME           = GoCD
CI_SHARED_DIRECTORY       = /tmp/shared_directory
PROGET_SERVER_URI         = proget.domain.local
PROGET_TOKEN              = [MASKED]
VAULT_SERVER_URI          = vault.domain.local
VAULT_TOKEN               = [MASKED]
======================================================
INCREMENT_PATCH_PACKAGE_VERSION = true
MAJOR_PACKAGE_VERSION           = 0
MINOR_PACKAGE_VERSION           = 0
NEW_MAJOR_PACKAGE_VERSION       = 0
NEW_MINOR_PACKAGE_VERSION       = 0
PREVIOUS_MAJOR_PACKAGE_VERSION  = 0
PREVIOUS_MINOR_PACKAGE_VERSION  = 0
PREVIOUS_PATCH_PACKAGE_VERSION  = 2
+ Exporting NEW_PACKAGE_VERSION variable [0.0.3] to [.package_version.env]
Uploading artifacts for successful job 00:01
Uploading artifacts...
.package_version.env: found 1 matching files and directories 
Uploading artifacts as "dotenv" to coordinator... ok  id=1895 responseStatus=201 Created token=x_dth4Av
Cleaning up project directory and file based variables 00:00
Job succeeded

REFENCE THESE LINES, in relation to what is not being passed as expected from top level…

Also if anyone has a fix for the above :stuck_out_tongue: would be more than happy, yet again been busy and haven’t fixed as of yet. Assuming gitlab runner change someplace.

Found the fix to this, or maybe a work around… I’m not 100% sure… Please see below configuration for resolution of configuration. Used referenced configuration from (Keyword reference for the `.gitlab-ci.yml` file | GitLab) and (Variable can be used on `include.ref` in `.gitlab-ci.yml` (#219065) · Issues · GitLab.org / GitLab · GitLab)

/powershell/Module-Name/.gitlab-ci.yml

# .gitlab-ci.yml
stages:
  - build

build:powershell: 
  stage: build
  variables:
    MAJOR_PACKAGE_VERSION: "2"
    MINOR_PACKAGE_VERSION: "2"
  trigger:
    include:
      - project: "devops/continuous-integration/powershell"
        ref: "master"
        file: "gitlab-pipeline.yml"
    strategy: depend

/devops/continuous-itegration/powershell/.gitlab-ci.yml

# Refenence Links:
#   Artifact/Variable Passing
#   - https://stackoverflow.com/questions/44774520/exporting-environment-variables-from-one-stage-to-the-next-in-gitlab-ci
#   - https://docs.gitlab.com/ee/ci/yaml/index.html#artifactsexpire_in
#   - https://docs.gitlab.com/ee/ci/variables/index.html#pass-an-environment-variable-to-another-job

image: docker:latest
stages:
  - test
  - pack
variables:
  DOCKER_DRIVER: overlay2
before_script:
  # Add required packages
  - apk add git --quiet --no-progress --no-cache
  # Set default git branch
  - git config --global init.defaultBranch master
  # Get continuous integration shared library
  - git clone -b master https://${GITLAB_CI_USER}:${GITLAB_CI_ACCESS_TOKEN}@${GITLAB_SERVER_URI}/devops/continuous-integration/powershell.git ${CI_SHARED_DIRECTORY}
  # Set permissions for continuous integration shared library
  - chmod -R +x ${CI_SHARED_DIRECTORY}/scripts/
  - cd ${CI_PROJECT_DIR}
  - echo "${CI_PROJECT_NAME}.${CI_COMMIT_BRANCH}.${CI_COMMIT_SHORT_SHA}.${CI_JOB_ID}.$(date "+%Y%m%d")"

test:powershell:
  stage: test
  image: ${DOCKER_USERNAME}/alpine-powershell:latest
  script:
    - ${CI_SHARED_DIRECTORY}/scripts/test.sh
  allow_failure: false

version:powershell:
  stage: test
  image: ${DOCKER_USERNAME}/alpine-powershell:latest
  script:
    - ${CI_SHARED_DIRECTORY}/scripts/version.sh
  artifacts:
    reports:
      dotenv: .package_version.env
    expire_in: 30 seconds
  allow_failure: false

publish:powershell:
  stage: pack
  image: ${DOCKER_USERNAME}/alpine-dotnet:latest
  script:
    - ${CI_SHARED_DIRECTORY}/scripts/publish.sh
  needs:
    - job: test:powershell
    - job: version:powershell
      artifacts: true
  allow_failure: false
  only:
  - master

Gilab-CI Output:

Running with gitlab-runner 14.3.2 (e0218c92)
  on gitlab-runner AXUcv82y
Preparing the "kubernetes" executor 00:00
Using Kubernetes namespace: gitlab-ce
Using Kubernetes executor with image condoamanti/alpine-powershell:latest ...
Using attach strategy to execute scripts...
Preparing environment 00:06
Waiting for pod gitlab-ce/runner-axucv82y-project-55-concurrent-1f6vnn to be running, status is Pending
	ContainersNotInitialized: "containers with incomplete status: [init-permissions]"
	ContainersNotReady: "containers with unready status: [build helper]"
	ContainersNotReady: "containers with unready status: [build helper]"
Waiting for pod gitlab-ce/runner-axucv82y-project-55-concurrent-1f6vnn to be running, status is Pending
	ContainersNotReady: "containers with unready status: [build helper]"
	ContainersNotReady: "containers with unready status: [build helper]"
Running on runner-axucv82y-project-55-concurrent-1f6vnn via gitlab-runner-5465555d88-2944l...
Getting source from Git repository 00:00
Fetching changes with git depth set to 50...
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
Initialized empty Git repository in /builds/AXUcv82y/1/devops/powershell/GoCD/.git/
Created fresh repository.
Checking out afc85ca4 as master...
Skipping Git submodules setup
Executing "step_script" stage of the job script 00:06
$ apk add git --quiet --no-progress --no-cache
$ git config --global init.defaultBranch master
$ git clone -b master https://${GITLAB_CI_USER}:${GITLAB_CI_ACCESS_TOKEN}@${GITLAB_SERVER_URI}/devops/continuous-integration/powershell.git ${CI_SHARED_DIRECTORY}
Cloning into '/tmp/shared_directory'...
$ chmod -R +x ${CI_SHARED_DIRECTORY}/scripts/
$ cd ${CI_PROJECT_DIR}
$ echo "${CI_PROJECT_NAME}.${CI_COMMIT_BRANCH}.${CI_COMMIT_SHORT_SHA}.${CI_JOB_ID}.$(date "+%Y%m%d")"
GoCD.master.afc85ca4.1928.20211007
$ ${CI_SHARED_DIRECTORY}/scripts/version.sh
+ Obtaining last package version from [proget.domain.local] at this uri [http://proget.domain.local/nuget/private-nuget/Packages()?$format=json&$filter=Id eq 'GoCD']
Variables:
======================================================
DOCKER_USERNAME           = condoamanti
CI_PROJECT_NAME           = GoCD
CI_SHARED_DIRECTORY       = /tmp/shared_directory
PROGET_SERVER_URI         = proget.domain.local
PROGET_TOKEN              = [MASKED]
VAULT_SERVER_URI          = vault.domain.local
VAULT_TOKEN               = [MASKED]
======================================================
INCREMENT_PATCH_PACKAGE_VERSION = true
MAJOR_PACKAGE_VERSION           = 2
MINOR_PACKAGE_VERSION           = 2
NEW_MAJOR_PACKAGE_VERSION       = 2
NEW_MINOR_PACKAGE_VERSION       = 2
PREVIOUS_MAJOR_PACKAGE_VERSION  = 2
PREVIOUS_MINOR_PACKAGE_VERSION  = 2
PREVIOUS_PATCH_PACKAGE_VERSION  = 1
+ Exporting NEW_PACKAGE_VERSION variable [2.2.2] to [.package_version.env]
Uploading artifacts for successful job 00:01
Uploading artifacts...
.package_version.env: found 1 matching files and directories 
Uploading artifacts as "dotenv" to coordinator... ok  id=1928 responseStatus=201 Created token=VEgyZ8A_
Cleaning up project directory and file based variables 00:00
Job succeeded

Gitlab PIpeline Overview: