Как написать Pipeline в GitLab для схожих репозиториев

«Как написать Pipeline в GitLab для схожих репозиториев» — вопрос из категории CI/CD, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для поддержания единообразия и избежания дублирования в нескольких репозиториях я использовал подход с шаблонами (templates), подключаемыми через директиву include. Это позволяет централизованно управлять логикой сборки, тестирования и деплоя.

1. Создаем общий шаблон в отдельном репозитории или проекте (gitlab-ci-templates):

Файл: .gitlab-ci-common.yml

# Общие переменные для всех проектов
variables:
  DOCKER_REGISTRY: "registry.example.com"
  DOCKER_BUILDKIT: 1

# Шаблон для сборки Docker-образа
.docker-build:
  image: docker:20.10
  services:
    - docker:20.10-dind
  before_script:
    - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY
  script:
    - docker build --pull -t $DOCKER_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA .
    - docker push $DOCKER_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH

# Шаблон для запуска unit-тестов (пример для Node.js)
.unit-tests:
  image: node:16-alpine
  script:
    - npm ci
    - npm run test:unit
  artifacts:
    when: always
    reports:
      junit: reports/junit.xml
    paths:
      - coverage/

2. В .gitlab-ci.yml каждого микросервиса подключаем и расширяем шаблоны:

# Подключаем общие шаблоны
include:
  - project: 'devops/gitlab-ci-templates'
    ref: main
    file: '/.gitlab-ci-common.yml'

# Определяем стадии для этого конкретного проекта
stages:
  - test
  - build
  - deploy

# Job для линтера (может быть уникальным для проекта)
eslint:
  stage: test
  image: node:16-alpine
  script:
    - npm ci
    - npm run lint

# Job для сборки — наследуем и расширяем общий шаблон
build-image:
  extends: .docker-build
  stage: build
  # Добавляем специфичные для проекта переменные
  variables:
    DOCKERFILE_PATH: ./Dockerfile.prod

# Job для деплоя в Kubernetes (также может быть шаблонным)
deploy-staging:
  stage: deploy
  image: bitnami/kubectl:latest
  script:
    - kubectl config use-context staging
    - kubectl set image deployment/$CI_PROJECT_NAME app=$DOCKER_REGISTRY/$CI_PROJECT_PATH:$CI_COMMIT_SHORT_SHA -n staging
  environment:
    name: staging
    url: https://staging.example.com

Преимущества такого подхода:

  • Единый источник истины: Изменения в процессе CI/CD вносятся в одном месте.
  • Гибкость: Каждый проект может переопределять или расширять шаблонные jobs под свои нужды.
  • Снижение ошибок: Минимизируется копипаста конфигураций между репозиториями.