Задача pipeline и первый job
Курс «Лаборатория GitLab CI/CD»
GitLab CI/CD описывает действия, которые выполняются для определённой версии проекта. В этой серии подготовим лабораторию course-card: из небольшого JSON-каталога строится статическая страница, затем результат проверяется, сохраняется как артефакт и передаётся в отдельное учебное состояние staging. Мы будем разбирать устройство конвейера, причины передачи файлов и правила запуска.
Это собственный проект, продолжающий тему начального pipeline. Он не повторяет курс Git и не настраивает VPS, DNS или рабочий хостинг. Предполагается, что вы понимаете файлы репозитория и умеете читать простые команды. Все листинги и результаты в серии являются инструкциями для самостоятельного прохождения: при подготовке материалы не запускались, проект в реальном GitLab не создавался.
Три участника процесса
Репозиторий хранит исходники: courses.json, шаблон страницы и программы в scripts/. GitLab читает файл .gitlab-ci.yml и создаёт pipeline — набор заданий для события и версии. Runner получает отдельные задания и выполняет их в своей среде. Это разные роли. Наличие репозитория ещё не означает, что найдётся runner, способный исполнить нужный job.
Job — единица работы с именем, командами и условиями. Pipeline связывает несколько таких единиц. В начальном варианте используем только inspect-runtime, чтобы проверить намерение конфигурации, а не сразу объединять сборку, проверки и публикацию. Если первый job не может стартовать, разбор большого конвейера будет затруднён множеством независимых причин.
Сохраните следующий полный вариант как .gitlab-ci.yml в собственном учебном проекте. Здесь контейнер node:24-bookworm-slim задаёт семейство среды. Его тег не является неизменяемым идентификатором образа; для строгой фиксации в реальном процессе применяют проверенный digest. Нам пока достаточно объявить подходящую среду с Node.js 24.
default:
image: node:24-bookworm-slim
inspect-runtime:
script:
- node --version
- node -e 'console.log("course-card pipeline")'
default задаёт общую настройку образа. Имя inspect-runtime выбираем сами, а script является ключом GitLab. Две команды в списке выполняются последовательно в одном job. Ожидаем увидеть версию Node.js и строку course-card pipeline; конкретный patch-номер зависит от образа на момент самостоятельного запуска.
Что означает успешное задание
Job считается успешным по результату выполнения команд, а не по слову success в журнале. Если программа вернёт ненулевой код завершения, задание обычно завершится ошибкой. Вывод помогает понять причину, но сам по себе не устанавливает состояние. Поэтому строка «всё готово», напечатанная до настоящей сборки, не является доказательством готового сайта.
Вводная демонстрация Валентина Деспа показывает простой build/test-путь: одно задание создаёт файл, следующее пытается его найти и сначала получает ошибку. Причина — раздельное выполнение jobs; затем автор добавляет artifacts. Мы сохраняем этот учебный механизм, но расширяем предмет до настоящих данных каталога. Современное начало работы также описано в официальном tutorial GitLab.
Не требуется добавлять в этот первый job секреты, подключение к серверу или установку npm-пакетов. Наши программы используют встроенные возможности Node.js, а реальный выпуск наружу не входит в основной сценарий. Чем меньше первых действий, тем легче отличить ошибку YAML от недоступного runner и отсутствующей команды внутри образа.
Надпись pending в GitLab обычно означает, что job ждёт подходящего исполнителя. Она не равна синтаксической ошибке самой программы. Наличие активного runner, его tags и доступность для проекта рассматриваются позднее. Пока важно знать, что корректная конфигурация и фактическое начало работы — разные события.
Данные и конечный договор
В архиве лаборатории находятся три курса: «Сетка каталога», «Запросы к API» и «Git в команде». Каждый объект имеет slug, title, level и lessons. slug станет устойчивым идентификатором, заголовок попадёт в HTML, число занятий — в подпись. Данные придуманы для учебного проекта и не описывают реальную выдачу ProfessorWeb.
{"slug":"grid-catalog","title":"Сетка каталога","level":"basic","lessons":8}
Сборка создаст dist/index.html и dist/release.json. Метаданные выпуска будут содержать версию исходников и хэши подготовленных файлов. Проверка прочитает именно собранный каталог, а не повторно создаст его по новой ветке. Затем подготовка staging скопирует тот же артефакт в папку внутри job. Это учебная модель передачи результата, а не размещение сайта у посетителей.
| Объект | Для чего нужен | Чего не доказывает |
|---|---|---|
| Исходники | Описывают данные и генерацию | Что сборка завершилась |
| Job | Выполняет выбранные команды | Что другие jobs получили его файлы |
| Артефакт | Сохраняет результат конкретной работы | Что сайт опубликован |
| Staging-пакет | Показывает подготовленный к передаче результат | Что существует внешний сервер |
Формулировка конечного договора поможет оценивать каждое добавление. Кэш должен ускорять вспомогательное действие, а не служить единственным хранилищем выпуска. Переменная не должна молча менять данные между сборкой и проверкой. Ручная стадия должна потреблять подготовленные файлы, а не пересобирать другой результат. Эти различия будем постепенно выражать в конфигурации.
Чтобы проверить границу первого результата, представьте job, который печатает нужную строку, но не создаёт ни одного файла. Он корректно выполнит диагностическую задачу, однако не подготовит сайт. Затем представьте файл, созданный вручную на компьютере автора: его наличие не означает успешный pipeline для текущего commit. В обоих случаях важно назвать, какое утверждение подтверждается наблюдением. Для нашей лаборатории первый шаг подтверждает только выполнение конкретных команд в выбранной среде. Следующие шаги добавляют новые обязательства по данным, файлам и проверке, а не меняют прошлый результат задним числом.
Границы самостоятельной работы
В своих учебных условиях можно создать отдельный проект и добавить конфигурацию, если у вас есть соответствующие права. Не переносите пример сразу в рабочий pipeline с доступом к production. Даже без внешней публикации команды выполняются на runner и получают доступ к окружению, которое предоставлено проекту. Набор прав должен соответствовать назначению конкретного задания.
Полный синтаксис ключей находится в справочнике YAML GitLab. В этой серии конфигурация сохраняется этапами в ci/lesson-01.yml и следующих снимках, поэтому можно сравнивать изменения без поиска скрытых фрагментов. Основной .gitlab-ci.yml в архиве содержит конечный вариант, а уроки объясняют путь к нему.
После первого шага ожидаем один диагностический job и понятный договор лаборатории. Успех такого задания подтверждает только доступность выбранной среды для указанных команд. Он ещё не строит каталог и не передаёт файлы. Следующий урок добавит сборку и покажет, почему порядок стадий сам по себе не создаёт общую рабочую папку.