134 commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4b74356c60 |
fix(metrics): force-recreate alert-ack/tg-relay после up -d — код монтируется с хоста
All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 15s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 12s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
up -d сравнивает описание сервиса, не содержимое бинд-маунта. alert-ack и tg-relay получают app.py именно бинд-маунтом (не сборкой образа), поэтому правка файла не пересоздаёт уже работающий контейнер — он продолжает исполнять старый код в памяти интерпретатора. Подтверждено на проде 12.09.2026: PR #3490 (фикс alert-ack) слился, файл на диске обновился (git reset --hard), а gendesign-alert-ack, запущенный 25 минут назад, отвечал по старой логике. Помог только ручной docker restart. force-recreate для обоих сервисов сделан условным по PROFILES (case ",$PROFILES,"), чтобы не падать на несуществующем контейнере, когда профиль alerts/relay в этом прогоне не включён. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY6iWDnGDthdvsMWgK1BMG |
||
|
|
347342bb5c |
fix(metrics): гасим crash-loop tg-relay пустым секретом через профиль relay
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 13s
CI / openapi-codegen-check (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
PR #3487 добавил сервис tg-relay без profiles: контейнер поднимался всегда и падал в SystemExit на пустом TG_RELAY_SECRET (на проде подтверждён Restarting в бесконечном цикле). - deploy-metrics.yml: TG_RELAY_SECRET прокинут в ssh-action по образцу ALERT_ACK_GLITCHTIP_SECRET; профиль relay включается независимо от alerts, только когда секрет непуст; ::warning на пустом секрете. Сравнение PROFILES с "alerts" переведено на case, иначе комбинация "alerts,relay" сломала бы прежнюю точную строковую проверку. - docker-compose.metrics.yml: tg-relay получил profiles: ["relay"]. - tradein-mvp/docker-compose.prod.yml: комментарий у tgbot — deploy-tradein.yml секреты приложения в CI не инжектит, TELEGRAM_RELAY_BASE_URL и TELEGRAM_RELAY_SECRET на продуктовом хосте заводятся так же, как прочие TELEGRAM_* — строкой в user-managed runtime-файле окружения backend на хосте, без правок workflow (существующий механизм этого файла, см. README-АДМИНУ.md). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JY6iWDnGDthdvsMWgK1BMG |
||
| 127c9a5c2a |
Merge pull request 'Деплой метрик перечитывает конфиг Prometheus, а не только кладёт его на диск' (#3476) from fix/3467-metrics-deploy-reload into main
All checks were successful
Deploy / changes (push) Successful in 11s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy Metrics / server (push) Successful in 32s
Deploy / build-backend (push) Successful in 51s
Deploy / build-worker (push) Successful in 58s
Deploy Metrics / agent-infra (push) Successful in 29s
Deploy Metrics / agent-apps (push) Successful in 31s
Deploy / deploy (push) Successful in 1m18s
Deploy / deploy-status (push) Successful in 2s
Deploy / perimeter-smoke (push) Successful in 1m46s
|
|||
|
|
e7f127bc6e |
chore(ops): маршрут и секрет для резервного приёмника алертов GlitchTip
All checks were successful
CI Trade-In / changes (pull_request) Successful in 13s
CI / changes (pull_request) Successful in 18s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Обвязка к #3482, который добавил сам эндпоинт в alert-ack, но не мог тронуть caddy и workflow: файлы Caddy в тот момент правил параллельный PR #3478. Три вещи: маршрут /glitchtip* на metrics.gendsgn.ru, проброс нового секрета ALERT_ACK_GLITCHTIP_SECRET в окружение деплоя, и предупреждение шага, если секрет пуст. Последнее не косметика: при пустом секрете эндпоинт отвечает 503 на всё, и без предупреждения резервный канал молча не поднялся бы. Секрет намеренно отдельный от продуктового TRADEIN_INTERNAL_AUTH_SECRET — это другой хост и другой домен безопасности. Refs #3471, #3482 |
||
|
|
6febb36afd |
fix(ops): деплой метрик перечитывает конфиг Prometheus, а не только кладёт его на диск
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 3m14s
CI / backend-tests (pull_request) Successful in 19m15s
lastConfigTime у gendesign-prometheus совпадал со startTime контейнера 16 суток: docker compose up -d не пересоздаёт контейнер из-за изменения содержимого бинд-маунта (сравнивается только описание сервиса), а --web.enable-lifecycle был включён, но /-/reload никто не вызывал. Любая правка ops/metrics/prometheus/** доезжала до диска и молча не вступала в силу до случайного рестарта, при зелёном деплое. Добавлен шаг по образцу уже работающей проверки Caddyfile в этом же workflow: promtool check config + promtool check rules внутри контейнера, reload только при успешной проверке, приёмка через сравнение lastConfigTime до/после (обновляется на каждый успешный reload, поэтому надёжно ловит и несостоявшийся вызов). Провал promtool теперь роняет шаг и не трогает работающий Prometheus. Alertmanager уже чинился отдельно (--force-recreate, #3078/#3136) — reload для него намеренно не помогает из-за переиспользуемого инода, это не regressed. Loki (/etc/loki/loki-config.yml), Grafana (provisioning) и Alloy (config.alloy) в том же деплое лежат на дисковых бинд-маунтах без reload — чинить их этим PR не стал, см. summary задачи. Refs #3467, #3471 |
||
|
|
bbdcfeb825 |
ci(#3274): гейт против возврата фронта в общую команду и снятия ретрая (часть 2b/3)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 12s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 1m16s
CI / openapi-codegen-check (pull_request) Successful in 2m5s
CI / backend-tests (pull_request) Successful in 17m28s
Только scripts/ + ci.yml: ни deploy.yml, ни deploy-tradein.yml по этим путям не триггерятся. Мержить ПОСЛЕ частей 1 и 2a — гейт проверяет обе половины и на main без них покраснеет. |
||
| 204e2e09de |
Merge pull request 'fix(deploy): подменять фронт МЕРЫ отдельной командой — окно простоя 30–90 с уходит (#3274, часть 1/2)' (#3442) from fix/3274-part1-deploy-swap into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 13s
Deploy Trade-In / build-browser (push) Successful in 37s
Deploy Trade-In / build-frontend (push) Successful in 2m11s
Deploy Trade-In / test (push) Successful in 4m22s
Deploy Trade-In / build-backend (push) Successful in 34s
Deploy Trade-In / deploy (push) Successful in 6m40s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 1m40s
|
|||
| 134985a624 |
fix(smoke): отказ TLS-сертификата — это FAIL, а не «ответа нет»
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Повтор запроса включался на ЛЮБОМ ненулевом rc curl, хотя собственный комментарий рядом называл сетевой класс (6/28/35/52/56). Протухший, чужой или самоподписанный сертификат даёт rc=60 (замер: expired.badssl.com, self-signed.badssl.com, wrong.host.badssl.com) — и измеренный регресс периметра уезжал в колонку «периметр этой проверкой НЕ проверен», потратив на детерминированный отказ три попытки и 6 c пауз. Ровно этот отказ и есть предмет проверки 5b: без site-блока Caddy не выпускает сертификат. Коды сетевого класса вынесены в NETWORK_RC рядом с комментарием, чтобы описание и поведение не разъезжались; повтор делается только по ним. rc=7 (соединение отвергнуто) добавлен туда же — ответа при нём тоже нет. curl_failed печатает rc в обеих ветках: строки RETRY при SMOKE_ATTEMPTS=1 нет вовсе, и «домена нет» (6) было не отличить от «сертификат протух» (60). timeout-minutes 10 → 40: худший случай (прод не отвечает — мертвы все 43 проверки) = 43 × 53 c ≈ 38 мин, в 10 минут помещалось ~8 мёртвых проверок, и job убивали ДО печати FAIL-строк и итога — в том самом сценарии, ради которого правка и делалась. |
|||
| dacd298b21 |
fix(deploy): подменять фронт МЕРЫ отдельной командой — окно 30–90 с уходит
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m0s
CI / backend-tests (pull_request) Successful in 17m25s
Публичный лендинг meraocenka.ru лежал 30–90 с на КАЖДОМ деплое (#3274). Причина не в скорости подмены контейнера: она стоит полсекунды. `docker compose up -d` со СПИСКОМ сервисов работает в две фазы — сначала create (старый контейнер каждого сервиса останавливается и УДАЛЯЕТСЯ, иначе занято container_name), потом start, в порядке зависимостей и с ожиданием их условий. Между фазами старого фронта уже нет, а новый ещё не запущен. Прод, 10.09, два деплоя подряд (docker inspect .Created/.StartedAt): пачка сервисов: tradein-backend создан 15:01:40 → запущен 15:02:10 (30 с), в логе Caddy три 503 на лендинге: 15:01:46/:52 и 15:02:06; ОДИН сервис: tradein-frontend создан 16:42:17.5 → запущен 16:42:18.0 (0,5 с), 503 в логе нет ни одного. Тот же двухфазный порядок воспроизведён на стенде (реальный образ фронта + Caddy 2): соседи создаются сразу, стартуют через 41 с. Поэтому frontend убран из общего `up -d $SERVICES` и пересоздаётся своей командой после пачки: в его графе один сервис, create и start идут подряд. Остаток ~0,5 с добирает ретрай подключения в Caddy — отдельным коммитом, он мержится своим путём (caddy_only → graceful reload, без пересборки). Проба для замера на живом деплое — scripts/probe-deploy-window.sh: считает коды и САМУЮ ДЛИННУЮ серию не-200 в секундах, 000 отдельной строкой (его даёт и отбой периметра, не только простой). Запускать НА хосте прода: с внешнего адреса частая серия сама ловит 30–50 % 000. Refs #3274 |
|||
| c0e45b48d3 |
fix(smoke): отличать «ответа не было» от «код не тот» в смоуке периметра
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Прогон perimeter-smoke-mera на голове main (
|
|||
|
|
671fef758e |
feat(mera): Метрика и GA4 на публичном контуре + открытие сайта для индексации
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m19s
CI / openapi-codegen-check (pull_request) Successful in 2m6s
CI / backend-tests (pull_request) Successful in 17m40s
ЗАЧЕМ. Статьи МЕРЫ публикуются с UTM-метками, но посмотреть, приходил ли по ним кто-нибудь, было физически нечем: веб-аналитики на публичном контуре не было вовсе. Заодно вскрылось, что «толкнуть в выдаче» тоже нельзя — всё дерево mera-public отдавало `robots: noindex, nofollow`. СЧЁТЧИКИ. Яндекс.Метрика и GA4 подключаются ТОЛЬКО в `mera-public/layout.tsx` и никогда в корневом `app/layout.tsx` — иначе счётчик уехал бы в закрытый контур (/v2, /admin, /scrapers, /history), где анонимных посетителей нет, а приватные маршруты сотрудников есть. Идентификаторы приходят build-time (`NEXT_PUBLIC_YM_ID` / `NEXT_PUBLIC_GA_ID`) — канон Dockerfile'а этого проекта: Next инлайнит NEXT_PUBLIC_* на сборке, runtime env их не подхватит. Пустое значение = тег не рендерится вовсе, никаких `ym(undefined)`. Оба build-arg'а прописаны в ОБОИХ блоках CI, включая retry-сборку без кеша. Вебвизор выключен намеренно. Он пишет ввод в поля, а на `/estimate` человек вводит адрес своей квартиры; раздел 9 политики этого не раскрывает. Включать следует одним заходом с правкой политики и маскировкой полей — в коде рядом записано, что именно понадобится. ЦЕЛИ ВОРОНКИ. Десять целей: клик по CTA, начало ввода адреса, адрес выбран, результат с разбивкой по вердикту (ok/thin/none), ошибка расчёта, ошибка валидации, отказ подсказок, показ платного тизера. Кнопок «Проверить квартиру» восемь штук в разных компонентах, все — обычные `<a>` через PublicLink, поэтому вместо восьми копий onClick один делегированный слушатель на document: девятая кнопка подключится сама. Цель «оплата успешна» НЕ заведена — вызова checkout во фронте нет вовсе, PAYMENTS_ENABLED выключен, страницы возврата не существует; вешать её пока не на что. ИНДЕКСАЦИЯ. Снят noindex со всех публичных страниц, добавлены `app/robots.ts` и `app/mera-public/sitemap.ts`, metadataBase, canonical на КОРОТКИЕ адреса, openGraph и JSON-LD Article на главной статье. robots.txt и sitemap.xml разведены по двум разным handle в Caddy не от хорошей жизни: у Next robots.txt — конвенция корня app/, а sitemap живёт в сегменте маршрута, и формы путей не совпадают. 152-ФЗ. Раздел 9 «Файлы cookie и веб-аналитика» в политике (обработчики названы поимённо — этого требует ч. 3 ст. 6) + уведомляющий, не блокирующий баннер. Гейт «названий площадок в публичной копии быть не должно» получил узкое исключение ровно на аналитические словосочетания в политике; голое «Яндекс» как площадка остаётся запрещённым и там. ПОПУТНЫЙ БАГ (замер на живом проде 10.09.2026). `meraocenka.ru/articles/` с UTM-метками отдавал 301 на адрес БЕЗ query — матчер @meraShortSlash собирал цель из regex-захвата пути и терял параметры. Код ответа при этом оставался 301, поэтому смоук проблему не видел. Мессенджеры и автолинкификаторы дописывают слэш сами, то есть атрибуция терялась именно на трафике по опубликованной ссылке. Починено тем же приёмом, что у соседних матчеров; в смоук добавлена проверка буквального Location. ГЕЙТЫ. `isPublicPath` и периметр-тест узнали про новые машинные адреса; noindex-гейт развёрнут (падает, если флаг вернулся) и расширен на строковую форму `robots: "noindex"`; заведена проверка, что корневых `handle` в site-блоке не появляется без объявления — раньше эту дверь гейт не видел. Проверено: tsc и eslint чисто, `npm run build` проходит, robots.txt и sitemap.xml отдаются по нужным адресам, при пустых ID в HTML нет ни одного обращения к mc.yandex.ru и googletagmanager, `caddy validate` валиден, изоляция mera-public от B2B не нарушена. Два теста LoginPage падают и на нетронутом дереве — не наши. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CiUFZ3rmTNpp3DRajUo8KQ |
||
| c9a9085df6 |
fix(deploy-metrics): пересоздавать alloy после выката конфига, гейт по иноду
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Конфиг Alloy смонтирован бинд-маунтом ОДНОГО файла, а `git reset --hard` в деплое не правит его на месте, а пишет новым инодом. `up -d` сравнивает описание сервиса, содержимое бинд-маунта в сравнение не входит — контейнер не пересоздаётся и продолжает читать прежний, уже удалённый инод. Отказ беззвучный: на диске новый конфиг, деплой зелёный, а фильтрация идёт по старому. Пойман на проде 06.09: на Beget после success-деплоя контейнер держал инод от 26.08, и новый фильтр заработал только после ручного `docker restart gendesign-alloy`. Тот же приём, что у alertmanager в джобе server. Позиции чтения журнала лежат в томе alloy_data и пересоздание переживают. Гейт после подъёма сверяет инод файла на хосте с инодом внутри контейнера: расхождение = деплой красный, а не «зелёный со старым конфигом». |
|||
| 1b1977efa3 |
fix(deploy): правки ревью гейта ПТИЦЫ — таймаут сессии, crash-loop, множественный id (#3324)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m4s
CI / backend-tests (pull_request) Successful in 17m35s
command_timeout: 30m — дефолт appleboy/ssh-action 10m короче worst-case гейта (~17 мин), сессию убило бы посреди диагноза и авария читалась бы обрывом связи. Деградация «нет health-конфига» требовала лишь running дважды: crash-loop с временем жизни больше паузы проходил как стабильный (обе проверки видят running, просто это разные жизни контейнера). Теперь сверяется RestartCount до/после окна 15 с; окно учитывается в счётчике ожидания, иначе таймаут 240 с растянулся бы на ~24 мин и упёрся в command_timeout. cid(): `ps -aq` возвращает несколько id при залежавшемся exited-контейнере → docker inspect падает → пустой статус → ложный красный. tail -n1. worker healthcheck: убран `2>&1` (глушил причину, которую деплой печатает из .State.Health.Log), retries 3→5 — при interval 60s тройка промахов = 3 минуты, столько длится обычный флап Redis, а из unhealthy контейнер сам не выходит. |
|||
| 13c4420d1f |
fix(deploy): гейт ПТИЦЫ читает health worker/beat/frontend, а не только curl backend (#3324)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 12s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m4s
CI / backend-tests (pull_request) Successful in 17m40s
Деплой ПТИЦЫ проверял ровно один признак — `curl backend /health`. Worker и beat не имели healthcheck'а в compose вообще, у frontend была TCP-only проба, которую деплой не читал. Crash-loop воркера, вставший beat и фронт с 500 уезжали зелёным деплоем: признак «прод жив» отсутствовал в старом состоянии ровно так же, как в новом. compose: worker — `celery inspect ping -d celery@$(hostname)` (адресно в ЭТОТ узел, без -d ответил бы любой воркер на брокере); beat — свежесть shelve-файла расписания (на inspect ping beat не отвечает; поминутная beat-задача гарантирует обновление mtime не реже ~3 мин при sync_every=180 с, порог 10 мин = 3× запас). Фиктивной `true`-пробы нет: она повторяла бы State.Running. deploy.yml: после подъёма — ожидание healthy для backend/worker/beat/frontend через docker inspect, HTTP-статус фронта (TCP мало), сверка running-образа с локально скачанным $IMAGE_TAG (приём #2679 из deploy-tradein). Каждая проверка при провале печатает контейнер, статус, healthcheck-лог и хвост логов; итог — явный rc в логе и exit им же. Порядок «миграции до подъёма кода» не тронут, `up -d --wait` не используется намеренно (подъём разбит на несколько up). |
|||
| f31cb56081 |
прод: лендинг ходил в чужой бэкенд — имя сервиса двоится между продуктами
All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m12s
CI / backend-tests (pull_request) Successful in 17m35s
CI Trade-In / changes (pull_request) Successful in 8s
CI / frontend-tests (pull_request) Successful in 1m11s
Публичный лендинг отдавался БЕЗ витрины: без ленты сделок, без строк сверки
«прогноз против факта», без подписи разброса. Страница про точность — без
единого доказательства. Отдавалось 106 КБ вместо 241 КБ.
Причина. ПТИЦА и МЕРА — разные compose-проекты, но оба назвали свой сервис
backend и оба подключены к общей сети gendesign_shared. Изнутри фронта:
backend → 172.18.0.6 (МЕРА) + 172.18.0.9 (ПТИЦА)
tradein-backend → 172.18.0.6
BACKEND_URL=http://backend:8000 уводил серверный рендер в бэкенд ПТИЦЫ, тот
отвечал 401 no authenticated user, и страница рендерилась пустой.
Отказ тихий вдвойне. fetch не бросает — приходит валидный HTTP-ответ, просто
чужой. И имя двоится, поэтому часть перегенераций попадала в правильный адрес:
утром страница была с данными, к обеду без них, и это выглядело случайной
поломкой, а не ошибкой конфигурации.
DATABASE_URL болен тем же: @postgres:5432 мог уйти в базу ПТИЦЫ. Там спасало
лишь несовпадение кредов — отказ вместо тихого чтения не тех данных. Полагаться
на это нельзя: защита держится на том, что у чужой базы нет пользователя с
нашим паролем. Переведён на однозначное имя во всех трёх сервисах.
Гейт check-compose-ambiguous-hosts.py: пересечение имён сервисов обоих compose
и запрет ссылаться на них как на хост. Селфтест по конвенции соседних гейтов —
он провалился дважды на моих же фикстурах (в них не было общего имени, то есть
ловить было нечего), и это ровно то, ради чего селфтест и нужен.
Фальсификация на настоящем файле: возврат backend:8000 даёт точную строку 479,
возврат @postgres — все четыре ссылки.
|
|||
|
|
4e8cf5ab62 |
chore(ci): node 20 отслужил — рантайм фронтов и оба CI-джоба на node 24 LTS
All checks were successful
CI Trade-In / changes (pull_request) Successful in 11s
CI / changes (pull_request) Successful in 13s
CI Trade-In / browser-tests (pull_request) Successful in 1m16s
CI Trade-In / frontend-checks (pull_request) Successful in 1m30s
CI / frontend-tests (pull_request) Successful in 1m23s
CI / openapi-codegen-check (pull_request) Successful in 2m23s
CI Trade-In / backend-tests (pull_request) Successful in 5m47s
CI / backend-tests (pull_request) Successful in 18m12s
Node 20 вышел из поддержки 30.04.2026: security-патчи для него больше не выпускаются, а образ node:20-alpine продолжает собираться и молча уносить это в прод. Node 24 — текущая Active LTS. Меняется ровно major рантайма, больше ничего: frontend/Dockerfile node:20-alpine → node:24-alpine (deps/builder/runner) tradein-mvp/frontend/Dockerfile то же, три стадии .forgejo/workflows/ci.yml node-version "20" → "24" (два джоба) .forgejo/workflows/ci-tradein.yml то же (один джоб) Версия в CI намеренно держится равной major'у из Dockerfile — так было и раньше, комментарии рядом обновлены вместе с числом, чтобы не разошлись. Ни `engines`, ни `.nvmrc` в проекте нет — других мест, где закреплён major, не осталось (проверено grep'ом по Dockerfile/yml/md). Совместимость: next 15.5.24 поддерживает node 20/22/24; sharp 0.35.4 — node ^18.17 || ^20.3 || >=22, prebuild linuxmusl-x64 есть. Приёмка — этот самый CI: джобы фронтов теперь выполняются на node 24, так что зелёный прогон PR и есть доказательство. Локально проверить нечем — на машине node 26, это не тот major. |
||
|
|
192fdbfbf6 |
fix(ops/metrics): тема «метрики» задаётся дефолтом, а не ручным заведением секрета
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m2s
CI / backend-tests (pull_request) Successful in 17m10s
Разделение тем из #3163 зависело от шага «завести секрет руками». Шаг отказал сразу же: 27.08 два прогона деплоя подряд отработали зелёными, напечатали строку про откат — и тема «метрики» осталась пустой, а весь инфраструктурный поток продолжил идти в тему клиентских инцидентов. Номер темы форума секретом не является: в репозитории уже лежат домены, пути на хостах, имена контейнеров и внешние адреса. Ставим 245 значением по умолчанию прямо в деплое; переменная окружения по-прежнему перекрывает — переезд темы или другой чат решается ею, без правки кода. Откат на METRICS_TELEGRAM_TOPIC_ID убран намеренно и запрещён тестом. Он возвращал ровно то состояние, ради ухода от которого всё затевалось, и сообщал об этом строкой в логе прогона, которую никто не читает. Молчаливое «почти правильно» хуже явной поломки. Прогнано в обе стороны: с переменной — тема из окружения, без неё — 245. backend/tests/ops — 86 passed. |
||
|
|
b90872b5d7 |
feat(ops/metrics): инфра-алерты уезжают в тему «метрики», клиенты остаются в «алертах»
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m57s
CI / backend-tests (pull_request) Successful in 17m26s
Форумная группа имеет три темы, но тема «метрики» была пуста: оба прямых получателя Alertmanager — telegram и telegram-heartbeat — брали топик из той же переменной METRICS_TELEGRAM_TOPIC_ID, что и сервис alert-ack. Развести их было нечем, и heartbeat вместе со всем инфраструктурным шумом падал в ленту клиентских инцидентов. Смешанные в одной теме, инфраструктура и клиентский инцидент не равны по срочности и приучают пролистывать обе. Вводится METRICS_TELEGRAM_INFRA_TOPIC_ID для прямых получателей Alertmanager. alert-ack и вебхук GlitchTip остаются на прежней переменной, тема поддержки не тронута. Пока новая переменная не задана, берётся старая — до этого момента поведение ровно прежнее, а не сломанное. Клиентская METRICS_TELEGRAM_TOPIC_LINE убрана целиком: после переезда обоих получателей на инфраструктурную строку шаблон её не содержит, а деплой продолжал бы её собирать и объявлять в envsubst. Тест, закрепляющий сборку такой строки, зеленел бы вечно и мешал бы её убрать. Проверено рендером, а не чтением: при заданной теме telegram и telegram-heartbeat дают 245, telegram-clients уходит вебхуком без темы; при незаданной — поля message_thread_id нет вовсе (пустое значение уронило бы Alertmanager целиком). Логика отката прогнана во всех трёх состояниях переменных. backend/tests/ops — 86 passed. Closes #3163 |
||
|
|
99125b8093 |
fix(ops/metrics): Prometheus не видел ни одного Alertmanager — цель file_sd осталась пустой
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Профиль alerts включили, а файл целей `alertmanager_targets.yml` остался плейсхолдером `[]`. Снаружи всё зелёное: alertmanager и alert-ack Up/healthy, деплой зелёный, в логах ни одной ошибки — при этом `activeAlertmanagers: []` и 1568 уведомлений в `prometheus_notifications_dropped_total`. Горящий с 26.08 `Watchdog` не доехал никуда, как и HostAgentDown с RemoteWriteStalled. Причина в том, что включатель профиля и цель для Prometheus лежали в разных местах: профиль поднимает deploy-metrics.yml по наличию токена и чата, а файл целей правился руками. Разъезд не ловится ничем — `[]` штатен при выключенном профиле, поэтому ни валидация, ни healthcheck, ни лог на него не реагируют. Файл становится производным (`alertmanager_targets.gen.yml`, в .gitignore) и рендерится деплоем тем же условием, что включает профиль: цель при включённых алертах, `[]` при выключенных. Рендер идёт до `up` и пишет усечением на месте, поэтому инод сохраняется и работающий Prometheus подхватывает цель сам — та же ловушка одиночного бинд-маунта, что уже описана в этом workflow у Alertmanager. Пустой список пишется явно, а не удалением файла: несуществующий путь docker подменяет каталогом, и Prometheus не стартует вовсе. Closes #3155 |
||
|
|
4ef8bc818b |
ci(tradein): гейт невалидных индексов — деплой ловил их уже на проде
All checks were successful
CI Trade-In / changes (pull_request) Successful in 7s
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Successful in 59s
CI Trade-In / frontend-checks (pull_request) Successful in 1m5s
CI Trade-In / backend-tests (pull_request) Successful in 4m53s
Оборванный CREATE INDEX CONCURRENTLY оставляет индекс с indisvalid=false: планировщик им не пользуется, ошибки нет, а re-run миграции с IF NOT EXISTS видит его как существующий и молча пропускает. До сих пор это ловил только шаг 3b деплоя — то есть после раскатки на прод, ценой красного деплоя и ручного DROP INDEX CONCURRENTLY в окне. Тот же запрос теперь стоит в CI сразу после сборки схемы из 252 миграций. Проверка в деплое ОСТАЁТСЯ: CI собирает схему с нуля и по построению не может воспроизвести оборванный CIC на живой базе — это разные детекторы, не дубликаты. CI ловит миграцию, которая рождает невалидный индекс из чистой схемы; деплой ловит след аварии на проде. Оба пути проверены на реальной базе (prod tradein-postgres): штатный предикат → invalid=0, гейт зелёный; инвертированный → 358, ветка падения срабатывает и печатает список idx/tbl. Refs #2990 |
||
|
|
5ea05cffa6 |
fix(ops/metrics): правки конфига Alertmanager молча не доезжали до контейнера
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m0s
CI / backend-tests (pull_request) Successful in 17m28s
Пойман на проде 27.08 сразу после мержа #3136. На диске лежал новый конфиг — `webhook_configs` на сервис кнопки подтверждения, — `amtool check-config` его одобрил, деплой зелёный. А контейнер продолжал слать алерты напрямую: на диске: webhook_configs: url http://alert-ack:8080/alertmanager в контейнере: telegram_configs: Конфиг подключён бинд-маунтом ФАЙЛА, а рендер делает `rm` и создаёт файл заново — иначе не перезаписать: после chown он принадлежит 65534 с правами 600, а каталог принадлежит деплой-пользователю. `rm` + создание даёт НОВЫЙ инод, тогда как открытый дескриптор внутри работающего контейнера продолжает смотреть на прежний, уже удалённый. `up -d` контейнер не трогает: он сравнивает описание сервиса, а содержимое бинд-маунта в сравнение не входит. Отказ беззвучный — ни одного красного признака нигде. Значит и все прежние правки маршрутизации применялись лишь тогда, когда контейнер пересоздавался по совпадению. Перезагрузка по SIGHUP/API не лечит: она перечитывает тот же открытый инод. Лечит только пересоздание контейнера — его и добавляю, под флагом, который выставляется ПОСЛЕ успешной проверки конфига. Порядок важен: при обратном битый конфиг убивал бы работающий Alertmanager вместо того, чтобы оставить прежний работать. Прод уже приведён в соответствие вручную — контейнер пересоздан, маршрут клиентских инцидентов теперь идёт через кнопку. Эта правка нужна, чтобы следующая правка конфига доехала сама. Три теста: пересоздание есть, оно закрыто проверкой флага (безусловное рвало бы доставку на каждом деплое метрик), флаг выставляется после проверки. Прогон: 78 ops-тестов зелёные, ruff чист. |
||
|
|
6f120c6605 |
feat(observability): клиентский инцидент зовёт дежурного поимённо + чинит сломанное продолжение команды (#3078)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m59s
CI / backend-tests (pull_request) Successful in 17m26s
Две вещи, вторая — исправление собственной ошибки из #3127. ## Дежурного зовут по имени 27.08 продукты лежали 10 часов, и в канале «диск занят на 86 %» и «клиенты не могут открыть сайт» выглядели одинаково. Появился отдельный маршрут: severity=critical И host=apps, то есть критично на ПРОДУКТОВОЙ машине — значит людям недоступна МЕРА и Site Finder, а не «где-то в инфраструктуре тесно». У такого сообщения другой текст (🚨 КЛИЕНТЫ ЗАТРОНУТЫ), упоминание дежурного и repeat_interval 30 минут против 3 часов у прочего критичного: пока инцидент не погашен, напоминание должно быть неудобным. Сужение по host=apps существенно. Без него дежурного звали бы на каждую инфраструктурную мелочь, и тег перестал бы что-либо значить за неделю. Сам аккаунт в репозиторий не попадает — берётся из METRICS_TELEGRAM_ONCALL. Дежурный меняется, конфиг в git — нет. Пустая переменная = сообщение без тега, поведение не ломается. ## Починка: комментарий внутри продолжения команды В #3127 блок rm -f вместе с комментарием встал МЕЖДУ строками, каждая из которых заканчивалась обратным слешем. Строки склеиваются, и весь вызов envsubst уехал в комментарий — конфиг Alertmanager перестал бы рендериться вовсе, при полностью зелёном деплое. Синтаксически это корректный шелл, bash -n такое не ловит, а в диффе не видно: строки выглядят как отдельные. Поэтому проверка структурная и применяется ко ВСЕМ shell-блокам workflow, а не только к месту ожога. |
||
|
|
630f3e6e76 |
fix(observability): конфиг Alertmanager читается контейнером — гейт падал на своих же правах (#3078)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Как только канал алертов реально включился (#3126), профиль alerts впервые дошёл до проверки конфига — и деплой встал: amtool: error: failed to validate 1 file(s) Checking '/tmp/am.yml' FAILED: open /tmp/am.yml: permission denied Отрендеренный конфиг пишется с правами 600 и принадлежит деплой-пользователю, а и amtool, и сам Alertmanager в образе prom/alertmanager работают под nobody (65534). Прочитать чужой файл 600 они не могут. Проверка падала не на содержимом конфига, а на доступе к нему — и контейнер после подъёма упал бы ровно там же. Дефект не поймали раньше по понятной причине: без токена профиль alerts не включался, и эта ветка не исполнялась НИ РАЗУ с момента появления гейта в #3111. Проверка, которая никогда не запускалась, ничем не отличается от отсутствующей — это ровно тот класс тихой поломки, ради которого весь стек и заводится. Права не ослабляем: в файле лежит токен бота. Вместо chmod 644 (который внёс бы токен в список файлов, читаемых любым локальным пользователем машины) отдаём файл во владение 65534 одноразовым контейнером от root — passwordless sudo на хосте нет, а бинд-маунт правит host-инод напрямую. Доступ остаётся ровно у того, кто конфиг читает. Следствие, которое легко проглядеть: после смены владельца `>` в этот файл на следующем деплое уже не запишет, поэтому добавлен rm перед рендером — каталог принадлежит деплой-пользователю, пересоздать файл он может. |
||
| 70db090813 |
Merge pull request 'feat(ops): сторож расхождения «прод ↔ main» — недоехавший деплой перестаёт быть молчаливым (#3029)' (#3125) from chore/3029-deploy-drift-guard into main
All checks were successful
deploy-drift / drift (push) Successful in 8s
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Successful in 35s
Deploy / build-worker (push) Successful in 37s
Deploy / deploy (push) Successful in 1m1s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 10s
|
|||
|
|
30a21abfa7 |
feat(observability): токен алертов приходит из секретов Actions, а не только с машины (#3078)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Стек наблюдаемости был готов ещё вчера, но Alertmanager не поднимался: профиль alerts включается, только когда заданы METRICS_TELEGRAM_BOT_TOKEN и METRICS_TELEGRAM_CHAT_ID, а читались они ИСКЛЮЧИТЕЛЬНО из файла окружения на инфраструктурной машине. То есть включить алерты можно было только правкой прод-файла руками по ssh — в обход репозитория, без следа в истории и без возможности сделать это из CI. Именно это и держало задачу открытой дольше нужного. Цена промедления измерена: 27.08 продукты лежали 10 часов, и ни одно звено оповещения не сработало (#3119); в тот же день сутки не доезжал деплой, и об этом тоже никто не узнал (#3029). Теперь три переменные форвардятся в ssh-шаг из секретов Actions. Порядок разрешения сохранён осознанно: инжектированные значения ставятся ДО того, как скрипт подхватит окружение машины, поэтому хост, если ключи заданы на нём, переопределяет секреты — последнее слово остаётся за машиной, а секреты работают как разумный дефолт. Канал проверен вживую: бот MERAsupport_bot, форум «МЕРА», тема «алерты» (message_thread_id=158) — пробное сообщение доставлено. |
||
|
|
de56b8ae01 |
feat(ops): сторож расхождения «прод ↔ main» — молчаливый недоехавший деплой становится видимым (#3029)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m8s
CI / backend-tests (pull_request) Successful in 17m30s
27.08 прод сутки жил на позавчерашнем коммите, и это нашлось только руками. Замена IP сервера (#3110) осиротила секрет DEPLOY_HOST: deploy.yml падал на `dial tcp ***:***: i/o timeout`, при этом CI оставался зелёным, PR продолжали мержиться, а deploy-infra.yml исправно обновлял Beget и создавал впечатление, что всё в порядке. Проверок, которые спрашивают не «прошёл ли прогон», а «доехал ли код», не было ни одной. Этот сторож — ровно такая: ежечасно читает HEAD с прод-хоста и сверяет с tip main. Три исхода вместо двух. «Хост не ответил» (2) отделён от «на хосте не тот код» (1) — это разные аварии с разной первой командой в разборе, и сегодня погорели именно на их смешении: недоступность выглядела как обычный красный прогон. Льготный период 30 минут гасит ложную тревогу на деплое, который ещё в полёте: ежечасный сторож неизбежно попадёт в окно между мержем и концом выката, а сторож, которого научились игнорировать, хуже отсутствующего. Логика вынесена в scripts/check-deploy-drift.sh и не ходит по сети — SSH живёт в workflow, где секреты. Благодаря этому тест ИСПОЛНЯЕТ настоящий скрипт, а не пересказывает его: ошибка в самом bash видна только при запуске. Read-only: один ssh и git rev-parse, ничего не деплоит. |
||
|
|
efaab2efda |
chore(ops): адрес Poincare — 188.124.37.140 вместо заменённого 188.246.224.93 (#3110)
All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 7s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
CI / openapi-codegen-check (pull_request) Successful in 1m58s
CI / backend-tests (pull_request) Successful in 17m16s
Selectel заменил адрес сервера в ночь на 27.08 по нашей заявке: старый 188.246.224.93 фильтровался российскими операторами и не открывался ни с домашнего интернета, ни с мобильного (#3110). Новый адрес фильтрации не имеет — проверено с машины владельца после переключения DNS. Замена уронила сервер на 10 часов: адрес на порте сменился, а в ОС остался прежний (разбор и восстановление — #3119). Здесь только то, что осталось в репозитории. Единственное функциональное вхождение — дефолт HOST_IP в ops/selectel-ci-access.sh: скрипт открывает раннеру доступ на прод-хост, и с прежним значением он молча настроил бы доступ на адрес, которого у нас больше нет. Остальные семь — тексты комментариев в Caddyfile-секциях, compose, bootstrap-скриптах и раннбуке крона; они не исполняются, но именно по ним сверяются при переезде, и разошедшийся адрес в них дороже, чем кажется. |
||
|
|
5b7ef161e3 |
feat(observability): алерты адресуются в топик форумной группы (#3078)
All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 10s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m2s
CI / backend-tests (pull_request) Successful in 17m24s
Бот, которым шлются тревоги, — тот же, что пересылает сообщения поддержки, а
его чат форумный. Без message_thread_id Alertmanager кладёт тревоги в общую
тему, вперемешку с клиентской перепиской.
Поле поддерживается: проверено amtool check-config на том же образе, что
поднимается в проде (prom/alertmanager:v0.28.0). Схема Alertmanager строгая и
неизвестные поля отвергает, так что успешная проверка означает именно
поддержку, а не молчаливое игнорирование.
Подставляется ЦЕЛАЯ СТРОКА, а не значение: envsubst не умеет условий, и при
шаблоне вида `message_thread_id: ${TOPIC_ID}` незаданный топик дал бы
`message_thread_id:` без значения. Это не деградация - Alertmanager с таким
конфигом не стартует вовсе, то есть алертинг исчезает целиком. Деплой
формирует либо всю строку с отступом, либо пустую.
Топик необязателен: без него поле отсутствует, алерты уходят в общую тему,
поведение прежнее.
Попутно добавлена проверка конфига через amtool ДО подъёма стека - по образцу
`caddy validate` ниже в этом же файле. amtool берётся из того же образа, что и
сам Alertmanager, иначе проверялась бы не та версия схемы. Битый конфиг теперь
роняет деплой громко, а не выключает алертинг тихо.
Тесты (4) рендерят шаблон обоими способами и разбирают результат как YAML -
проверяется фактический конфиг, а не наличие нужных слов в тексте. Отдельно
проверено, что переменная объявлена в списке envsubst: забыть её - значит
оставить в конфиге литерал плейсхолдера.
Фальсификация: на исходных файлах краснеют 3 из 4; проходит только тест,
фиксирующий сохранённое поведение при незаданном топике. tests/ops целиком -
35 passed.
|
||
|
|
beafe6925b |
fix(observability): агент не падает из-за переменной чужой роли (#3078)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 1m55s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Successful in 17m25s
Джоба agent-apps упала целиком:
error while interpolating services.postgres-exporter-infra.environment.
DATA_SOURCE_NAME: required variable INFRA_EXPORTER_DSN is missing a value
INFRA_EXPORTER_DSN нужен экспортеру с profiles: ["infra"], который на
продуктовом хосте не поднимается вовсе. Но compose интерполирует ВЕСЬ файл
до фильтрации по профилям, поэтому `${VAR:?}` роняет команду из-за чужой
переменной. Вместе с агентом не поднялись alloy, node-exporter и cadvisor,
которым никакой DSN не нужен. Симметрично упал бы и инфраструктурный агент -
на двух продуктовых переменных.
Второй дефект в той же цепочке: GENDESIGN_EXPORTER_DSN тоже отсутствовал.
setup-metrics-exporter-dsn.sh читает только runtime-файл окружения бэкенда, а
DATABASE_URL и TRADEIN_DATABASE_URL живут в основном. Значит подстановка
всегда была пустой, add_key печатал "нечем заполнить" и выходил с кодом 0 -
мягкий пропуск встречался с жёстким требованием compose.
Стало:
- compose: `:-` вместо `:?` у трёх DSN. Интерполяция больше не может упасть.
- deploy-metrics.yml: профиль экспортеров включается, только если нужные ЭТОЙ
роли DSN заполнены; иначе ::warning и агент поднимается без экспортера.
Громкость не убрана, а перенесена туда, где роль известна. Тот же приём, что
уже применён к Alertmanager в джобе server.
- setup-metrics-exporter-dsn.sh: читает оба файла окружения (базовый, затем
runtime - он перекрывает). Пишет по-прежнему только в runtime, лишних копий
пароля не заводит.
Почему `:-` не ослабление: пустой DATA_SOURCE_NAME поднял бы экспортер,
который молча не отдаёт метрик, - ровно тот тихий отказ, ради которого весь
стек и заводится. Поэтому пустой DSN теперь означает "профиль не включаем",
а не "поднимаем пустым".
Известное следствие, отмеченное в коде: INFRA_EXPORTER_DSN не собирает никто -
скрипт знает только про GENDESIGN_/TRADEIN_ и работает на продуктовом хосте.
Пока это так, инфраструктурный агент будет честно предупреждать, что метрик
Postgres инфры нет, вместо того чтобы падать целиком.
Тесты (3) структурные, проверяют оба конца инварианта: обязательности не
вернулись в compose; каждая DSN-переменная проверяется в деплое; профили не
захардкожены. Фальсификация: на исходных файлах краснеют все три.
|
||
| 1da2eee142 |
Merge pull request 'fix(observability): стек не поднимался — привилегированную роль спрашиваем у контейнера, а не угадываем (#3078)' (#3105) from fix/3078-metrics-role-discovery into main
Some checks failed
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy Metrics / server (push) Failing after 26s
Deploy Metrics / agent-apps (push) Has been skipped
Deploy Metrics / agent-infra (push) Has been skipped
Deploy / build-backend (push) Successful in 37s
Deploy / build-worker (push) Successful in 40s
Deploy / deploy (push) Successful in 1m4s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 10s
Reviewed-on: #3105 |
|||
|
|
33bc7e4acf |
fix(observability): привилегированную роль спрашиваем у контейнера, а не угадываем (#3078)
All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 12s
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m2s
CI / backend-tests (pull_request) Successful in 17m21s
Стек наблюдаемости не поднялся ни на одном хосте после мержа #3099: джоба server упала, agent-apps и agent-infra пропустились как зависимые. Причина (задача 23657, 26.08 08:55): err: ОШИБКА: не нашёл роль с правом CREATE ROLE в gendesign-infra-postgres setup-metrics-grafana-role.sh искал привилегированную роль перебором трёх имён - glitchtip, forgejo, postgres. Ни одно не совпадает ни с одним реальным кластером проекта: infra-postgres -> infra, gendesign-postgres-1 -> gendesign, tradein-postgres -> tradein. Комментарий над перебором сам предупреждал, что "угадывать postgres неверно", и дальше шло угадывание. Замер на живом контейнере 26.08 (read-only, ничего не создавалось): POSTGRES_USER изнутри контейнера: infra glitchtip - отказ, forgejo - отказ, postgres - отказ, infra - 1 Стало: имя берём из POSTGRES_USER самого контейнера - это та переменная, которой роль и создана при initdb, то есть источник истины. Прежний список оставлен ПОСЛЕ него запасным путём для кластера не из образа postgres. Попутно - глоб в paths деплоя. Воркфлоу запускает ТРИ setup-скрипта, а в триггере стоял только setup-metrics-secrets.sh: правка двух остальных не заводила выкат, и на хосте молча оставалась старая версия. Тот же класс, что #2203 закрыл глобом ops/*.sh. Добавлен тест, который сверяет запускаемые скрипты с шаблонами paths - на исходном воркфлоу он краснеет, указывая на setup-metrics-exporter-dsn.sh. Тесты (6) исполняют РЕАЛЬНЫЙ скрипт с подставным docker и проверяют фактический выбор роли, а не наличие правильных слов в комментарии. Фальсификация: на исходном коде краснеют 3 из 5 ролевых тестов; проходят только те два, что фиксируют сохранённое поведение (запасной перебор и громкая ошибка при отсутствии привилегий). tests/ops целиком - 28 passed. |
||
|
|
46b42c80db |
ci(caddy): гард — import обязан быть покрыт volume-маунтом
All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 10s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 1m10s
CI / openapi-codegen-check (pull_request) Successful in 2m18s
CI / backend-tests (pull_request) Successful in 17m41s
Follow-up к #3103. Прод лёг на ~30 минут потому, что PR завёл `import ../metrics-*.caddy.snippet` в caddy/sites/infra.caddy, но не добавил bind-монты этих файлов в docker-compose.prod.yml. Соседний гард `caddy validate` эту дыру не ловит принципиально: он копирует каталог caddy/ целиком (`docker cp caddy ...`), а на проде смонтированы только отдельные файлы плюс два каталога. Расхождение между «что лежит в репозитории» и «что реально видит контейнер» видно только если сверять с маунтами. check-caddy-snippet-mounts.py разбирает bind-монты сервиса caddy:, резолвит каждый `import` в Caddyfile / caddy/sites/*.caddy / caddy/*.caddy.snippet относительно КОНТЕЙНЕРНОГО пути импортирующего файла и падает, если цель не покрыта ни одним маунтом. Именованные сниппеты `(name) { }` пропускаются, для glob/placeholder-импортов (`caddy/sites/{$CADDY_SITES:*}.caddy`) проверяется каталог. --selftest воспроизводит ровно баг #3102. |
||
|
|
309d273f3f |
feat(observability): стек метрик и логов — Prometheus, Loki, Grafana, агенты на обоих хостах
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 9s
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
Метрик в проекте не было ни одной: ни экспортеров, ни /metrics в бэкендах, единственный канал наблюдения — journald, единственный сигнал об аварии — исключение в GlitchTip. Из-за этого целый класс отказов невидим в принципе: задача рапортует done, строк ноль, исключения нет. Так протухли данные на семь месяцев (#2998), 34 дня был мёртв house_imv_backfill (#2698), 8 суток писал ноль newbuilding_enrich (#2767), 91 день копилось раздутие listings (#2992). Grafana не заменяет GlitchTip: ошибки остаются там. Grafana OSS не принимает Sentry DSN ни одним компонентом, а скрубберы в before_send — требование 152-ФЗ. Здесь появляется другой класс данных: ряды и алерты по трендам. Наблюдатель поставлен у ДРУГОГО провайдера, чем наблюдаемое: серверная сторона на Beget, рядом с GlitchTip. Если ляжет Poincare, мониторинг должен об этом сказать, а не лечь вместе с ним. Транспорт push, а не pull: агент на Poincare шлёт remote_write и логи исходящим HTTPS, поэтому там не открывается ни одного входящего порта сверх 22/80/443. При обрыве канала Alloy копит в WAL и досылает — pull-скрейп в той же ситуации терял бы точки именно в аварии, ради которой мониторинг и нужен. Два контура доступа с разными учётками. Пароль приёмника по построению лежит открытым на продуктовом хосте, значит его компрометация неизбежна вместе с хостом; будь это учётка витрины, утёк бы и доступ к дашбордам. GlitchTip читается прямым SQL, а не Sentry-плагином: у плагина на 6.1.6 stats_v2 отдаёт 500 (баг GlitchTip #381), Events/Discover — 404 (#416), а в grafana/sentry-datasource слово glitchtip не встречается ни разу. Схема сверена на живой базе: колонка времени называется timestamp, а не received, и отдельной таблицы IssueIndex не существует — агрегаты лежат на самой issue_events_issue. Алерты за профилем alerts: канал доставки — открытый вопрос #3078, и стек не должен на нём стоять. Деплой предупреждает, что уведомлять пока некому. Каждая настройка, способная отказать молча, закрыта явно: ретенция Prometheus задана и по времени и по размеру, retention_enabled у компактора Loki (без него retention_period не работает вовсе), путь к журналу и запуск Alloy от root (иначе агент читает ноль записей без ошибки), проверка Caddy до перезагрузки (на этом хосте тот же Caddy держит git, errors и obsidian). Refs #3078 |
||
| 729e9acc52 |
fix(tradein/deploy): подключить selectel-оверрайд — иначе после переезда бот умрёт молча (#3093)
All checks were successful
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-frontend (push) Successful in 2m42s
Deploy Trade-In / build-browser (push) Successful in 3m16s
Deploy Trade-In / deploy (push) Successful in 3m15s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 9s
Deploy Trade-In / test (push) Successful in 3m52s
Deploy Trade-In / build-backend (push) Successful in 34s
|
|||
| bffec49434 |
feat(ops): у волта Obsidian появился автоматический бэкап (#3090)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy Infra Host / sync-infra-host (push) Successful in 4s
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy / deploy (push) Successful in 1m35s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 9s
|
|||
| de157b1024 |
fix(ci): стек CouchDB после переезда остаётся на своём хосте (#3087)
All checks were successful
Deploy Obsidian / deploy-obsidian (push) Successful in 1m52s
|
|||
| 17d23cfaae |
chore(ci): деплой не убивает worker посреди скрап-прогона (#3084)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-worker (push) Successful in 43s
Deploy / build-backend (push) Successful in 44s
Deploy / build-frontend (push) Successful in 42s
Deploy / deploy (push) Successful in 1m41s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 9s
|
|||
| 536137d460 |
feat(ci): деплой проверяет, к тому ли хосту подключился (#3079)
All checks were successful
Deploy Infra Host / sync-infra-host (push) Successful in 2s
Deploy / changes (push) Successful in 9s
Deploy Trade-In / changes (push) Successful in 12s
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Successful in 52s
Deploy / build-worker (push) Successful in 52s
Deploy / build-frontend (push) Successful in 52s
Deploy Trade-In / build-browser (push) Successful in 41s
Deploy Obsidian / deploy-obsidian (push) Successful in 2m15s
Deploy / deploy (push) Successful in 1m53s
Deploy Trade-In / build-frontend (push) Successful in 2m44s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 12s
Deploy Trade-In / test (push) Successful in 4m8s
Deploy Trade-In / build-backend (push) Successful in 47s
Deploy Trade-In / deploy (push) Successful in 1m42s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 9s
|
|||
| be2e07d9c3 |
feat(ops): лёгкий Postgres на Beget под forgejo и glitchtip (#3080)
All checks were successful
Deploy Infra Host / sync-infra-host (push) Successful in 2s
Deploy / changes (push) Successful in 7s
Deploy / deploy-caddy (push) Has been skipped
Deploy / perimeter-smoke (push) Successful in 10s
Deploy / build-backend (push) Successful in 50s
Deploy / build-frontend (push) Successful in 51s
Deploy / build-worker (push) Successful in 53s
Deploy / deploy (push) Successful in 1m43s
Deploy / deploy-status (push) Successful in 1s
|
|||
| 0ba52e55db |
chore(ops): развести crontab по хостам под переезд (#3072)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-frontend (push) Successful in 41s
Deploy / build-backend (push) Successful in 43s
Deploy / build-worker (push) Successful in 45s
Deploy / deploy (push) Successful in 1m32s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 9s
|
|||
| 01128e6331 |
chore(ci): синхронизировать /opt/gendesign на остающемся хосте (#3071)
All checks were successful
Deploy Infra Host / sync-infra-host (push) Successful in 2s
|
|||
|
|
4cb8f32dcc |
Merge remote-tracking branch 'forgejo/main' into fix/2990-clean-start-initdb
All checks were successful
CI / changes (pull_request) Successful in 10s
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 9s
CI Trade-In / browser-tests (pull_request) Successful in 57s
CI Trade-In / frontend-checks (pull_request) Successful in 1m40s
CI / openapi-codegen-check (pull_request) Successful in 2m45s
CI Trade-In / backend-tests (pull_request) Successful in 5m15s
CI / backend-tests (pull_request) Successful in 18m13s
|
||
|
|
a3ccbbd045 |
fix(db/ci): 077 гардится по USER MAPPING, деплой ждёт готовности БД по TCP
Deep-review BLOCK на PR #3011: обе правки чинили заявленный симптом только частично. 077: гард считал pending-строки по source='rosreestr' AND dedup_hash ~ md5-паттерн и пропускал backfill, только если таких строк 0. На чистой БД они есть — 003_seed_deals.sql сеет синтетические сделки с тем же паттерном, значит pending > 0 уже на пустом томе, и миграция всё равно падала на "user mapping not found" (воспроизведено в CI run 8257). Первичный гард теперь проверяет напрямую наличие USER MAPPING для gendesign_remote (идиома из app/core/fdw.py:57-62), счётчик pending оставлен вторым — экономит обращение к FDW, когда мигрировать уже нечего. deploy-tradein.yml: цикл ожидания готовности postgres ходил по unix-сокету (pg_isready без -h). На пустом томе временный init-сервер отвечает на сокете, пока docker-entrypoint-initdb.d ещё прогоняет цепочку миграций — проба зеленела посреди initdb. Добавлен -h 127.0.0.1 (тот же приём уже есть в ci-tradein.yml:157) — TCP открывается только после полного завершения initdb.d. Отдельно ужесточён sentinel baseline-детекции: раньше «схема уже накачена» проверялась одной таблицей listings (миграция 002, почти голова цепочки). Если бы гонка готовности когда-нибудь вернулась, listings был бы уже создан, а хвост цепочки — ещё нет, и baseline тихо пометил бы недостающие миграции применёнными без прогона. Теперь проверяются оба конца — listings (голова) и houses_geog_gist_idx, индекс из миграции 270 (хвост); при несовпадении (ровно один конец на месте) деплой падает громко с explicit ошибкой вместо угадывания. |
||
| f2945b7157 |
fix(ci): деплой падает громко, если :latest отстаёт от головы по компоненту (#2950) (#3023)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy Trade-In / changes (push) Successful in 15s
Deploy / deploy-caddy (push) Has been skipped
Deploy Trade-In / build-browser (push) Successful in 57s
Deploy / build-backend (push) Successful in 1m2s
Deploy / build-frontend (push) Successful in 1m8s
Deploy / build-worker (push) Successful in 1m9s
Deploy / deploy (push) Successful in 1m58s
Deploy / deploy-status (push) Successful in 3s
Deploy Trade-In / build-frontend (push) Successful in 3m14s
Deploy / perimeter-smoke (push) Successful in 14s
Deploy Trade-In / test (push) Successful in 4m12s
Deploy Trade-In / build-backend (push) Successful in 33s
Deploy Trade-In / deploy (push) Successful in 2m16s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 9s
|
|||
| 95db3f44c8 |
fix(ops): бэкапы — +x на deploy-скриптах при деплое tradein, тихий s3 cp (#3005) (#3019)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Has been skipped
Deploy / deploy-caddy (push) Has been skipped
Deploy Trade-In / changes (push) Successful in 13s
Deploy Trade-In / build-browser (push) Successful in 41s
Deploy / deploy (push) Successful in 1m38s
Deploy / deploy-status (push) Successful in 2s
Deploy / perimeter-smoke (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Successful in 2m38s
Deploy Trade-In / test (push) Successful in 3m47s
Deploy Trade-In / build-backend (push) Successful in 34s
Deploy Trade-In / deploy (push) Successful in 1m38s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 9s
|
|||
|
|
efc965a257 |
fix(db/ci): чистый старт БД больше не падает на 077 и не может уехать на пустой схеме
Some checks failed
CI Trade-In / changes (pull_request) Successful in 9s
CI / changes (pull_request) Successful in 10s
CI Trade-In / backend-tests (pull_request) Failing after 55s
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Successful in 1m3s
CI Trade-In / frontend-checks (pull_request) Successful in 1m47s
CI / openapi-codegen-check (pull_request) Successful in 2m26s
CI / backend-tests (pull_request) Successful in 17m51s
Блокер переезда (#2990). Чистый старт на пустом томе падал: 077 читает foreign table gendesign_rosreestr_deals, а USER MAPPING создаёт бэкенд при старте (app/core/fdw.py), то есть ПОСЛЕ docker-entrypoint-initdb.d. Контейнер не поднимался вообще. Путь «пустой том» на реальном железе не исполнялся ни разу, а CI этот файл явно пропускал — гейт, который должен был поймать, был ослаблен. Проверено по всем 14 миграциям, упоминающим FDW-таблицы: читает ровно одна — 077. Остальные только CREATE/DROP FOREIGN TABLE и COMMENT, им ни USER MAPPING, ни связь с чужой БД не нужны. 077 не удалена, а сделана самозащитной: гард считает строки в md5-форме и выходит раньше обращения к FDW, если мигрировать нечего. На чистой БД таких строк нет по определению. Удаление файла было бы неверным — прод помнит миграции по bare-filename в _schema_migrations, и test_applied_migration_is_not_renamed_or_deleted падает на удалении. Исключение в ci-tradein.yml снято: теперь цепочка применяется целиком, то есть CI сам стал репетицией чистого старта. Отдельно закрыт тихий отказ в deploy-tradein.yml. Ветка baseline срабатывала по одному лишь отсутствию _schema_migrations, а это состояние неоднозначно: так выглядит и наполненный прод до внедрения tracking, и пустая БД нового сервера. Во втором случае baseline пометил бы все миграции применёнными, ни одной не прогнав, и деплой уехал бы зелёным на пустой схеме. Добавлен sentinel по listings: пусто → baseline пропускается, цепочка применяется с нуля. Refs #2990, #2989 |
||
|
|
2d2336cd51 |
fix(ops): деплой триггерится на любой ops/*.sh, а не только docker-prune.sh (#2203)
All checks were successful
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 9s
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 8s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m6s
CI / backend-tests (pull_request) Successful in 17m11s
paths-filter в deploy.yml знал только про ops/docker-prune.sh (#2887) — правка ops/backup.sh или новый ops/restore-drill.sh из этого же PR не долетели бы до /opt/gendesign: деплой не триггерится -> git reset --hard origin/main не исполняется -> cron на VM месяцами крутит старую версию, молча. Точечный список сам по себе и есть баг: #2887 добавил только тот файл, о котором тогда шла речь, и следующий новый ops-скрипт (backup.sh) остался за бортом. Глоб ops/*.sh закрывает класс целиком — не матчит подпути (ops/db-bootstrap/**, ops/glitchtip-auth-forwarder/**), у них свои explicit триггеры уже есть, дублирования нет. |
||
| 68d041022d |
fix(ci): ожидание докер-лока оставляет след в логе (#2950) (#2958)
Some checks are pending
Deploy / changes (push) Waiting to run
Deploy / build-backend (push) Blocked by required conditions
Deploy / build-worker (push) Blocked by required conditions
Deploy / build-frontend (push) Blocked by required conditions
Deploy / deploy (push) Blocked by required conditions
Deploy / deploy-caddy (push) Blocked by required conditions
Deploy / perimeter-smoke (push) Blocked by required conditions
Deploy / deploy-status (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-browser (push) Successful in 50s
Deploy Trade-In / build-frontend (push) Successful in 2m58s
Deploy Trade-In / test (push) Successful in 3m53s
Deploy Trade-In / build-backend (push) Successful in 32s
Deploy Trade-In / deploy (push) Successful in 1m53s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 8s
|
|||
| feff8214f7 |
fix(ci): докер-секции прод-деплоев исключают друг друга через host-lock (#2950) (#2955)
All checks were successful
Deploy / changes (push) Successful in 9s
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-browser (push) Successful in 48s
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-backend (push) Successful in 47s
Deploy / build-frontend (push) Successful in 49s
Deploy / build-worker (push) Successful in 49s
Deploy / deploy (push) Successful in 1m26s
Deploy / deploy-status (push) Successful in 3s
Deploy / perimeter-smoke (push) Successful in 13s
Deploy Trade-In / build-frontend (push) Successful in 2m59s
Deploy Trade-In / test (push) Successful in 3m52s
Deploy Trade-In / build-backend (push) Successful in 37s
Deploy Trade-In / deploy (push) Successful in 2m22s
Deploy Trade-In / deploy-status (push) Successful in 1s
Deploy Trade-In / perimeter-smoke (push) Successful in 10s
|
|||
| 2a01dea103 |
fix(ci): прод-деплои в одну группу concurrency — прун одного убивал pull другого (#2950) (#2952)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy Trade-In / changes (push) Successful in 10s
Deploy / deploy-caddy (push) Has been skipped
Deploy / build-worker (push) Successful in 51s
Deploy / build-backend (push) Successful in 52s
Deploy / build-frontend (push) Successful in 51s
Deploy Trade-In / build-browser (push) Successful in 32s
Deploy / deploy (push) Successful in 1m21s
Deploy / deploy-status (push) Successful in 1s
Deploy / perimeter-smoke (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Successful in 3m30s
Deploy Trade-In / test (push) Successful in 4m15s
Deploy Trade-In / build-backend (push) Successful in 31s
Deploy Trade-In / deploy (push) Successful in 2m6s
Deploy Trade-In / deploy-status (push) Successful in 2s
Deploy Trade-In / perimeter-smoke (push) Successful in 11s
|