Непрерывная доставка (GitVerse → прод-сервер по SSH)¶
Пайплайн GitVerse: один файл .gitverse/workflows/gitverse-ci.yaml (jobs smoke API, frontend, docs, затем при необходимости SSH-деплой). Локальные вызовы uses: ./…/другой-workflow.yaml на GitVerse не используются — раннеры могли оставаться в «Ожидание». Длинные shell-шаги smoke и деплоя вынесены в scripts/ci/gitverse/.
После успешного прохождения всех jobs (smoke_api_tests, frontend_smoke_tests, docs_checks) выполняется job deploy_production, если:
- push в ветку
master, или - ручной запуск (workflow_dispatch) с включённым параметром «Запустить SSH-деплой на прод…» (
run_production_deploy).
Дальше: SSH на сервер, обновление кода, пересборка и запуск стека из docker-compose.prod.yml (скрипт сам выберет docker compose или sudo -n docker compose, см. ниже), ожидание статуса running у всех сервисов, HTTP-проверки с публичного URL.
Это типичная модель для небольших и средних команд: качество → затем деплой, один активный прод, секреты только в CI, ключ хоста зафиксирован (SSH host key pinning), деплойный SSH-ключ отделён от личного.
1. Отдельная пара ключей только для CI → сервер¶
Не используйте личный SSH-ключ.
На своей машине:
ssh-keygen -t ed25519 -f ./konstructorium-deploy-ci -C "konstructorium-gitverse-deploy" -N ""
Публичный ключ konstructorium-deploy-ci.pub добавьте на сервер в ~/.ssh/authorized_keys пользователя, под которым будет деплой (тот же пользователь, что и для вашего ручного SSH).
Приватный ключ konstructorium-deploy-ci целиком вставьте в секрет DEPLOY_SSH_PRIVATE_KEY в настройках репозитория GitVerse (вместе с строками BEGIN / END).
2. Зафиксировать ключ сервера (known_hosts)¶
Снимите отпечаток с того же хоста и порта, что использует CI:
ssh-keyscan -p 22 ВАШ_СТАТИЧЕСКИЙ_IP
Вывод целиком — в секрет DEPLOY_SSH_KNOWN_HOSTS. Так раннер не согласится на неизвестный хост при смене машины или атаке MITM.
3. Обязательные секреты GitVerse¶
| Секрет | Назначение |
|---|---|
DEPLOY_HOST |
IP или DNS сервера |
DEPLOY_USER |
SSH-пользователь |
DEPLOY_SSH_PRIVATE_KEY |
Приватный ключ CI (см. выше) |
DEPLOY_SSH_KNOWN_HOSTS |
Результат ssh-keyscan |
DEPLOY_PUBLIC_URL |
Публичный базовый URL, например https://shop.example.com (без завершающего /) |
4. Опциональные секреты¶
| Секрет | Назначение |
|---|---|
DEPLOY_SSH_PORT |
Порт SSH, если не 22 |
DEPLOY_PROJECT_DIR |
Каталог клона репозитория на сервере; если не задан — используется /opt/konstructorium |
DEPLOY_GIT_REF |
Ветка/тег для git pull --ff-only (по умолчанию master) |
DEPLOY_DOCKER_USE_SUDO |
Необязательно: always / 1 — всегда sudo -n docker compose; never / 0 — всегда без sudo. Если не задан, скрипт scripts/release/deploy-on-server.sh сам пробует сначала обычный docker, затем sudo -n docker. |
5. Что должно быть настроено на сервере один раз¶
- Клон репозитория с возможностью
git pullс GitVerse (deploy key на чтение или токен вcredential/ HTTPS). - Файл
.envдляdocker-compose.prod.yml(не коммитится; уже у вас есть). - Установлены Docker и Docker Compose v2. Доступ к сокету Docker для пользователя деплоя: либо группа
docker, либо неинтерактивный sudo на бинарник Docker (CI не может ввести пароль). Пример дляsudoers: строка видаdeployuser ALL=(root) NOPASSWD: /usr/bin/docker(путь кdockerпроверьте командойcommand -v docker).
Скрипт на сервере вызывается из репозитория после git pull: scripts/release/deploy-on-server.sh (через bash -s с переменными окружения). Если обычный docker info от имени пользователя деплоя падает с permission denied на сокете, скрипт попробует sudo -n docker info; для этого на сервере должен быть настроен NOPASSWD для docker, иначе задайте пользователя в группу docker и перелогиньтесь, либо вынесите деплой под пользователя с доступом к сокету.
6. Поведение «как у зрелых команд»¶
- Деплой только после зелёного CI (
needsв workflow). - Push в
masterили явный ручной запуск с флагом деплоя (удобно для проверки CD без коммита вmaster). - Отдельный machine / deploy SSH-ключ, не человеческий.
- Pinning ключа хоста через
DEPLOY_SSH_KNOWN_HOSTS. - После деплоя: все контейнеры в
docker-compose.prod.ymlв статусеrunning; внутренние health на127.0.0.1:8001–8007(+analyticsчерезdocker compose exec); публичные проверки/healthи/api/*/health/черезDEPLOY_PUBLIC_URL.
7. GitVerse: gitverse.*, не github.*, и переводы строк¶
В условиях job (например if:) для ветки и типа события используйте gitverse.ref и gitverse.event_name. Контекст github.ref / github.event_name на GitVerse часто пустой, из‑за чего деплой никогда не запускается, хотя push был в master.
Файлы workflow в репозитории должны быть в LF (Unix). Если сохранять YAML с CRLF (Windows по умолчанию), раннер GitVerse может получить job без runs-on и без steps (runs-on key not defined, No steps found). В корне репозитория лежит .gitattributes с правилом eol=lf для .gitverse/workflows/**. После добавления атрибутов выполните пере-checkout или git add --renormalize .gitverse/workflows/.
8. Как протестировать CD¶
- Заполните секреты из разделов 1–3.
- В GitVerse: CI/CD → запуск workflow вручную (workflow_dispatch) → отметьте «Запустить SSH-деплой на прод…» → Run. Пройдут те же тесты, затем при успехе выполнится деплой (удобно с любой ветки, с которой вы запускаете workflow — код на сервере всё равно подтянется по
DEPLOY_GIT_REF/masterв скрипте на сервере). - Либо сделайте обычный merge/push в
masterпосле того, как пайплайн на LF и сgitverse.*попал в репозиторий.
Расширения на будущее (при росте команды): окружение с ручным approval, деплой по тегу, отдельный staging, артефакты в registry вместо build на сервере.