ci: сделать видимыми два безмолвных шага после pytest (#2871) #2872

Merged
bot-backend merged 1 commit from ci/2871-post-test-steps-visible into main 2026-08-13 16:53:45 +00:00
Collaborator

Проблема

backend-tests на PR #2865 покраснел три раза подряд — и каждый раз ПОСЛЕ зелёного
pytest:

Required test coverage of 65% reached. Total coverage: 74.57%
4647 passed, 28 skipped, 7 warnings in 899.63s
   ← девять секунд без единой строки
Skipping step 'Cache uv packages' due to 'success()'
🏁  Job failed

После pytest идут ровно два шага, оба if: always(): Coverage summary и
Снести тестовый Postgres. act_runner не печатает баннеры обычных run:-шагов,
а оба шага молчат по построению — первый пишет в $GITHUB_STEP_SUMMARY, второй глушит
вывод в /dev/null. Я сравнил логи зелёного и красного прогонов построчно: в этом месте
они неотличимы. Понять, какой из двух шагов упал, нечем.

Что исключено замерами (не рассуждением)

Гипотеза Чем опровергнута
Диск (#2869) третий прогон при 28 ГБ свободных — то же падение
Раннер падало на vps-runner-2 и vps-runner-1; vps-runner-2 в тот же час дал зелёный прогон
Пропавший тест pytest --collect-only на обеих ветках: разница ровно 3 теста, вся объясняется базой
Гейт покрытия 74.57% ≥ 65 во ВСЕХ прогонах, до сотых одинаково
Устаревшая база обновил ветку от base — упало снова

Что делает PR

  1. Маркеры начала и конца у обоих шагов — в следующем красном прогоне будет видно,
    докуда дошло.

  2. Шаг-отчёт больше не может уронить сборку. coverage report уважает fail_under
    из pyproject.toml и выходит с кодом 2, а run: исполняется под
    bash -eo pipefail → конструкция report="$(uv run coverage report ... | tail -40)"
    роняла шаг. Воспроизвёл локально:

    pytest exit=0
    coverage-summary step exit=2
    

    Теперь код возврата печатается отдельной строкой, а гейт остаётся там, где ему место —
    в pytest --cov-fail-under=65. Отчёт должен печатать, а не гейтить.

  3. || cov_rc=$? вместо отдельной строки cov_rc=$? — под set -e присваивание после
    упавшей команды просто не выполнится, и код возврата снова потеряется. Тот же класс
    ловушки, что я поймал в уборщике билдеров (#2870).

Честно про границы

Этот PR не утверждает, что нашёл причину. В CI покрытие 74.57% > 65, значит путь
через fail_under там срабатывать не должен. Механизм найден и обезврежен, но виновник
будет назван только следующим прогоном — по маркерам.

Проверка

  • yaml.safe_load — валиден
  • pre-commit check yaml — passed
  • локальный прогон шага в bash -eo pipefail — воспроизводит exit 2 на старой форме
  • после мержа: обновить #2865 от base, перезапустить и прочитать маркеры

Refs #2871

## Проблема `backend-tests` на PR #2865 покраснел **три раза подряд** — и каждый раз ПОСЛЕ зелёного pytest: ``` Required test coverage of 65% reached. Total coverage: 74.57% 4647 passed, 28 skipped, 7 warnings in 899.63s ← девять секунд без единой строки Skipping step 'Cache uv packages' due to 'success()' 🏁 Job failed ``` После pytest идут ровно два шага, оба `if: always()`: `Coverage summary` и `Снести тестовый Postgres`. `act_runner` не печатает баннеры обычных `run:`-шагов, а оба шага молчат по построению — первый пишет в `$GITHUB_STEP_SUMMARY`, второй глушит вывод в `/dev/null`. Я сравнил логи зелёного и красного прогонов построчно: в этом месте они **неотличимы**. Понять, какой из двух шагов упал, нечем. ## Что исключено замерами (не рассуждением) | Гипотеза | Чем опровергнута | |---|---| | Диск (#2869) | третий прогон при 28 ГБ свободных — то же падение | | Раннер | падало на `vps-runner-2` и `vps-runner-1`; `vps-runner-2` в тот же час дал зелёный прогон | | Пропавший тест | `pytest --collect-only` на обеих ветках: разница ровно 3 теста, вся объясняется базой | | Гейт покрытия | 74.57% ≥ 65 во ВСЕХ прогонах, до сотых одинаково | | Устаревшая база | обновил ветку от base — упало снова | ## Что делает PR 1. **Маркеры** начала и конца у обоих шагов — в следующем красном прогоне будет видно, докуда дошло. 2. **Шаг-отчёт больше не может уронить сборку.** `coverage report` уважает `fail_under` из `pyproject.toml` и выходит с кодом **2**, а `run:` исполняется под `bash -eo pipefail` → конструкция `report="$(uv run coverage report ... | tail -40)"` роняла шаг. Воспроизвёл локально: ``` pytest exit=0 coverage-summary step exit=2 ``` Теперь код возврата печатается отдельной строкой, а гейт остаётся там, где ему место — в `pytest --cov-fail-under=65`. Отчёт должен печатать, а не гейтить. 3. `|| cov_rc=$?` вместо отдельной строки `cov_rc=$?` — под `set -e` присваивание после упавшей команды просто не выполнится, и код возврата снова потеряется. Тот же класс ловушки, что я поймал в уборщике билдеров (#2870). ## Честно про границы Этот PR **не утверждает**, что нашёл причину. В CI покрытие 74.57% > 65, значит путь через `fail_under` там срабатывать не должен. Механизм найден и обезврежен, но виновник будет назван только следующим прогоном — по маркерам. ## Проверка - [x] `yaml.safe_load` — валиден - [x] pre-commit `check yaml` — passed - [x] локальный прогон шага в `bash -eo pipefail` — воспроизводит exit 2 на старой форме - [ ] после мержа: обновить #2865 от base, перезапустить и прочитать маркеры Refs #2871
bot-backend added 1 commit 2026-08-13 16:35:42 +00:00
ci: сделать видимыми два безмолвных шага после pytest
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 Trade-In / frontend-checks (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 1m19s
CI / openapi-codegen-check (pull_request) Successful in 2m20s
CI / backend-tests (pull_request) Successful in 16m37s
254a52d89c
backend-tests трижды покраснел ПОСЛЕ зелёного pytest (4647 passed, покрытие
74.57% ≥ 65), и по логу невозможно понять, в каком из двух `if: always()`
шагов это случилось: act_runner не печатает баннеры обычных `run:`-шагов,
а оба шага в штатном режиме молчат — один пишет в $GITHUB_STEP_SUMMARY,
второй глушит вывод в /dev/null. Зелёный и красный прогоны в этом месте
неотличимы построчно.

Добавлены маркеры начала/конца обоих шагов.

Отдельно: `coverage report` уважает fail_under из pyproject и выходит с
кодом 2, а `run:` идёт под `bash -eo pipefail` — то есть шаг-ОТЧЁТ умел
ронять сборку. Воспроизведено локально (pytest exit=0, шаг exit=2).
Теперь код возврата печатается, а гейт остаётся там, где ему место —
в `pytest --cov-fail-under=65`.

`|| cov_rc=$?` вместо отдельной строки `cov_rc=$?`: под `set -e`
присваивание после упавшей команды не выполнилось бы, и код снова
потерялся бы.

Refs #2871
bot-backend merged commit a6e751da65 into main 2026-08-13 16:53:45 +00:00
bot-backend deleted branch ci/2871-post-test-steps-visible 2026-08-13 16:53:46 +00:00
Sign in to join this conversation.
No reviewers
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#2872
No description provided.