Материал открыт для чтения

Войдите, чтобы сохранять прогресс и результаты.

Войти
GitLab CI/CD: от первых проверок до деплоя

.gitlab-ci.yml: команды, image, before_script и YAML

чтение ~6 минУрок 5 из 20

.gitlab-ci.yml: команды, image, before_script и YAML

module9 gitlab ci Image03

GitLab CI управляется файлом .gitlab-ci.yml в корне репозитория. Когда ты делаешь git push, GitLab читает этот файл, строит pipeline и отдает jobs runner-у.

Это обычный YAML-файл, поэтому отступы важны. Табуляции лучше не использовать. Если GitLab пишет yaml invalid, сначала проверь структуру.

В лабораторных файл удобно редактировать в VSCode внутри VM: нажми кнопку VSCode, открой папку gitlab-ci-lab и файл .gitlab-ci.yml. Если работаешь прямо в терминале, используй Vim.

В GitLab UI файл тоже можно открыть через Build -> Pipeline editor. Там GitLab может подсказать, валидна ли конфигурация. Но полный процесс как в реальном проекте такой: изменить файл в репозитории, сделать commit, push и посмотреть pipeline.

module9 gitlab ci Image24

Если GitLab показывает Pipeline syntax is correct, это означает только одно: YAML можно разобрать и GitLab понимает структуру pipeline. Это еще не доказывает, что команды внутри job реально пройдут. Например, docker build может упасть уже во время выполнения, если не найден Dockerfile.

Job

Job - минимальная единица работы. Пример:

check-shell:
  image: alpine:3.20
  stage: verify
  before_script:
    - apk add --no-cache bash
  script:
    - bash --version
    - ./scripts/check.sh
  after_script:
    - echo "job finished"

Что здесь происходит:

  • check-shell - имя job, оно будет видно в pipeline;
  • image - Docker image, внутри которого runner выполнит команды;
  • stage - этап pipeline;
  • before_script - подготовка перед основными командами;
  • script - главная работа job;
  • after_script - запускается и после успешного job, и после падения.

image

image отвечает на вопрос: “в каком окружении выполнить команды”. Если указать alpine:3.20, внутри job будет маленький Linux с Alpine. Если указать docker:27-cli, внутри будет Docker CLI.

show-os:
  image: alpine:3.20
  script:
    - cat /etc/os-release

Новички часто путают image в job и Docker image приложения. В GitLab CI image означает: runner запустит Docker container из этого образа и уже внутри него выполнит команды из script.

Например, если в job указано image: alpine:3.20, GitLab не собирает твоё приложение в Alpine. Он просто запускает временный container с Alpine и выполняет там команды job. А Docker image приложения - это отдельный результат сборки: его ты создаёшь командой docker build и потом отправляешь в registry.

before_script и after_script

У job есть основная часть - script. Именно там должна быть главная работа: запустить тесты, собрать приложение, собрать Docker image, выполнить deploy-команду.

Но почти всегда вокруг основной работы есть служебные шаги. Перед тестами нужно установить зависимости. Перед deploy нужно войти в registry (docker login) или подготовить SSH-ключ. После падения полезно вывести список файлов, статус сервиса или последние строки лога. Для таких случаев есть before_script и after_script.

before_script выполняется перед script. Его удобно использовать для подготовки окружения:

before_script:
  - apk add --no-cache curl bash
  - chmod +x ./scripts/check.sh

check-shell:
  image: alpine:3.20
  script:
    - ./scripts/check.sh

В этом примере runner сначала поставит curl и bash, затем сделает скрипт исполняемым, и только потом перейдет к основной команде ./scripts/check.sh.

Частые случаи для before_script:

  • поставить маленькую утилиту, которой нет в image;
  • выполнить docker login перед сборкой или публикацией image;
  • подготовить SSH-доступ перед deploy;
  • создать временную директорию;
  • проверить, что нужная переменная окружения задана;
  • выполнить одинаковую подготовку для нескольких jobs.

При этом before_script не должен превращаться в “установи половину системы каждый раз”. Если job постоянно начинает с большой установки пакетов, pipeline будет медленным. Обычно лучше выбрать более подходящий image или собрать свой базовый image для CI. Переиспользование общих блоков через шаблоны, extends и include мы разберём дальше.

after_script выполняется после script. Его часто используют не для основной работы, а для диагностики и аккуратного завершения:

after_script:
  - echo "job status: $CI_JOB_STATUS"
  - ls -la
  - tail -50 app.log || true

Такой блок полезен, когда job упал, а тебе нужно понять почему. Например, тесты завершились ошибкой, но after_script всё равно выведет статус, список файлов и последние строки лога. Это помогает быстрее разобраться, что произошло внутри контейнера runner-а.

Частые случаи для after_script:

  • вывести $CI_JOB_STATUS;
  • показать логи после падения;
  • проверить, какие файлы реально были созданы;
  • удалить временные файлы или остановить локальный тестовый процесс;
  • оставить понятную диагностику для человека, который открыл log job.

Важно: не стоит переносить в after_script то, от чего зависит успешность job. Основная проверка должна быть в script, потому что именно она показывает, прошла работа или нет. after_script лучше воспринимать как “после основной работы покажи полезную информацию и аккуратно заверши окружение”.

Multiline script

Для нескольких связанных shell-команд удобно использовать YAML block scalar:

test:
  script:
    - |
      set -e
      echo "start"
      ./run-tests.sh
      echo "done"

set -e останавливает shell при ошибке. Без него команда внутри многострочного блока может упасть, а job все равно продолжит выполнение, если следующая команда завершится успешно. Для CI это может быть опасно: pipeline может стать зеленым, хотя внутри была ошибка.

В следующей главе разберём variables. Это уже следующий слой поверх script и image: сначала посмотрим переменные, которые прямо записаны в .gitlab-ci.yml, потом переменные из интерфейса GitLab, а затем встроенные переменные, которые GitLab создаёт сам.

Материал изучен?

Войдите, чтобы сохранить прогресс и перейти к практической лаборатории.

Войти и продолжить