Привет, на связи Олег Казаков из Spectr. Сегодня мы разберем тему параметризованных сборок в GitLab и чем они могут быть полезны.
Введение в параметризованные сборки
Понятие параметризованных сборок очень популярно в Jenkins — это функционал, который позволяет запускать сборки с пользовательскими параметрами. Это значительно расширяет возможности автоматизации и делает процессы более гибкими.
Одна из ключевых задач, для которой этот функционал может применяться, — тестирование функционала в разных окружениях. Можно запускать тесты на окружении (например, dev, staging, test), просто задавая нужные параметры.
Параметризованные сборки в GitLab
В GitLab подобный функционал тоже имеется, и сегодня я расскажу, как его можно использовать.
В документации GitLab этот функционал можно посмотреть тут: Prefill variables in manual pipelines. Здесь описывается, как можно задавать переменные, которые будут предварительно заполняться при запуске пайплайна вручную. То есть при создании пайплайна в интерфейсе данные переменные уже будут предзаполнены и их можно поменять перед запуском.
А еще чуть ниже описан механизм установки списка значений, из которых можно выбирать при создании пайплайна.
Тестовый пайплайн
Пробуем сделать так, как в документации, — добавить переменную с выбором. Добавляем .gitlab-ci.yml, переменную и тестовый первый джоб (т. к. без него не запустится пайплайн), получаем следующее:
stages:
- build
variables:
DEPLOY_ENVIRONMENT:
value: "test_1"
options:
- "test_1"
- "test_2"
- "test_3"
description: "The deployment target. Set to 'test_1' by default."
build:
stage: build
script:
- echo "test build"
- echo $DEPLOY_ENVIRONMENT
В данном примере считаем, что у нас есть три тестовых окружения, а в тестовом джобе просто выводим содержимое переменной. Далее пушим, видим, что у нас сразу запускается пайплайн, где устанавливается значение по умолчанию, т. е. “test_1”:
Теперь попробуем создать пайплайн вручную, для этого переходим в список пайплайнов, нажимаем на кнопку создания пайплайна:
В появившейся форме можно выбрать ветку (у нас пока только main) и можно указать значение нашей переменной, — для проверки поменяемна «test_2»:
Далее запускаем пайплайн, дожидаемся его выполнения:
И видим результат: значение переменной теперь «test_2»:
То есть, как видим, если запускать пайплайн вручную, можно влиять на значение переменных, — это, собственно, и есть параметризованный пайплайн. Если же пайплайн запускается автоматически по какому-то событию, то там всегда дефолтное значение.
Ограничение условий запуска пайплайна
Вернемся опять к Jenkins, параметризованные пайплайны там запускаются только вручную. Это объяснимо, так как в таких пайплайнах нужно заранее задавать параметры, что требует взаимодействия с пользователем, и автоматически запускать такие пайплайны нет особого смысла. Поэтому и нам надо сделать так, чтобы такие пайплайны запускались только вручную.
Для этого модифицируем наш джоб:
build:
stage: build
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_PIPELINE_SOURCE == "api"
- if: $CI_PIPELINE_SOURCE == "trigger"
- if: $CI_PIPELINE_SOURCE != "push"
when: never
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
script:
- echo "test build"
- echo $DEPLOY_ENVIRONMENT
Добавился блок rules, в котором указываем условия срабатывания. В переменной CI_PIPELINE_SOURCE находится информация о том, как запускается пайплайн. В этом случае мы запрещаем запускать данный джоб, если был пуш или если был создан мерж-реквест. В остальных случаях джоб будет выполняться (и в этих случаях можем указывать свои параметры).
Приближенный к реальности пример
Теперь модифицируем наш CI/CD, чтобы он стал больше походить на реальный:
stages:
- build
variables:
IMAGE_NAME: $CI_REGISTRY_IMAGE/$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA
DEPLOY_ENVIRONMENT:
value: "test_1"
options:
- "test_1"
- "test_2"
- "test_3"
description: "The deployment target. Set to 'test_1' by default."
.auth_in_registry: &auth_in_registry
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
.docker_build: &docker_build
- docker buildx create --use
- docker buildx build --push --platform linux/amd64 -f docker/Dockerfile -t ${IMAGE_NAME} .
- docker buildx stop
- docker buildx rm
build:
stage: build
environment:
name: ${DEPLOY_ENVIRONMENT}
before_script:
- *auth_in_registry
image: docker:24.0.5
services:
- docker:24.0.5-dind
rules:
- if: $CI_PIPELINE_SOURCE == "schedule"
- if: $CI_PIPELINE_SOURCE == "web"
- if: $CI_PIPELINE_SOURCE == "api"
- if: $CI_PIPELINE_SOURCE == "trigger"
- if: $CI_PIPELINE_SOURCE != "push"
when: never
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
script:
- *docker_build
Что добавилось:
Переменная IMAGE_NAME: используется для удобства сборки и тегирования Docker-образов на основе коммитов.
Анкор .auth_in_registry: для аутентификации в реестре GitLab.
Анкор .docker_build: для сборки Docker-образа из Dockerfile.
В рамках джоба build используем анкоры выше, а также «Docker-in-Docker», чтобы делать сборку.
Также можно увидеть такую конструкцию:
environment:
name: ${DEPLOY_ENVIRONMENT}
Что она нам дает?
Во-первых, у нас под каждое тестовое окружение создается окружение в GitLab:
Можно отслеживать историю:
Во-вторых, мы таким образом можем удобно управлять переменными окружения в самом GitLab (не prefilled-переменными, а переменными проекта/группы в GitLab), то есть можно задавать для каждого тестового окружения свои значения.
Заключение
Мы рассмотрели тему параметризованных сборок в GitLab и сделали пайплайн со стадией сборки образа. Далее по аналогии можно добавить стадии деплоя и тестирования, чтобы реализовать полный пайплайн тестирования функционала.