Ответ
Я настраивал GitLab CI/CD для микросервисной архитектуры, где каждый сервис имел свой репозиторий, но общие требования к сборке, тестированию и деплою. Конфигурация строилась на принципах скорости, безопасности и воспроизводимости.
Пример .gitlab-ci.yml для Go-микросервиса, разворачиваемого в Kubernetes:
# 1. Определяем глобальные настройки и образы
default:
image: golang:1.19-alpine
before_script:
- apk add --no-cache git
- go version
# 2. Разбиваем pipeline на стадии
stages:
- validate # Линтинг, проверка зависимостей
- test # Unit и интеграционные тесты
- build # Сборка артефактов и Docker-образов
- security # Сканирование уязвимостей
- deploy # Деплой в окружения
# 3. Job'ы для каждой стадии
# 3.1 Валидация
lint:
stage: validate
script:
- go mod tidy
- go mod verify
- go fmt ./...
- go vet ./...
- staticcheck ./...
artifacts:
when: always
paths:
- go.sum
expire_in: 1 week
# 3.2 Тестирование с кэшированием зависимостей и сбором покрытия
test:
stage: test
script:
- go test -race -coverprofile=coverage.txt -covermode=atomic ./...
coverage: '/total:s*(statements)?s*d+.d+%/'
artifacts:
reports:
cobertura: coverage.xml
paths:
- coverage.txt
cache: # Кэшируем модули Go для ускорения
key: ${CI_COMMIT_REF_SLUG}
paths:
- .go/pkg/mod/
# 3.3 Сборка мультиархитектурного Docker-образа
build:
stage: build
image: docker:20.10
services:
- docker:20.10-dind
variables:
DOCKER_BUILDKIT: 1
DOCKER_TARGET: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
script:
- |
docker buildx create --use
docker buildx build --platform linux/amd64,linux/arm64
--push
-t $DOCKER_TARGET
-f Dockerfile .
only:
- main
- merge_requests
# 3.4 Сканирование образа на уязвимости с Trivy
trivy-scan:
stage: security
image: aquasec/trivy:latest
variables:
TRIVY_NO_PROGRESS: "true"
script:
- trivy image --exit-code 1 --severity HIGH,CRITICAL $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
allow_failure: false # Фейл пайплайна при критических уязвимостях
# 3.5 Деплой в staging через Helm
deploy-staging:
stage: deploy
image: alpine/helm:3.10
environment:
name: staging
url: https://api-staging.example.com
script:
- helm upgrade --install
--namespace staging
--set image.tag=$CI_COMMIT_SHORT_SHA
--values .helm/values-staging.yaml
my-service .helm/
only:
- main
# 3.6 Ручное подтверждение для деплоя в production
deploy-production:
stage: deploy
image: alpine/helm:3.10
environment:
name: production
url: https://api.example.com
script:
- helm upgrade --install
--namespace production
--set image.tag=$CI_COMMIT_SHORT_SHA
--values .helm/values-production.yaml
my-service .helm/
when: manual # Требует ручного подтверждения
only:
- main
Ключевые решения в этой конфигурации:
- BuildKit и Buildx: Для мультиархитектурных сборок и эффективного кэширования слоев.
- Кэширование зависимостей Go: Значительно ускоряет этап тестирования.
- Security Scanning: Интеграция Trivy на ранней стадии для блокировки развертывания уязвимых образов.
- Ручное подтверждение для production: Обязательный гейт для контроля над выпуском.
- Environments: Использование встроенных окружений GitLab для отслеживания развертываний и их статусов.
Для управления общими шагами (например, деплоем Helm) я выносил их в шаблоны, подключаемые через include, как описано в предыдущем ответе.