Перейти к содержанию

Непрерывная доставка (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. Заполните секреты из разделов 1–3.
  2. В GitVerse: CI/CD → запуск workflow вручную (workflow_dispatch) → отметьте «Запустить SSH-деплой на прод…»Run. Пройдут те же тесты, затем при успехе выполнится деплой (удобно с любой ветки, с которой вы запускаете workflow — код на сервере всё равно подтянется по DEPLOY_GIT_REF / master в скрипте на сервере).
  3. Либо сделайте обычный merge/push в master после того, как пайплайн на LF и с gitverse.* попал в репозиторий.

Расширения на будущее (при росте команды): окружение с ручным approval, деплой по тегу, отдельный staging, артефакты в registry вместо build на сервере.