Gitlab
Описание
Распределенная система хранения репозиториев, с большим инструментарием для работы с ними.
Дает возможность компаниям развернуть свой инстанс Gitlab для своих проектов.
Предоставляет систему построения CI/CD (Gitlab CI)
Содержит в себе встроенные хранилища для репозиториев, образов Docker, раннеров, Jira и другие инструменты.
Gitlab CI
Описание
Gitlab CI - инструмент для автоматизации процессов разработки и доставки ПО.
Позволяет автоматически собирать, тестировать и деплоить ПО.
Основные атрибуты pipeline
pipeline
pipeline - это набор задач, которые выполняются в определенном порядке.
Сам пайплайн описывается в файле который лежит в корне проекта (под служебным названием .gilab-ci.yml, но может называться как угодно)
pipeline состоит из самого pipeline. Внутри него есть stages (этапы) и внутри stages лежат сами задачи (jobs)
Любой gitlab-ci.yml начинается с описания stages
Скрытые stages
Существует два специальных stages: .pre, .post.
Эти stages выполняются всегда в начале и всегда в конце pipeline. В них никаких jobs нет.
Jobs - задачи или джобы описываются нвчиная с имени, затем указываются атрибуты будущей задачи и сам скрипт, который она выполняет
Variables - переменные используются для передачи изменяемых данных внутрь задачи. Указанные переменные устанавливаются переменными окружения внутри раннера.
stages:
- build
build app:
variables:
POSTGRES_DB: appname_db
stage: build
script:
- command_to_build my_app --arg POSTGRES_DB=${POSTGRES_DB}
Globals - большинство атрибутов, можно вынести из секции описания задачи на верхний уровень. Тогда они станут глобальными параметрами по-умолчанию. Их все еще можно переопределить внутри джобы.
stages:
- build
variables:
POSTGRES_DB: appname_db
build app:
stage: build
script:
- command_to_build my_app --arg POSTGRES_DB=${POSTGRES_DB}
Пример pipeline
В папке проекта создаем файл .gitlab-ci.yml:
# описание stages
stages:
- lint
- build
- test
- deploy
# описание job под названием docker build
docker build:
# название этапа
stage: build
# команды для выполнения
script:
- docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} ${CI_REGISTRY}
- docker build -t ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} .
- if [[ "${CI_COMMIT_BRANCH}" == "${CI_DEFAULT_BRANCH}" ]] ; then
docker tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} ${CI_REGISTRY_IMAGE}:latest;
docker push ${CI_REGISTRY_IMAGE}:latest; fi
- if [[ -z "${CI_COMMIT_TAG}" ]] ; then
docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG};
else
docker tag ${CI_REGISTRY_IMAGE}:${CI_COMMIT_REF_SLUG} ${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG};
docker push ${CI_REGISTRY_IMAGE}:${CI_COMMIT_TAG}; fi
needs:
- ["django tests"]
tags:
- docker
django tests:
image: python:3.9-alpine
stage: test
script:
- pip install -r requirements.txt
- mkdir db
- python manage.py test
# тег gitlab-runner для этого job
tags:
- dev-shell
Services сайдкары для контейнера
Зачем нужны сервисы
Сервис - это дополнительный контейнер, который поднимается вместе с основным, в момент выполнения задачи.
- Контейнеры связываются между собой (links)
- К сервису имеется доступ во время сборки
Пример сервиса postgresql
Описываем сервис, после чего вызываем подключение к нему из задачи
Обращение к хосту выполняется по имени сервиса, если не определено иное имя через alias.
services:
- postgres
variables:
POSTGRES_DB: custom_db
POSTGRES_USER: custom_user
POSTGRES_PASSWORD: custom_pass
connect:
script:
- export PGPASSWORD=$POSTGRES_PASSWORD
- psql -h "postgres" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT 'OK' AS status;"
Различные версии приложения
Можно использовать разные версии одного сервиса для приложения.
test:2.6:
image: ruby:2.6
services:
- postgres:11.7
script:
- bundle exec rake spec
test:2.7:
image: ruby:2.6
services:
- postgres:12.2
script:
- bundle exec rake spec
Конфигурирование
Можно задать параметры для сервисного контейнера, как для любого обычного контейнера.
Например, переопределить имя и стартовые команды.
default:
image:
name: ruby:2.6
entrypoint: ["/bin/bash"]
services:
- name: my-postgres:11.7
alias: db-postgres
entrypoint: ["/usr/local/bin/db-postgres"]
command: ["start"]
test:
script:
- bundle exec rake spec
variables:
HTTP_PROXY: "https://10.1.1.1:8090"
POSTGRES_DB: "my_custom_db"
POSTGRES_USER: "postgres"
POSTGRES_PASSWORD: "example"
PGDATA: "/var/lib/postgresql/data"
POSTGRES_INITDB_ARGS: "--encoding=UTF8 --data-checksums"
services:
- name: postgres:11.7
test:
script:
- bundle exec rake spec
Класический пример сервиса: dind
dind - docker in docker
Используется для доступа к docker-daemon изнутри контейнера с docker cli.
Для этого также нужно определить переменную DOCKER_HOST.
Сохранение результатов
Работа с артефактами
Cache - сохранение результатов работы раннера между задачами одного этапа. Можно использовать S3-хранилище.
- можно задавать любой ключ
- можно использовать только в рамках одного раннера
- нельзя скачать в виде артефакта
Artifacts - сохранение результатов сборок и работы раннера для последующего использования. Можно скачать чеерз интерфейс. Используется для передачи состояния между этапами.
- множество вариаций конфигурирования
- доступно между раннерами
- можно скачать через UI
- можно выкладывать как репорты
Кастомизация пайплайнов
Дополнительные параметры задач
before_script/after_script - то же самое, что и script, но выполняется либо перед либо после него
when/rules/workflow - правила для параметризации задач: можно задать условия при которых пайплайн будет запускаться
when - условие запуска задачи
Job в ручном режиме
Job запускается сама
Rules - задание дополнительных условий для job
tests_codestyle_check:
stage: test
script:
- composer install -q
- php vendor/bin/phpcs
rules:
- if: $CI_JOB_STAGE == "test"
when: always
- if: $VAR == "string value"
when: always
Workflow - общие правила для всего pipeline
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
when: never
- if: $CI_COMMIT_BRANCH`
Predefined CI/CD variables
| Переменная | Описание |
|---|---|
gitlab-ci-token |
специальный пользователь, которого GitLab создает автоматически только на время работы job. Пример использования: docker login -u gitlab-ci-token -p ${CI_JOB_TOKEN} |
${CI_JOB_TOKEN}=[MASKED] |
уникальный токен конкретной job. После завершения job становится недействительным |
${CI_PROJECT_NAME}=for_test |
название репозитория |
${CI_REGISTRY}=registry.gitlab.com |
адрес Registry GitLab |
${CI_REGISTRY_IMAGE}=registry.gitlab.com/username/for_test |
адрес образа в GitLab Container Registry |
${CI_COMMIT_REF_SLUG}=main |
имя ветки преобразованное в безопасный формат (было feature/docker стало feature-docker). Часто используется docker build -t app:$CI_COMMIT_REF_SLUG . |
${CI_COMMIT_REF_NAME}=main |
на какой ветке или теге сейчас выполняется pipeline |
${CI_COMMIT_SHA}=1009a5559f4e23c862a18eddc4fbb5f3d3e1534d |
полный SHA коммита |
${CI_COMMIT_BRANCH}=main |
ветка, для которой сейчас выполняется pipeline. Она меняется в зависимости от того, где ты сейчас находишься |
${CI_DEFAULT_BRANCH}=main |
название основной ветки, используется чтобы не хардкодить на случай если дефолтная ветка изменит свое название |
${CI_COMMIT_TAG} |
название тега |
${CI_PIPELINE_SOURCE=push / merge_request_event |
откуда запустился pipeline (push/merge_request_event\schedule\web) |
${CI_PIPELINE_URL}=https://gitlab.com/username/for_test/-/pipelines/2666589838} |
ссылка на pipeline (можно отправлять в telegram) |
${CI_JOB_NAME}=show variables |
название job |
${CI_PROJECT_DIR}=/home/gitlab-runner/builds/pJwjkgAw6/0/andreyd97/for_test |
куда runner склонировал проект. Все команды выполняются отсюда |
| --- |
Советы
1) По максимуму использовать переменные (где возможно)
Плохо:
Правильно: