I’m trying to assign values to the list of variables, according of appropriate choice maded at the pipeline startup. So In my case:
I have a gitlab-ci.yml
file with following:
variables:
DOCKER_DRIVER: overlay
REGISTRY: registry.restream.ru:5000
CENTOS_TESTS_VERSION: 1.1.3
CENTOS_PYTHON_VERSION: 1.0.5
CENTOS_CPP_VERSION: 1.0.4
REDOS7_CPP_VERSION: 1.0.0
REDOS8_TESTS_VERSION: 1.0.0
REDOS8_CPP_VERSION: 1.0.0
REDOS8_PYTHON_VERSION: 1.0.0
OS_VERSION:
value: "RedOS-8"
options:
- "RedOS-8"
- "CentOS-7"
- "RedOS-7"
description: "The deployment target. Set to 'RedOS-8' by default."
COMPONENT_TYPE:
value: "Python"
options:
- "Python"
- "C++"
- "Tests"
description: "The deployment component type. Set to 'Python' by default."
default:
before_script:
- >
if [[ $OS_VERSION = "RedOS-8" ]] && [[ $COMPONENT_TYPE = "C++" ]]; then
variables:
DOCKERFILE = ./redos8/cpp.Dockerfile
IMAGE_NAME = redos8-cpp
IMAGE_VERSION = $REDOS8_CPP_VERSION
elif [[ $OS_VERSION = "RedOS-8" ]] && [[ $COMPONENT_TYPE = "Python" ]]; then
variables:
DOCKERFILE = ./redos8/python.Dockerfile
IMAGE_NAME: redos8-python
IMAGE_VERSION = REDOS8_PYTHON_VERSION
elif [[ $OS_VERSION = "RedOS-8" ]] && [[ $COMPONENT_TYPE = "Tests" ]]; then
variables:
DOCKERFILE: ./redos8/tests.Dockerfile
IMAGE_NAME: redos8-tests
IMAGE_VERSION = $REDOS8_TESTS_VERSION
elif [[ $OS_VERSION = "RedOS-7" ]]; then
variables:
DOCKERFILE = ./redos7/cpp.Dockerfile
IMAGE_NAME = redos7-cpp
IMAGE_VERSION = $REDOS7_CPP_VERSION
elif [[ $OS_VERSION = "CentOS-7" ]] && [[ $COMPONENT_TYPE = "Python" ]]; then
variables:
DOCKERFILE = ./redos7/python.Dockerfile
IMAGE_NAME = centos7-python
IMAGE_VERSION = $CENTOS_PYTHON_VERSION
else
variables:
DOCKERFILE = ./centos7/cpp.Dockerfile
fi
stages:
- lint
- build
.lint:
stage: lint
image: $REGISTRY/hadolint/hadolint:v2.12.0-alpine
rules:
- changes:
- $DOCKERFILE
- repo/*
- scripts/*
tags:
- dind
script:
- hadolint $DOCKERFILE
.build:
image: $REGISTRY/docker:latest
services:
- $REGISTRY/docker:dind
stage: build
variables:
FULL_IMAGE_NAME: $REGISTRY/rtpp-team/ci-cd/$IMAGE_NAME:$IMAGE_VERSION
rules:
- changes:
- $DOCKERFILE
- repo/*
- scripts/*
tags:
- dind
script:
- docker build --pull --tag $FULL_IMAGE_NAME --file $DOCKERFILE .
- docker push $FULL_IMAGE_NAME
lint_dockerfile:tests:
extends: .lint
variables:
DOCKERFILE: $DOCKERFILE
build_image:tests:
extends: .build
variables:
DOCKERFILE: $DOCKERFILE
IMAGE_NAME: $IMAGE_NAME
IMAGE_VERSION: $CENTOS_TESTS_VERSION
needs:
- job: lint_dockerfile:tests
lint_dockerfile:python:
extends: .lint
variables:
DOCKERFILE: $DOCKERFILE
build_image:python:
extends: .build
variables:
DOCKERFILE: $DOCKERFILE
IMAGE_NAME: $IMAGE_NAME
IMAGE_VERSION: $CENTOS_PYTHON_VERSION
needs:
- job: lint_dockerfile:python
lint_dockerfile:cpp:
extends: .lint
variables:
DOCKERFILE: $DOCKERFILE
build_image:cpp:
extends: .build
variables:
DOCKERFILE: $DOCKERFILE
IMAGE_NAME: $IMAGE_VERSION
IMAGE_VERSION: $CENTOS_CPP_VERSION
needs:
- job: lint_dockerfile:cpp
For example, I chose condition like "RedOS-8" + "C++".
In log output I get:
Getting source from Git repository
00:01
Fetching changes with git depth set to 20...
Reinitialized existing Git repository in /builds/dev_team/devops/ci-cd-docker-images/.git/
Checking out 61cad3e4 as detached HEAD (ref is devops/WINK-5057)
Skipping Git submodules setup
Executing "step_script" stage of the job script
00:01
Using docker image sha256:19b38dcec411d7f333601a68f55cb3e710fca099615a7eee0fa2e020adfc7292 for registry.team.ru:5000/hadolint/hadolint:v2.12.0-alpine with digest hadolint/hadolint@sha256:3c206a451cec6d486367e758645269fd7d696c5ccb6ff59d8b03b0e45268a199
$ if [[ $OS_VERSION = "RedOS-8" ]] && [[ $COMPONENT_TYPE = "C++" ]]; then # collapsed multi-line command
/bin/sh: eval: line 179: variables:: not found
I tried to change multi-line characters from >
to |
. Also, I tried to use one condition for test like:
default:
before_script:
- >
if [[ $OS_VERSION = "RedOS-8" ]] && [[ $COMPONENT_TYPE = "C++" ]]; then
variables:
DOCKERFILE = ./redos8/cpp.Dockerfile
IMAGE_NAME = redos8-cpp
IMAGE_VERSION = $REDOS8_CPP_VERSION
With no result. The log output gave me the same error with "# collapsed multi-line command" and $DOCKERFILE not found for the first pipeline step called "hadolint".
2
Answers
You could have a first job that run the conditional logic but writes the environment variables in a file, and then use the content of that file as env vars for next jobs thanks to
artifacts:reports:dotenv
.Generic example:
See:
Writing long scripts in the pipline reduces readability and invites errors. Use shellcheck.
variables:
is not a shell command, so you get/bin/sh: eval: line 179: variables:: not found
.DOCKERFILE = ./redos8/cpp.Dockerfile
is not shell assignment.Create a shell script in the repository:
Then source it from the pipeline.
I also like beeing explicit. The last
"$@"
can be used to run as a wrapper, which allows for easy local testing: