Замечательная штука, чтобы настроить свои CI/CD процессы. Думаю, по популярности идёт на втором месте, сразу после Jenkins’а и постепенно вытесняет его.
Итак, чтобы собрать свой pipeline в gitlab’е, нужно завести в нём репу, куда в корень просто добавляем .gitlab-ci.yaml
. В этом файле полностью описывается процесс. Он представляет из себя сгруппированный по стадиям набор задач, запускающий скрипты в докер контейнере. Если кратко, то это и есть вся суть процесса.
Сами докер контейнеры для выполнения задач запускаются gitlab runner’ом — отдельной службой для CI/CD, устанавливаемой возможно даже на отдельном сервере и подключаемой к gitlab инстансу. Об его установке я рассказывал, но на gitlab.com есть готовые раннеры для всех — так что pet проекты, которые легко собираются, запустятся автоматически. А вообще, к gitlab.com также, как и к собственноручно установленному гитлабу, можно прикрутить свои ранеры.
Рассмотрим простой пример:
# говорим, в каком контейнере запускать pipeline
image: alpine:latest
# кэш сборки, объясню ниже..
cache:
paths:
- ./*.txt
# стадии - по ним группируются таски
stages:
- build
- package
# центральный элемент - job'а (задача)
build1:
stage: build # Запускаяется в рамках стадии build
only:
- master # только при пуше в ветку мастер
script: # и выполняет следующие sh скрипты
- echo "author alse-code" > author.txt
# аналогичная задача
build2:
stage: build
only:
- master
script:
- echo "Copyright (c) 2020" > copyright.txt
# job для другой стадии
collect:
stage: package
only:
- master
when: manual # запускается вручную по клику в интерфейсе
script:
- cat author.txt > artifact.txt
- cat copyright.txt >> artifact.txt
artifacts: # здесь мы указываем, что можно будет скачать после выполнения job'ы
paths:
- artifact.txt
# sh скрипты, запускающиеся перед каждой job'ой
before_script:
- echo "Before script section"
- echo "For example you might run an update here or install a build dependency"
- echo "Or perhaps you might print out some debugging details"
# sh скрипты, запускающиеся после каждой job'ы
after_script:
- echo "After script section"
- echo "For example you might do some cleanup here"
Важно: прежде чем написать и закоммитить свой пример, проверь его здесь: https://your-gitlab-project-url/-/ci/lint (CI/CD → Jobs → CI Lint (сверху слева)). Помимо проверки синтаксиса он выдаст много полезной информации.
В этом простом pipeline у нас три задачи: две для стадии build и одна в стадии package.
Задачи, объявленные в рамках одной стадии, выполняются параллельно. Сами стадии же — выполняются последовательно. Если задача на стадии завалилась, следующие стадии не выполняются, а pipeline считается проваленным (если только в задаче не указано allow_failure: true
)
Задачи выполняются только на ветке мастер, т.к. указано only master.
В ходе pipeline у нас создаются два файла — author.txt и copyright.txt. Затем в следующую стадию, в задаче collect, мы их объединяем и говорим, что полученный файл будет доступен как артефакт — то есть, когда зайдём в CI/CD → Jobs(или найдя job по pipeline) →collect job, то увидим справа

Однако эта задача collect не запускается сама — она помечена when: manual
. Для её запуска нужно нажать play на странице CI/CD → Pipelines

Последняя вещь, о которой я хочу рассказать. В данных задачах мы сами создаём файлы и оперируем ими. Обычно же мы оперируем файлами репы — дак вот, эти файлы также присутствуют в контейнере, а скрипты выполняются в директории с ними. Так что в данном случае можно просто сложить файлы author.txt и copyright.txt в корень проекта и оставить только задачу collect — результат будет аналогичным.
Но те файлы, которые мы создаём скриптом, видны только в рамках одной job’ы — после её выполнения репа возвращается в исходное состояние. Чтобы этого не происходило, я определил кэш:
cache:
paths:
- ./*.txt
файлы, отвечающие маске, будут сохраненяться в конце задач и будут доступны между ними. Таким образом, в задаче collect нам доступны созданные на предыдущей стадии txt файлы.
Вот и всё — просто пишем задачки, внутри которых пишем свои скрипты. На практике это и есть вся суть ci/cd 🙂
Погружение
Блог про Kotlin и джавовый стэк, поэтому вот официальный пример CI через gradle. Всё, что там есть, мы рассмотрели — разве что кэш на уровне отдельных job и переменные, но запутаться сложно.
Много других официальных примеров
Продвинутый уровень pipeline’ов на хабре