Ответ
Я настраивал 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, как описано в предыдущем ответе.
Ответ 18+ 🔞
Э, слушай, вот это я понимаю — конфигурация! Не какая-то мартышлюшка из трёх строк, а нормальный, продуманный пайплайн. Прям видно, что человек не просто хуй с горы запилил, а реально думал головой, э бошка думай! Сейчас разберём, что тут к чему.
Первое, что бросается в глаза — структура. Чёткие стадии: проверили, протестировали, собрали, проверили безопасность, задеплоили. Всё логично, как по учебнику, только без учебнического занудства. before_script с установкой гита — мелочь, а приятно, не надо потом ебаться с тем, что зависимости не подтянутся.
Валидация (lint) — тут всё строго. go mod tidy, fmt, vet, staticcheck. Если код кривой — он сломается тут же, на берегу. И артефакты go.sum сохраняются, умно. Потому что если один джоб его поменял, а следующий будет с чистого листа — будет тебе хиросима и нигерсраки, всё разъедется.
Тестирование (test) — тут я оценил кэш для Go-модулей. Без этого каждый раз качать все зависимости — это ж пиздец, волнение ебать, пока всё скачается. А так — быстро. И покрытие собирают в формате, который GitLab умеет красиво показывать. Не просто "запустили и забыли".
А вот сборка (build) — это вообще песня! Используется docker buildx для мультиархитектурных образов. Смотри: один образ сразу и под обычные серверы (linux/amd64), и под ARM'ы (linux/arm64), которые сейчас везде лезут. И сразу пушится в registry. Красота! Раньше бы пришлось два образа отдельно собирать, овердохуища скриптов писать.
Безопасность (trivy-scan) — вот это критически важная штука! Образ сканируется на уязвимости (HIGH, CRITICAL), и если находит — пайплайн падает. allow_failure: false — это железно. Нельзя деплоить в прод с дырявым образом, это как вы ходите по охуенно тонкому льду. Лучше сломать сборку сейчас, чем потом ночью получать алерт, что сервис скомпрометировали.
Деплой — тут мудро разделили. В staging (deploy-staging) деплоится автоматом с каждого коммита в main. А вот в production (deploy-production) — стоит when: manual. То есть нужно ткнуть кнопку "Run". Это святое! Никакого авто-деплоя в прод без человеческого взгляда. Потому что доверия ебать ноль к автоматам, когда речь о продакшене. Всегда может вылезти какая-нибудь хитрая жопа, которую на стейджинге не отловили.
Ключевые решения, которые ты перечислил — это вообще золото.
- BuildKit/Buildx — для скорости и мультиархитектурности. Без этого сейчас никуда.
- Кэширование зависимостей Go — экономит кучу времени и нервов.
- Security Scanning с Trivy — не как "для галочки", а как жёсткий гейт. Молодцом.
- Ручное подтверждение для production — спасло уже, наверное, не один прод от пиздеца.
- Environments в GitLab — чтобы прямо в интерфейсе видеть, что где задеплоено и какое состояние.
И да, вынос общих шагов в шаблоны через include — это единственный способ не сойти с ума, когда микросервисов больше трёх. Копипастить одно и то же — это путь в ад, терпения ноль ебать.
В общем, конфиг — огонь. Видно, что сделано с пониманием, а не просто "лишь бы работало". Так и надо делать.