В данной инструкции будут рассмотрены небольшие сценарии работы с Gitlab Pipelines. Мы приведем примеры использования наиболее востребованных опций при работе с CI/CD. По мере необходимости, база шаблонов будет пополняться.
Шаблоны
1. Минимальный сценарий. Для небольших заданий, состоящих из пары заданий:
stages:
- build
TASK_NAME:
stage: build
script:
- ./build_script.sh
- stages — описание стадий нашего пайплайна. В данном примере, всего одна.
- TASK_NAME — имя нашей задачи.
- stage — стадия, к которой относится наше задание.
- script — набор скриптов для выполнения.
2. Стандартный цикл при сборке. Обычно, процесс CI/CD включает следующие шаги:
Для написания такого сценария за основу можно взять шаблон:
stages:
- build
- test
- delivery
- deploy
build-job:
stage: build
script:
- echo "Start build job"
- build-script.sh
test-job:
stage: test
script:
- echo "Start test job"
- test-script.sh
delivery-job:
stage: delivery
script:
- echo "Start delivery job"
- delivery-script.sh
deploy-job:
stage: deploy
script:
- echo "Start deploy job"
- deploy-script.sh
Задания
<TASK_NAME>:
<OPTION1>: ...
<OPTION2>: ...
Мы перечислим лишь часто встречаемые опции. Полный список можно найти в официальной документации.
Stage
Опция указывает, к какой стадии относится задание. Например:
stages:
- build
- test
TASK_NAME:
...
stage: build
TASK_NAME:
...
stage: test
Сами же стадии описываются в общей директиве stages.
Также есть две стадии, которые не требуют предварительного определения в stages:
- .pre — запускает до выполнения основных заданий конвейера.
- .post — выполняется в конце, после выполнения основных заданий нашего пайплайна.
stages:
- build
- test
getVersion:
stage: .pre
script:
- VERSION=$(cat VERSION_FILE")
- echo "VERSION=${VERSION}" > variables.env
artifacts:
reports:
dotenv: variables.env
Image
Задаем имя образа, если наше задание выполняется в контейнере docker:
TASK_NAME:
...
image: debian:11
Before_script
TASK_NAME:
...
before_script:
- echo "Run before_script"
Script
Основная часть, где выполняются задания сценария, описана в опции script. Рассмотрим ее подробнее.
TASK_NAME:
...
script:
- command1
- command2
TASK_NAME:
...
script:
- |
command_line1
command_line2
TASK_NAME:
...
script:
- >
command_line1
command_line1_continue
command_line2
command_line2_continue
* данный индикатор интерпретирует новую команду после пустой строки.
After_script
Набор команд, которые запускаются после scripts, даже, при неудачном завершении последнего.
TASK_NAME:
...
script:
...
after_script:
- command1
- command2
Artifacts
1. Например, так можно указать, какие файлы или каталоги будут артефактами:
TASK_NAME:
...
artifacts:
paths:
- ${PKG_NAME}.deb
- ${PKG_NAME}.rpm
- *.txt
- configs/
* в моем примере, в артефакты попадут все файлы, название которых заканчивается на txt, файлы ${PKG_NAME}.deb и ${PKG_NAME}.rpm, а также каталог configs. Где ${PKG_NAME} — переменная (подробнее о переменных ниже).
В других заданиях, которые будут выполняться после можно использовать артефакты, обращаясь к ним по именам, например:
TASK_NAME_2:
...
script:
- cat *.txt
- yum -y localinstall ${PKG_NAME}.rpm
- apt -y install ./${PKG_NAME}.deb
2. Также мы можем передать системные переменные, которые были нами переданы в файл:
TASK_NAME:
...
script:
- echo -e "VERSION=1.1.1" > variables.env
...
artifacts:
reports:
dotenv: variables.env
* в данном примере мы передадим системную переменную VERSION со значением 1.1.1 через файл variables.env.
3. При необходимости, мы можем исключить из списка определенные файлы по названию или маске:
TASK_NAME:
...
artifacts:
paths:
...
exclude:
- ./.git/**/*
* в данном примере мы исключаем каталог .git, в котором, как правило, хранятся метаданные репозитория.
** обратите внимание, что в отличие от paths, exclude не берет файлы и каталоги рекурсивно и нужно явно указывать объекты.
Extends
.my_extend:
stage: build
variables:
USERNAME: my_user
script:
- extend script
TASK_NAME:
extends: .my_extend
variables:
VERSION: 123
PASSWORD: my_pwd
script:
- task script
И так, в нашем задании TASK_NAME мы используем extends. В результате, задание примет такой вид:
TASK_NAME:
stage: build
variables:
VERSION: 123
PASSWORD: my_pwd
USERNAME: my_user
script:
- task script
- stage: build попало в задание из my_extend.
- произошло объединение variables, итого в задание попали VERSION, PASSWORD и USERNAME.
- script используется из задания (значения ключей не объединяются, приоритет за значением основного задания).
Environment
Позволяет указать системную переменную, которая будет создана для выполнения задания.
TASK_NAME:
...
environment:
RSYNC_PASSWORD: rpass
EDITOR: vi
Release
Публикует релиз на портале Gitlab для нашего проекта.
TASK_NAME:
...
release:
name: 'Release $CI_COMMIT_TAG'
tag_name: '$CI_COMMIT_TAG'
description: 'Created using the release-cli'
assets:
links:
- name: "myprogram-${VERSION}"
url: "https://gitlab.com/master.dmosk/project/-/jobs/${CI_JOB_ID}/artifacts/raw/myprogram-${VERSION}.tar.gz"
rules:
- if: $CI_COMMIT_TAG
* обратите внимание, что мы применяем правило if (о нем ниже).
Директивы правил и ограничений
Rules
Правила, при соблюдении которых наше задание может быть запущено. Примеры работы с директивой rules приведены ниже.
When
Определяет условия запуска задания, например, только ручной запуск или через определенный интервал времени. Примеры работы приведены ниже.
Needs
Тоже набор правил, требующий определенных условий для запуска задачи. Все директивы условий и правил описаны ниже.
Правила и условия
Rules
Регламентирует различные правила, определенные с помощью:
1. Оператор if. Позволяем проверить условие, например, если переменная равна определенному значению:
TASK_NAME:
...
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
* в данном примере коммит должен быть выполнен в бранче по умолчанию.
2. Изменения затронули определенные файлы. Проверка выполняется с помощью опции changes.
В данном примере, файл script.sql:
TASK_NAME:
...
rules:
- changes:
- script.sql
а) При условии, что коммит выполнен в бранче по умолчанию И изменения затронули файл script.sql:
TASK_NAME:
...
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
changes:
- script.sql
б) При условии, что коммит выполнен в бранче по умолчанию ИЛИ изменения затронули файл script.sql
TASK_NAME:
...
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
- changes:
- script.sql
4. Проверка на существование файла. Определяется с помощью exists:
TASK_NAME:
...
rules:
- exists:
- script.sql
* задание будет выполняться только в случае присутствия файла script.sql.
5. Разрешить сбой задания. Задается с помощью allow_failure:
TASK_NAME:
...
rules:
- allow_failure: true
* в данном примере наш конвейер продолжит работу, если задание TASK_NAME будет выполнено с ошибкой.
6. Определение переменной в зависимости от условия. Для этого используются вместе if и variables:
TASK_NAME:
...
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
variables:
DEPLOY_VARIABLE: "production"
- if: '$CI_COMMIT_BRANCH =~ demo'
variables:
DEPLOY_VARIABLE: "demo"
When
Определяет условия запуска задания. Возможные значения:
- on_success (по умолчанию) — если все задания на более ранних этапах завершились успешно или имеют allow_failure: true.
- manual — запуск вручную (в панели pipeline появится кнопка запуска).
- always — запускать всегда, независимо от предыдущих результатов.
- on_failure — только в случае сбоя, хотя бы, одного задания на более раннем этапе.
- delayed — отложить запуск задания. Контролировать срок можно с помощью директивы start_in.
- never — никогда не запускать задание.
TASK_NAME:
...
when: manual
* задание не начнет выполняться, пока мы не нажмем кнопку запуска в GitLab CI/CD.
TASK_NAME:
...
when: always
TASK_NAME:
...
on_failure: always
TASK_NAME:
...
when: delayed
start_in: 30 minutes
* запуск задания будет отложен на 30 минут.
TASK_NAME:
...
when: never
* задание не будет выполняться.
TASK_NAME:
...
rules:
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
when: manual
Needs
TASK_NAME:
...
needs:
- artifacts: false
… позволяет начать выполнение задания без этого.
2. Job. Позволяет начать выполнение задачи только после завершения другого задания:
TASK_NAME:
...
needs:
- job: createBuild
* в нашем примере задача начнет выполняться не раньше завершения задачи с названием createBuild.
Переменные
Пользовательские переменные
Задаются с помощью директивы variables.
Можно определить глобально для всех заданий:
variables:
PKG_VER: "1.1.1"
TASK_NAME:
...
variables:
PKG_VER: "1.1.1"
script:
- echo ${PKG_VER}
Переменные Gitlab
Переменная | Описание | Пример |
---|---|---|
LOG_LEVEL | Определяет уровень журнала. Варианты: debug, info, warn, error, fatal, и panic. Имеет более низкий приоритет, по сравнению с аргументами командной строки —debug, —log-level. | LOG_LEVEL: warning |
CI_DEBUG_TRACE | Включение или отключение ведения журнала отладки. Принимает значения true или false. | CI_DEBUG_TRACE: true |
CONCURRENT | Ограничивает количество заданий, которые могут выполняться одновременно. | CONCURRENT: 5 |
GIT_STRATEGY | Способ загрузки файлов из репозитория. Возможны варианты: clone, fetch, и none (не загружать). | GIT_STRATEGY: none |
Дополнительные параметры
В данном разделе мы рассмотрим различные опции, которые не вошли в другие разделы.
workflow:
rules:
- if: $CI_COMMIT_TITLE =~ /-draft$/
when: never
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
- Не будет запущен, если название коммита содержит текст draft.
- Будет запущен, если пайплайн сработал после merge request.
- Будет запущен, если изменения внесены в основную ветку репозитория.
default:
image: centos:7
tags:
- ci-test
а) подключение локального файла (local):
include:
- local: .gitlab/ci/build.yml
б) коллекции шаблонов (template):
include:
- template: Custom/.gitlab-ci.yml
* в данном примере мы подключим к нашему сценарию содержимое файла Custom/.gitlab-ci.yml.
в) внешний файл доступный по HTTP (remote):
include:
- remote: 'https://gitlab.dmosk.ru/main/build.yml'
include:
- project: 'public-project'
ref: main
file: 'build.yml'
.apt-cache:
script:
- apt update
after_script:
- apt clean all
install:
stage: install
script:
- !reference [.apt-cache, script]
- apt install nginx
update:
stage: update
script:
- !reference [.apt-cache, script]
- apt upgrade
- !reference [.apt-cache, after_script]
* давайте разберемся, что происходит в нашем примере.
- Мы создали задачу apt-cache. Точка в начале названия говорит системе, что данную задачу не нужно стартовать автоматически при запуске pipeline. Созданная задача состоит из двух секций script и after_script. Секций может быть больше.
- Мы выполняем стадию install. В одной из строк выполнения мы вызываем apt-cache (только команды из раздела script).
- При выполнении стадии update мы вызываем apt-cache два раза — первый выполняет команды раздела script, второй — after_script.
Источник: https://www.dmosk.ru/miniinstruktions.php?mini=gitlab-pipeline