Раскатка обновлений Intekey WMS больше не зависит от того, у кого сегодня открыт SSH и кто помнит, какая сборка где стоит. Мы создали оркестратор, который берёт на себя весь цикл: сборку, проверки, раскатку по стендам, точки отката и отчётность. Ниже как он устроен.

Сборка
Оркестратор ведёт два продукта в одном контуре: Intekey WMS (Maven, тонкий jar) и Yard (образ экспортируется из приватного registry в .tar.gz и заливается через docker load).
Сборка всегда идёт из чистого git worktree по origin/<ветка>, ситуация "у меня локально собиралось" здесь невозможна в принципе. Версия и SHA коммита записываются в MANIFEST артефакта: по jar на любом стенде видно, из какого коммита он собран. Дополнительно формируется список коммитов с прошлой сборки, фактически готовые release notes без ручной подготовки.
Собрать можно по ветке, по тегу или по номеру merge request: из UI, через API или из чата.

Раскатка
Выбираешь артефакт, отмечаешь стенды, дальше живой лог по WebSocket в браузере, без захода на сервер.
Для Intekey WMS раскатка выглядит так: SFTP, подмена jar, systemctl restart, ожидание фактического старта логики. Для Yard: чанковая заливка образа, docker load, compose up, health-check.
Есть сборка с автораскаткой: в форме сборки отмечаются стенды, куда артефакт уедет сам при успешной сборке. Работает только для тестовых стендов, на прод так ничего не раскатывается.
Стенды за туннелями доступны через jump-host (ssh -J); ключи, пароли и sudo настраиваются в карточке стенда. Один running-деплой на стенд гарантирован уникальным индексом в БД, параллельные раскатки на один стенд исключены на уровне схемы.

Отложенные раскатки
Формат такой: этот jar на эти стенды в 03:00. Расписание переживает перезапуск деплоера.
Все проверки выполняются в момент запуска задания, а не в момент постановки: валидатор, занятость стенда и доступность реестра проверяются непосредственно ночью. Если деплоер не работал дольше окна допустимого опоздания, просроченное задание помечается как missed и не уезжает утром в рабочее время.
Артефакт, задействованный в запланированном задании, защищён от удаления, как поштучного, так и через очистку старых сборок.

Валидатор прод-раскатки
Раскатка на прод не выполняется по одной кнопке без проверок. Перед раскаткой оркестратор проверяет восемь правил:
# |
Проверка |
V1 |
артефакт собран этим деплоером, а не принесён извне |
V2 |
эта же сборка уже раскатана на тестовый стенд |
V3 |
выдержана soak-пауза после тестовой раскатки |
V4 |
тестовая проверка не устарела |
V5 |
стенд свободен и не заблокирован после неудачного отката |
V6 |
нет дрейфа версии: на стенде то, что записано в реестре |
V7 |
есть точка отката, бэкап и preflight сходятся |
V8 |
ветка сборки разрешена для прода |
Правило можно обойти, но только явным указанием, какое именно, с подтверждением, записью в аудит и уведомлением в корпоративном боте. Стенд с неподтверждённой средой трактуется как прод: лишнее подтверждение обходится дешевле случайной раскатки на боевой контур.

Бэкапы и точка отката
Поддерживаются холодный и горячий бэкап БД. Перед каждым необратимым шагом идёт preflight: место на диске, доступы, параметры базы.
Наборы бэкапов вместе с manifest.json хранятся на самом стенде, откат работает даже при недоступном деплоере. Пароль БД читается со стенда, не попадает в лог задачи и маскируется во всех отчётах.
Ретеншен построен так, чтобы не создать ситуацию без пути назад: автоочистка никогда не удаляет последнюю действующую точку отката, нужный набор можно закрепить (pin).

Автооткат с учётом схемы данных
Оркестратор читает modulesHash Intekey WMS (из _auto или из start.log) до и после раскатки. Если хэш изменился, значит схема мигрировала, и откат одного jar не вернёт данные в прежнее состояние. Если хэш прочитать не удалось, оркестратор считает, что схема изменилась. Это безопасный дефолт.
При восстановлении текущая база переименовывается, а не удаляется. Если старт на старом jar не удался, вторая попытка идёт уже с восстановлением БД. Стенд после неудавшегося отката блокируется до разбора человеком.

Перенос БД между стендами
Дамп идёт потоком: source, деплоер, target, и не сохраняется на диск деплоера, базы клиентов бывают в десятки гигабайт.
Перед стартом оркестратор считает, хватит ли места на приёмнике с учётом коэффициента распаковки, WAL и временных файлов pg_restore, и показывает оценку времени переноса. Без пройденной проверки ресурсов перенос не запускается, нужен токен, который выдаёт только сама проверка.
Направление одностороннее: прод в тест. Накатить бэкап на прод запрещено на трёх независимых уровнях кода.

Состояние стендов
Одна SSH-сессия, и по стенду видно всё: сервисы, свободное место, версия jar, аптайм сервиса и хоста.
Статусов четыре: ? работает, ? с замечаниями, ? не работает, ⚪ не проверен. down и unknown это разные состояния: "мы потеряли связь со стендом" и "стенд лежит" требуют разной реакции.
Кнопка "Состояние всех" показывает сводку по парку стендов с худшим статусом по группе.

Корпоративный бот и DevOps-чат
Команда /devops открывает меню Build / Deploy / Состояние стендов. /build запускает цепочку стенд, ветка, подтверждение. /deploy предлагает готовую сборку из списка. /status all выводит сводку по парку.
Бот распознаёт свободный текст: "обнови сирит тест", "пересобери Гарантис и раскатай", просто "сборка". Он определяет намерение, находит стенд по нескольким десяткам синонимов и алиасов, извлекает ветку из ссылки на MR или tree в GitLab, а при неоднозначности переспрашивает.
Уведомления настраиваются по событиям: старт прод-раскатки, обход правила валидатора, откат, бэкап, перенос БД, результат раскатки со списком коммитов. Раскатка прода из чата по умолчанию выключена.

Реестр релизов и аудит
Всё хранится в PostgreSQL: артефакты, раскатки, наборы бэкапов, переносы БД, журнал аудита. Внутри каждого стенда сквозная нумерация релизов.
Каждое действие с последствиями попадает в audit_log: кто, что, когда и с каким обходом правил. Если реестр недоступен, раскатка на тестовые стенды продолжается с предупреждением в логе, а раскатка на прод блокируется полностью. Инструмент не должен переживать сбой прода из-за сбоя собственной БД.
Логи всех задач хранятся на диске: к любой раскатке месячной давности можно вернуться и прочитать её целиком.

Что изменилось на практике
Раскатка на стенд занимает минуты, а не выделенное окно в календаре инженера.
На прод нельзя вывезти сборку, не прошедшую проверку на тесте, это заблокировано валидатором, а не держится на честном слове.
У каждой раскатки есть точка отката, и оркестратор сам определяет, требуется ли восстановление БД.
Ночные обновления идут без дежурного инженера.
История раскаток лежит в реестре и доступна по запросу, а не восстанавливается из переписки.
Частые вопросы
Чем оркестратор отличается от Jenkins, GitLab CI или Argo CD?
Специфика не в самом деплое, а в связке «деплой + бэкап + определение факта миграции схемы + автооткат с восстановлением данных» для десятков закрытых контуров с собственной БД у каждого клиента — то, что готовые инструменты из коробки не закрывают.
Что такое soak-пауза и зачем она нужна перед прод-раскаткой?
Выдержка новой сборки под нагрузкой в течение времени, чтобы проявились медленно накапливающиеся проблемы: утечки памяти, деградация отклика, заполнение диска логами — то, что короткий тест не успевает показать.
Чем configuration drift опасен для раскатки?
Если фактическое состояние стенда разошлось с тем, что записано в реестре, раскатка поверх такого стенда становится непредсказуемой: неизвестно, с каким реальным состоянием она взаимодействует.
Почему для отката иногда нужно восстанавливать БД, а простого возврата предыдущего jar недостаточно?
Если между версиями была миграция схемы, старый jar рассчитан на другую структуру БД. Возврат кода без возврата данных не восстанавливает прежнее состояние, а создаёт новое, несовместимое.
Чем разнятся статусы стенда down и unknown?
down — подтверждено, что стенд не работает. unknown — с ним потеряна связь, и его реальное состояние неизвестно. Это разные факты, требующие разной реакции.
Что такое break-glass-обход и почему он не запрещён полностью?
Аварийный способ пропустить конкретную проверку валидатора. Не запрещён, потому что иногда нужен, но обставлен так, чтобы использование было явным, подтверждённым и полностью прослеживаемым в аудите.