CI-шторм 2026-06-17 ~18:30 UTC — очередь раннеров забита, tradein-деплой #1699 застрял на ~17+ мин #1709

Closed
opened 2026-06-17 18:47:19 +00:00 by lekss361 · 4 comments
Owner

Что было (incident)

2026-06-17 ~18:30–18:46 UTC очередь Forgejo Actions переполнилась — деплой tradein #1699 (feat(yandex): route gate-API fetch through camoufox, merge e5d78b5e, merged 18:28:51Z) встал в хвост и не запустился даже спустя ~17 мин. Пользователь вручную отменил всю очередь ~18:46 UTC, чтобы разблокировать.

Доказательства (наблюдённые факты, прод)

  • Раннер-лог forgejo-runner (2 контейнера: forgejo-runner, forgejo-runner-2, оба Up 4 weeks):
    • task 6350→6363 за 26 секунд (18:32:57Z → 18:33:23Z), ~2с/task — пачка
    • далее всплески 6370-6375 (18:35-18:37), 6379-6380, 6391
    • повторяющееся "Parallel tasks (0) below minimum, setting to 1" → каждый раннер тянет parallel=1
  • API GET /actions/taskstotal_count: 6363
  • В очереди/обработке ~10+ открытых PR других bot-окон (SiteFinder / forecasting / estimator / scrapers fix-ы): #1700, #1697, #1696, #1695, #1687, #1686, #1684, #1682, #1637, #1617, #1590, #1509. Каждый push гонит 3 job: backend-tests, frontend-tests, openapi-codegen-check (ci.yml).
  • Видны дубль-прогоны одного PR: и по ветке (fix/...-NNNN), и по PR-номеру (#NNNN) — напр. #1696: 6369-6371 (PR) + 6382 (branch); #1684: 6372-6377; #1617: 6378-6380. → superseded-прогоны НЕ отменяются автоматически.
  • Образ ghcr.io/lekss361/gendesign-tradein-backend:latest на проде = 10 часов (build 08:22 UTC), нового после мержа #1699 не появилось → tradein build-джобы не успели стартовать до отмены очереди.

Почему так долго

2 раннера × parallel=1 = 2 одновременных job. При ~10 PR × 3 job + дубли (ветка+PR) очередь >30 job. deploy-tradein.yml имеет concurrency: deploy-tradein-prod, cancel-in-progress: false → деплой не вытесняется, но ждёт свободный раннер за общим пулом с тестовыми прогонами SiteFinder.

Разобрать потом

  1. Concurrency-cancel superseded PR-runs. Добавить в ci.yml concurrency: { group: ci-${{ github.ref }}, cancel-in-progress: true } — чтобы новый push в ветку/PR отменял предыдущий незавершённый прогон (сейчас и ветка, и PR-номер плодят параллельные прогоны).
  2. Почему всплеск PR одновременно — auto-backend bot churn (массовая раскатка fix-PR). Возможно throttle/батчинг создания PR.
  3. Приоритет деплоя. Деплой-пайплайны (deploy.yml, deploy-tradein.yml) делят раннеры с тестовыми job. Рассмотреть выделенный раннер-лейбл для deploy или повышенный приоритет.
  4. Ёмкость раннеров — поднять parallel >1 или добавить 3-й раннер (VPS-ресурсы позволяют?).
  5. Дедуп openapi-codegen-check/frontend-tests на чисто-backend-PR (paths-filter), чтобы не гонять лишние job.

Связано

  • tradein #1699 (camoufox-транспорт yandex) — после разблокировки нужен прод-смоук (lots>0 без тарпита). Проверить что деплой #1699 не был отменён в общей чистке очереди; при необходимости перезапустить deploy-tradein.yml (workflow_dispatch).

scope/devops · needs-human (требует решения по раннерам/CI-конфигу)

## Что было (incident) 2026-06-17 ~18:30–18:46 UTC очередь Forgejo Actions переполнилась — деплой tradein #1699 (`feat(yandex): route gate-API fetch through camoufox`, merge `e5d78b5e`, merged **18:28:51Z**) встал в хвост и не запустился даже спустя ~17 мин. Пользователь вручную **отменил всю очередь ~18:46 UTC**, чтобы разблокировать. ## Доказательства (наблюдённые факты, прод) - **Раннер-лог** `forgejo-runner` (2 контейнера: `forgejo-runner`, `forgejo-runner-2`, оба Up 4 weeks): - task **6350→6363** за **26 секунд** (18:32:57Z → 18:33:23Z), ~2с/task — пачка - далее всплески 6370-6375 (18:35-18:37), 6379-6380, 6391 - повторяющееся `"Parallel tasks (0) below minimum, setting to 1"` → каждый раннер тянет parallel=1 - **API** `GET /actions/tasks` → `total_count: 6363` - В очереди/обработке **~10+ открытых PR других bot-окон** (SiteFinder / forecasting / estimator / scrapers fix-ы): #1700, #1697, #1696, #1695, #1687, #1686, #1684, #1682, #1637, #1617, #1590, #1509. Каждый push гонит **3 job**: `backend-tests`, `frontend-tests`, `openapi-codegen-check` (ci.yml). - Видны **дубль-прогоны** одного PR: и по ветке (`fix/...-NNNN`), и по PR-номеру (`#NNNN`) — напр. #1696: 6369-6371 (PR) + 6382 (branch); #1684: 6372-6377; #1617: 6378-6380. → superseded-прогоны НЕ отменяются автоматически. - Образ `ghcr.io/lekss361/gendesign-tradein-backend:latest` на проде = **10 часов** (build 08:22 UTC), нового после мержа #1699 не появилось → tradein build-джобы не успели стартовать до отмены очереди. ## Почему так долго 2 раннера × parallel=1 = **2 одновременных job**. При ~10 PR × 3 job + дубли (ветка+PR) очередь >30 job. `deploy-tradein.yml` имеет `concurrency: deploy-tradein-prod, cancel-in-progress: false` → деплой не вытесняется, но **ждёт свободный раннер за общим пулом** с тестовыми прогонами SiteFinder. ## Разобрать потом 1. **Concurrency-cancel superseded PR-runs.** Добавить в `ci.yml` `concurrency: { group: ci-${{ github.ref }}, cancel-in-progress: true }` — чтобы новый push в ветку/PR отменял предыдущий незавершённый прогон (сейчас и ветка, и PR-номер плодят параллельные прогоны). 2. **Почему всплеск PR одновременно** — auto-backend bot churn (массовая раскатка fix-PR). Возможно throttle/батчинг создания PR. 3. **Приоритет деплоя.** Деплой-пайплайны (`deploy.yml`, `deploy-tradein.yml`) делят раннеры с тестовыми job. Рассмотреть выделенный раннер-лейбл для deploy или повышенный приоритет. 4. **Ёмкость раннеров** — поднять parallel >1 или добавить 3-й раннер (VPS-ресурсы позволяют?). 5. **Дедуп `openapi-codegen-check`/`frontend-tests`** на чисто-backend-PR (paths-filter), чтобы не гонять лишние job. ## Связано - tradein #1699 (camoufox-транспорт yandex) — после разблокировки нужен прод-смоук (lots>0 без тарпита). Проверить что деплой #1699 не был отменён в общей чистке очереди; при необходимости перезапустить `deploy-tradein.yml` (workflow_dispatch). scope/devops · needs-human (требует решения по раннерам/CI-конфигу)
Author
Owner

Диагностика (devops, 2026-06-17, прод+API verified)

Раннеры/ресурсы — факты (ssh gendesign)

  • VPS: 6 vCPU, 11Gi RAM (5.6Gi available, swap = 0B), диск 80Gi free. Нагрузка спокойная.
  • 2 раннера forgejo-runner / forgejo-runner-2, оба Up 4 weeks. Конфиг ОБОИХ: capacity: 2 → реально 4 одновременных job, НЕ 2 как предполагалось в incident-описании. Лог "Parallel tasks (0) below minimum, setting to 1" — это benign per-poll сообщение раннера, НЕ показатель capacity.
  • Деплой tradein #1699разблокирован: run 6432 (deploy-tradein.yml, workflow_dispatch) = success 18:58Z. Образ пересобран.

ci.yml — concurrency и paths-filter УЖЕ на main

git show forgejo/main:.forgejo/workflows/ci.yml подтверждает: блок concurrency: {group: ci-${{github.workflow}}-${{github.ref}}, cancel-in-progress: true} (строки 34-36) уже есть, как и dorny/paths-filter changes-job. Т.е. задачи #1 и #5 частично закрыты ранее.

Корень дубль-прогонов (ветка+PR)

on: триггерит И pull_request (ref=refs/pull/N/merge) И push на feat/**,fix/**,… (ref=refs/heads/...). Это разные github.ref → разные concurrency-группы → НЕ отменяют друг друга. Отсюда дубли: #1706 → run 2417 (push fix/emiss) + run 2418 (PR #1706) на одном SHA. Concurrency-cancel сейчас работает только внутри одной ветки (consecutive push), не между push и PR.
Фикс: убрать push-триггер на feature-ветки, оставить только pull_request. Каждый коммит → 1 прогон вместо 2 (≈−50% job). Concurrency-блок тогда корректно отменяет superseded PR-прогоны при новом пуше (ref стабилен = refs/pull/N/merge). PR в работе.

НОВЫЙ симптом «сборки красные» — это РЕАЛЬНЫЕ, СИСТЕМНЫЕ провалы на main (не артефакт шторма)

Две поломки воспроизводятся идентично на #1706, #1705, #1687 (3 независимых PR):

1. backend-testsFAILED tests/services/test_objective_backfill.py::test_auto_apply_matches_dry_run_no_inserts - assert 1 == 0. Тест ждёт result["auto_accepted"] == 0 при dry_run=True, функция вернула 1. Это расхождение кода и теста на main (вероятно auto_apply_matches стал считать projected-кандидатов в dry-run). → нужен backend-фикс (тест vs семантика функции).

2. openapi-codegen-checkapi-types.ts устарел. Дифф (authoritative, post-prettier):

@@ PoiScoreItem @@        + score_contribution: number;
@@ poi-score result @@    + poi_weighted_score: number;

Замержённый POI-score PR (≈#1486 normalize POI weighted score) добавил 2 поля в Pydantic-схему, но frontend/src/lib/api-types.ts не перегенерён → drift на main, каждый backend-PR падает на этом чек не по своей вине. → фикс: regen api-types.ts (4 строки, контент известен точно).

⚠️ Branch protection = [] (нет защиты main)

CI-статусы никогда не блокируют merge — auto-reviewer мержит по своему verdict независимо от красного CI. Поэтому #1705/#1706 смержились с красным backend-tests. Следствие: красный CI (а) жжёт 2 из 4 дефицитных слотов на повтор известных провалов каждый PR, усугубляя шторм, (б) обесценивает gate. Фикс двух системных провалов выше вернёт сигнал.

План фиксов (отдельными минимальными PR)

  1. [devops, в работе] ci.yml: убрать push-триггер feature-веток (дедуп ветка+PR, ≈−50% job).
  2. [backend] test_objective_backfill — выровнять тест/семантику auto_apply_matches dry_run.
  3. [frontend] regen api-types.ts (+score_contribution, +poi_weighted_score).
  4. Ёмкость: parallel УЖЕ =2/раннер (4 слота). Поднимать до 6 рискованно — swap=0, при 6 тяжёлых job (uv+geo+npm) возможен OOM. Рекомендация: сначала добавить swap (2-4Gi), потом capacity 3. Дедуп (#1) — главный рычаг, снижает базовую нагрузку вдвое без риска.
  5. Деплой-приоритет: после дедупа+cancel слоты освобождаются быстро → деплой ждёт секунды, не 17 мин. Выделенный раннер-лейбл для деплоя при 2 раннерах урежет test-throughput вдвое — держу как опцию, если голодание повторится.
  6. Bot-churn (не мой код): рекомендация — throttle/батчинг создания fix-PR в auto-backend пайплайне (≈10 PR одновременно = первопричина объёма).
## Диагностика (devops, 2026-06-17, прод+API verified) ### Раннеры/ресурсы — факты (ssh gendesign) - **VPS**: 6 vCPU, 11Gi RAM (**5.6Gi available, swap = 0B**), диск 80Gi free. Нагрузка спокойная. - **2 раннера** `forgejo-runner` / `forgejo-runner-2`, оба `Up 4 weeks`. Конфиг ОБОИХ: **`capacity: 2`** → реально **4 одновременных job**, НЕ 2 как предполагалось в incident-описании. Лог `"Parallel tasks (0) below minimum, setting to 1"` — это benign per-poll сообщение раннера, НЕ показатель capacity. - Деплой tradein #1699 — **разблокирован**: run 6432 (`deploy-tradein.yml`, workflow_dispatch) = **success** 18:58Z. Образ пересобран. ### ci.yml — concurrency и paths-filter УЖЕ на main `git show forgejo/main:.forgejo/workflows/ci.yml` подтверждает: блок `concurrency: {group: ci-${{github.workflow}}-${{github.ref}}, cancel-in-progress: true}` (строки 34-36) **уже есть**, как и `dorny/paths-filter` changes-job. Т.е. задачи #1 и #5 частично закрыты ранее. ### Корень дубль-прогонов (ветка+PR) `on:` триггерит **И `pull_request`** (ref=`refs/pull/N/merge`) **И `push` на `feat/**`,`fix/**`,…** (ref=`refs/heads/...`). Это **разные `github.ref` → разные concurrency-группы → НЕ отменяют друг друга**. Отсюда дубли: #1706 → run 2417 (push fix/emiss) + run 2418 (PR #1706) на одном SHA. Concurrency-cancel сейчас работает только внутри одной ветки (consecutive push), не между push и PR. → **Фикс: убрать `push`-триггер на feature-ветки, оставить только `pull_request`.** Каждый коммит → 1 прогон вместо 2 (≈−50% job). Concurrency-блок тогда корректно отменяет superseded PR-прогоны при новом пуше (ref стабилен = `refs/pull/N/merge`). PR в работе. ### НОВЫЙ симптом «сборки красные» — это РЕАЛЬНЫЕ, СИСТЕМНЫЕ провалы на main (не артефакт шторма) Две поломки воспроизводятся **идентично** на #1706, #1705, #1687 (3 независимых PR): **1. `backend-tests`** — `FAILED tests/services/test_objective_backfill.py::test_auto_apply_matches_dry_run_no_inserts - assert 1 == 0`. Тест ждёт `result["auto_accepted"] == 0` при `dry_run=True`, функция вернула `1`. Это **расхождение кода и теста на main** (вероятно `auto_apply_matches` стал считать projected-кандидатов в dry-run). → нужен backend-фикс (тест vs семантика функции). **2. `openapi-codegen-check`** — `api-types.ts устарел`. Дифф (authoritative, post-prettier): ```diff @@ PoiScoreItem @@ + score_contribution: number; @@ poi-score result @@ + poi_weighted_score: number; ``` Замержённый POI-score PR (≈#1486 `normalize POI weighted score`) добавил 2 поля в Pydantic-схему, но `frontend/src/lib/api-types.ts` не перегенерён → **drift на main**, каждый backend-PR падает на этом чек не по своей вине. → фикс: regen api-types.ts (4 строки, контент известен точно). ### ⚠️ Branch protection = `[]` (нет защиты main) CI-статусы **никогда не блокируют merge** — auto-reviewer мержит по своему verdict независимо от красного CI. Поэтому #1705/#1706 смержились с красным backend-tests. Следствие: красный CI (а) жжёт 2 из 4 дефицитных слотов на повтор известных провалов каждый PR, усугубляя шторм, (б) обесценивает gate. Фикс двух системных провалов выше вернёт сигнал. ### План фиксов (отдельными минимальными PR) 1. **[devops, в работе]** `ci.yml`: убрать `push`-триггер feature-веток (дедуп ветка+PR, ≈−50% job). 2. **[backend]** `test_objective_backfill` — выровнять тест/семантику `auto_apply_matches` dry_run. 3. **[frontend]** regen `api-types.ts` (+`score_contribution`, +`poi_weighted_score`). 4. **Ёмкость**: parallel УЖЕ =2/раннер (4 слота). Поднимать до 6 рискованно — **swap=0**, при 6 тяжёлых job (uv+geo+npm) возможен OOM. Рекомендация: сначала добавить swap (2-4Gi), потом capacity 3. Дедуп (#1) — главный рычаг, снижает базовую нагрузку вдвое без риска. 5. **Деплой-приоритет**: после дедупа+cancel слоты освобождаются быстро → деплой ждёт секунды, не 17 мин. Выделенный раннер-лейбл для деплоя при 2 раннерах урежет test-throughput вдвое — держу как опцию, если голодание повторится. 6. **Bot-churn** (не мой код): рекомендация — throttle/батчинг создания fix-PR в auto-backend пайплайне (≈10 PR одновременно = первопричина объёма).
Author
Owner

Сделано (2026-06-17, devops)

PR #1713 — дедуп дубль-прогонов (ветка+PR)

ci.yml: убран push-триггер feature-веток, остался только pull_request. Каждый коммит → 1 прогон вместо 2 (≈−50% job), concurrency cancel-in-progress теперь корректно гасит superseded-прогоны PR. Ждёт review/merge (не мержу сам).

Добавлен 3-й раннер (capacity-пул 4 → 6 слотов)

По запросу — всего 3 раннера (было 2). На проде /home/gendesign/forgejo/runner-compose.yml:

  • backup runner-compose.yml.bak.before-runner3;
  • добавлены сервисы runner-3-register + runner-3 (точная копия паттерна runner-2), data-dir ./runner-3/data, config.yml скопирован (capacity: 2), имя vps-runner-3, labels ubuntu-latest/22.04/24.04;
  • регистрация переиспользовала существующий RUNNER_TOKEN (он reusable — им же регистрировали runner-2 позже runner-1);
  • forgejo-runner-3 Up, vps-runner-3 ... declared successfully, 2 поллера → 6 одновременных job на 3 раннерах.

RAM после добавления: used 5.3Gi / avail 6.4Gi, наблюдаемое потребление CI-job ≈0.6Gi → 6 слотов ≈3.6Gi пик, влезает. ⚠️ swap всё ещё 0B и gendesign без passwordless-sudo (swap не добавил). Прод-БД делит хост с раннерами — при одновременном всплеске 6 тяжёлых job (uv+geo+npm) OOM-killer теоретически может задеть контейнер. Рекомендация юзеру: добавить 2-4Gi swapfile (нужен root) как страховку. NB: runner-compose.yml живёт вне git-репо (/home/gendesign/forgejo, не /opt/gendesign) — изменение задокументировано здесь, PR не требуется.

Осталось (системные красные сборки — НЕ блокируют merge, т.к. branch protection пуст, но жгут слоты и обесценивают gate)

  • backend: test_objective_backfill::test_auto_apply_matches_dry_run_no_inserts — выровнять тест/семантику auto_apply_matches(dry_run=True).
  • frontend: regen api-types.ts (+score_contribution, +poi_weighted_score).
    Беру в работу отдельными PR.
## Сделано (2026-06-17, devops) ### ✅ PR #1713 — дедуп дубль-прогонов (ветка+PR) `ci.yml`: убран `push`-триггер feature-веток, остался только `pull_request`. Каждый коммит → 1 прогон вместо 2 (≈−50% job), concurrency `cancel-in-progress` теперь корректно гасит superseded-прогоны PR. **Ждёт review/merge** (не мержу сам). ### ✅ Добавлен 3-й раннер (capacity-пул 4 → 6 слотов) По запросу — **всего 3 раннера** (было 2). На проде `/home/gendesign/forgejo/runner-compose.yml`: - backup `runner-compose.yml.bak.before-runner3`; - добавлены сервисы `runner-3-register` + `runner-3` (точная копия паттерна runner-2), data-dir `./runner-3/data`, `config.yml` скопирован (`capacity: 2`), имя `vps-runner-3`, labels `ubuntu-latest`/`22.04`/`24.04`; - регистрация переиспользовала существующий `RUNNER_TOKEN` (он reusable — им же регистрировали runner-2 позже runner-1); - `forgejo-runner-3` **Up**, `vps-runner-3 ... declared successfully`, 2 поллера → **6 одновременных job** на 3 раннерах. **RAM после добавления**: used 5.3Gi / avail **6.4Gi**, наблюдаемое потребление CI-job ≈0.6Gi → 6 слотов ≈3.6Gi пик, влезает. ⚠️ **swap всё ещё 0B** и `gendesign` без passwordless-sudo (swap не добавил). Прод-БД делит хост с раннерами — при одновременном всплеске 6 тяжёлых job (uv+geo+npm) OOM-killer теоретически может задеть контейнер. **Рекомендация юзеру**: добавить 2-4Gi swapfile (нужен root) как страховку. NB: `runner-compose.yml` живёт вне git-репо (`/home/gendesign/forgejo`, не `/opt/gendesign`) — изменение задокументировано здесь, PR не требуется. ### Осталось (системные красные сборки — НЕ блокируют merge, т.к. branch protection пуст, но жгут слоты и обесценивают gate) - backend: `test_objective_backfill::test_auto_apply_matches_dry_run_no_inserts` — выровнять тест/семантику `auto_apply_matches(dry_run=True)`. - frontend: regen `api-types.ts` (+`score_contribution`, +`poi_weighted_score`). Беру в работу отдельными PR.
Author
Owner

Итог CI-кризиса (2026-06-17, devops) — все системные проблемы закрыты

Проблема Фикс Статус
Дубль-прогоны (push+PR на один SHA) #1713ci.yml: только pull_request, без push feature-веток merged (−50% job)
Дефицит слотов (2 раннера ×2 = 4) +runner-3 (capacity 2) на проде 6 слотов
Системный красный openapi-codegen-check (api-types drift) #1714 — regen api-types.ts (+score_contribution, +poi_weighted_score) merged
Очень долгие gate-job (~3 мин env-build) #1717 — кэш ~/.cache/uv + uv sync --no-dev в codegen merged
Системный красный backend-tests (test_objective_backfill) #1721 — устаревшая ассерция (audit 14f3ef20 сменил dry_run на projected-counts, тест не обновили) 🟡 PR открыт, ждёт merge

После merge #1721 на main не остаётся системных красных — оба gate-job (backend-tests, openapi-codegen-check) зелёные на чистом main, и каждый PR перестаёт жечь слоты на повтор известных провалов.

Подтверждение (verify)

  • main 1de2ef2a: api-types.ts содержит оба поля; ci.yml содержит uv-cache + --no-dev.
  • #1721 root cause сверен с кодом: auto_apply_matches dry_run → {"auto_accepted": len(auto), ...}, ранний return до db.execute (мок execute.assert_not_called() валиден). Кандидаты 0.95/0.70/0.65 vs AUTO_ACCEPT_THRESHOLD=0.85/REVIEW_THRESHOLD=0.6 → auto=1/review=2/skipped=0. Полный сьют 3277 passed / 0 failed.

Открытые рекомендации (не блокеры)

  1. swap=0 на VPS — при 6 слотах одновременных тяжёлых job есть теоретический OOM-риск (прод-БД делит хост). Добавить 2-4Gi swapfile (нужен root) как страховку.
  2. Branch protection пуст — CI не блокирует merge. Если нужно, чтобы красный CI реально останавливал merge — включить required status checks на main.
  3. Bot-churn (не devops-код): ~10 fix-PR одновременно = первопричина объёма. Рассмотреть throttle/батчинг создания PR в auto-backend пайплайне.

Сам PR-ы не мержу (это ревьюер-окно). #1721 — последний на merge.

## Итог CI-кризиса (2026-06-17, devops) — все системные проблемы закрыты | Проблема | Фикс | Статус | |---|---|---| | Дубль-прогоны (push+PR на один SHA) | #1713 — `ci.yml`: только `pull_request`, без push feature-веток | ✅ merged (−50% job) | | Дефицит слотов (2 раннера ×2 = 4) | +`runner-3` (capacity 2) на проде | ✅ **6 слотов** | | Системный красный `openapi-codegen-check` (api-types drift) | #1714 — regen `api-types.ts` (+`score_contribution`, +`poi_weighted_score`) | ✅ merged | | Очень долгие gate-job (~3 мин env-build) | #1717 — кэш `~/.cache/uv` + `uv sync --no-dev` в codegen | ✅ merged | | Системный красный `backend-tests` (`test_objective_backfill`) | #1721 — устаревшая ассерция (audit `14f3ef20` сменил dry_run на projected-counts, тест не обновили) | 🟡 PR открыт, ждёт merge | После merge #1721 на main **не остаётся системных красных** — оба gate-job (backend-tests, openapi-codegen-check) зелёные на чистом main, и каждый PR перестаёт жечь слоты на повтор известных провалов. ### Подтверждение (verify) - main `1de2ef2a`: `api-types.ts` содержит оба поля; `ci.yml` содержит uv-cache + `--no-dev`. - #1721 root cause сверен с кодом: `auto_apply_matches` dry_run → `{"auto_accepted": len(auto), ...}`, ранний return до `db.execute` (мок `execute.assert_not_called()` валиден). Кандидаты 0.95/0.70/0.65 vs `AUTO_ACCEPT_THRESHOLD=0.85`/`REVIEW_THRESHOLD=0.6` → auto=1/review=2/skipped=0. Полный сьют 3277 passed / 0 failed. ### Открытые рекомендации (не блокеры) 1. **swap=0** на VPS — при 6 слотах одновременных тяжёлых job есть теоретический OOM-риск (прод-БД делит хост). Добавить 2-4Gi swapfile (нужен root) как страховку. 2. **Branch protection пуст** — CI не блокирует merge. Если нужно, чтобы красный CI реально останавливал merge — включить required status checks на `main`. 3. **Bot-churn** (не devops-код): ~10 fix-PR одновременно = первопричина объёма. Рассмотреть throttle/батчинг создания PR в auto-backend пайплайне. Сам PR-ы не мержу (это ревьюер-окно). #1721 — последний на merge.
Author
Owner

Рекомендация #1 (swap) — сделано (2026-06-17)

Добавлен 4Gi swapfile на VPS как страховка OOM под 6 CI-слотов (прод-БД делит хост):

  • /swapfile 4G (создан dd, контигуозный), swapon активен, free -h → Swap 4.0Gi;
  • персист: /etc/fstab (/swapfile none swap sw 0 0) + vm.swappiness=10 в /etc/sysctl.d/99-swap.conf (применён);
  • swappiness=10 → swap как страховка под реальным давлением, горячие страницы БД не выселяются в штатном режиме.

Выполнено через docker run --privileged --pid=host alpine nsenter -t1 (host-root: у ssh-юзера нет passwordless sudo, но есть docker-группа). Откат: swapoff /swapfile && rm /swapfile + строка fstab + 99-swap.conf.

Остаётся опционально: #2 branch protection (готов оформить ci-ok агрегирующий job + required-check отдельным PR по запросу) и #3 throttle bot-churn (вне CI-кода).

## ✅ Рекомендация #1 (swap) — сделано (2026-06-17) Добавлен 4Gi swapfile на VPS как страховка OOM под 6 CI-слотов (прод-БД делит хост): - `/swapfile` 4G (создан `dd`, контигуозный), `swapon` активен, `free -h` → Swap 4.0Gi; - персист: `/etc/fstab` (`/swapfile none swap sw 0 0`) + `vm.swappiness=10` в `/etc/sysctl.d/99-swap.conf` (применён); - `swappiness=10` → swap как страховка под реальным давлением, горячие страницы БД не выселяются в штатном режиме. Выполнено через `docker run --privileged --pid=host alpine nsenter -t1` (host-root: у ssh-юзера нет passwordless sudo, но есть docker-группа). Откат: `swapoff /swapfile && rm /swapfile` + строка fstab + `99-swap.conf`. Остаётся опционально: #2 branch protection (готов оформить `ci-ok` агрегирующий job + required-check отдельным PR по запросу) и #3 throttle bot-churn (вне CI-кода).
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#1709
No description provided.