Сборка и требования
Требования:
- Go 1.26+
- PostgreSQL, Redis
- Make
Локальная сборка
# Установка зависимостей
go mod download
# Линт/тест/сборка
go vet ./...
go test ./... -race
go build ./...Линтеры
Используется golangci-lint v2.10.1 с дополнительными линтерами:
# Установка
make install-lint
# Полный прогон
make lint
# Быстрый (только app + domain)
make lint-fast
# Архитектурная проверка (domain не импортирует infra/app)
make lint-archВключены линтеры: gosec (безопасность), bodyclose (закрытие тел HTTP-ответов), noctx (передача context в HTTP-запросы). Конфигурация — .golangci.yml.
Сканирование уязвимостей
make vulncheckЗапускает govulncheck ./... — проверяет зависимости на известные CVE.
CI (.gitlab-ci.yml)
Этапы пайплайна:
| Этап | Job | Когда |
|---|---|---|
check | lint (golangci-lint), lint-docs (redocly-cli через npm run lint-docs), test (go test + coverage), integration (Postgres+Redis) | Каждый push |
security | govulncheck | Каждый push |
build | build (go build) | Push без тега |
build | build-image (Kaniko → Container Registry) | Push в ветку v2/develop; в остальные ветки — вручную |
build | build-release (bundle + upload в Package Registry), build-image-release (Kaniko → Container Registry), build-docs (сборка VitePress-документации) | Push с тегом |
Из одного пайплайна выходят два артефакта, и оба адресуются одной и той же версией:
| Артефакт | Куда | Кто потребляет |
|---|---|---|
Deployment bundle (.tar.gz) | Generic Packages | VM + systemd через marv-ctl.sh (пин .marv-version) |
| OCI-образ | Container Registry | Kubernetes через Helm/Flux (пин image.tag) |
Оба собираются только после зелёных check и security — образ публикуется в реестр не раньше, чем пройдут линтеры и тесты.
Шаблон Kaniko (.build-image-template) подключается через include из infra/deploy — тот же, что использует zircon.
Deployment Bundle
Бандл — самодостаточный архив для деплоя на сервер (Go на сервере не нужен):
# Для текущей ОС
make bundle
# Для Linux (серверы)
make bundle-linux
# С явной версией
VERSION=1.2.3 make bundle
# Произвольная платформа
make bundle GOOS=linux GOARCH=arm64Содержимое бандла:
marv-VERSION-OS-ARCH/
├── bin/
│ ├── marv # основной сервер
│ ├── hgoose # утилита миграций БД (goose v3)
│ └── config-migrator # конвертер legacy-конфигов
├── scripts/
│ ├── deploy.sh # управление (run, migrate, version, ...)
│ └── marv.service.template # шаблон systemd unit
├── migrations/
│ └── *.sql # SQL-миграции
└── config/
├── config.example.yml # пример конфигурации
├── bots.example.json # пример конфигурации ботов
├── products.example.json # пример конфигурации продуктов
└── .env.example # пример переменных окруженияПараметры сборки:
CGO_ENABLED=0— статическая линковка-tags=go_json— ускоренный JSON через go_json-ldflags="-s -w -X ...AppVersion=VERSION"— инъекция версии, strip debug info
OCI-образ
Второй артефакт того же пайплайна — контейнерный образ в GitLab Container Registry (registry.gitlab.hgpoint.com/servers/marv). Собирается Kaniko по корневому Dockerfile.
Схема тегов:
| Пайплайн | Теги | VERSION в бинарнике |
|---|---|---|
| Push в ветку | <branch>-<short-sha> (например v2-3f9c1a2b) и подвижный <branch> | <branch>-<short-sha> |
Тег vX.Y.Z | vX.Y.Z, плюс latest для SemVer | vX.Y.Z |
<branch>-<short-sha> неизменяем и при этом читается человеком: видно ветку и коммит без похода в реестр. Подвижные <branch> и latest — только для локального docker pull; в Kubernetes всегда пинится неизменяемый тег или digest.
vX.Y.Z — та же строка, что и версия Generic Package и что game-репозиторий держит в .marv-version, поэтому один тег адресует и бандл, и образ.
Версия видна тремя способами:
docker run --rm registry.gitlab.hgpoint.com/servers/marv:v2.3.6 -version
docker image inspect …:v2.3.6 --format '{{index .Config.Labels "org.opencontainers.image.version"}}'
docker image inspect …:v2.3.6 --format '{{index .Config.Labels "org.opencontainers.image.revision"}}' # git shaЧто внутри образа:
marv,hgoose,config-migratorв/usr/local/bin- SQL-миграции в
/app/migrations(для migrate-джобы:hgoose -dir /app/migrations) - только примеры конфигов в
/app/config—config.debug.ymlиconfig.release.ymlсодержат живые креды и в образ не попадают. Рабочий конфиг приходит извне: ConfigMap в k8s, bind-mount локально USER 65532:65532— образ non-root, иначе Kubernetes сrunAsNonRoot: trueне запустит под
Приватный модуль servers/shared тянется по --build-arg CI_JOB_TOKEN. Токен живёт только в builder-стадии и в опубликованные слои не попадает.
Деплой на сервер
Деплой выполняется через Game Repository — см. Game Repository workflow.
Там описаны: создание Deploy Token, настройка сервера, marv-ctl.sh, обновление версии и конфигов.
deploy.sh
Скрипт-помощник для управления бандлом на сервере. Входит в состав бандла.
| Команда | Описание |
|---|---|
migrate | Применить все миграции |
migrate-status | Статус миграций |
migrate-down | Откатить одну миграцию |
config-migrate <file> | Мигрировать legacy-конфиг в новый формат на месте (флаг -w перезаписывает исходный файл) |
run | Запустить сервер (GIN_MODE=release) |
version | Версия бинарников |
./scripts/deploy.sh migrate # миграции
./scripts/deploy.sh run # запуск
./scripts/deploy.sh version # версияDocker
Dockerfile (multi-stage build):
# Сборка образа (CI_JOB_TOKEN — PAT с доступом к servers/shared)
docker build -t marv:latest --build-arg VERSION=1.2.3 --build-arg CI_JOB_TOKEN=<pat> .
# Запуск — конфиг обязательно монтируется, в образе лежат только примеры
docker run -p 8080:8080 -v ./config:/app/config marv:latestDocker Compose (локальная разработка):
docker-compose up -dПоднимает marv + PostgreSQL 17 + Redis 7 с health-checks и пробросом портов; ./config монтируется в /app/config.
Запуск
# Из исходников
go run ./cmd/marv
# Из бинарника
./marvПеред деплоем:
- Применить миграции (
hgoose upили./scripts/deploy.sh migrate) - Заполнить конфиг или переменные окружения
- Dev: PostgreSQL и Redis локальные. Release: PostgreSQL — отдельный сервер, Redis — обычно локальный
