CI ПТИЦА: Postgres с PostGIS, тест моста gap-fill в CI исполняется, а не пропускается (#2962)

На голове b74b02ea CI / backend-tests был красным (run 11737): 5125 passed, но
все 5 тестов test_2962_competitors_gapfill_bridge.py пропустились с причиной
«нет расширения postgis», а в skip_allowlist.txt их не было — гейт вернул rc=1.
В CI ПТИЦЫ plain postgres:16, а SQL конкурентов без PostGIS не исполнить
(ST_DWithin по geography).

- ci.yml: образ postgis/postgis:16-3.4 (тот же, что в ci-tradein.yml); образ
  сам создаёт расширение в POSTGRES_DB.
- тест: при CI/GITHUB_ACTIONS skipif выключен — если PostGIS из CI пропадёт,
  тест упадёт с настоящей причиной, а не пропустится молча.
- skip_allowlist.txt: пропуск объявлен только для машины без базы.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
bot-backend 2026-09-17 15:28:19 +05:00
parent b74b02ea8b
commit 33182e7df9
3 changed files with 30 additions and 10 deletions

View file

@ -260,10 +260,12 @@ jobs:
# #295 weighted AVG) self-skip'ался connectivity-probe'ом — в CI эти проверки
# не бежали ни разу с момента написания.
#
# plain postgres:16, БЕЗ PostGIS: тесты tests/sql/ строят себе временные
# таблицы (CREATE TEMP TABLE) и не трогают ни geometry, ни реальную схему —
# проверено локально, 16 passed за 1.3с. Поэтому и bootstrap схемы здесь не
# нужен, в отличие от tradein-лэйна.
# postgis/postgis:16-3.4, схема НЕ собирается: тесты строят себе временные
# таблицы (CREATE TEMP TABLE), которые затеняют боевые, и гоняют настоящий SQL
# модулей. PostGIS нужен с #2962: SQL конкурентов ищет «тот же ЖК» через
# ST_DWithin по geography, без расширения его не исполнить. На plain
# postgres:16 тест #2962 молча пропускался, то есть мост gap-fill в CI не
# проверялся вовсе. Образ сам создаёт расширение в POSTGRES_DB.
#
# TEST_DATABASE_URL НАМЕРЕННО НЕ задаётся: на него завязан tests/integration/
# (phantom-column gate), которому нужна КОПИЯ ПРОДОВОЙ схемы через pg_dump по
@ -294,15 +296,14 @@ jobs:
# ВРЕМЕННЫЙ сервер фазы initdb (listen_addresses=''), после которой БД
# ещё перезапускается. Проба по TCP зеленеет только на настоящем сервере.
#
# plain postgres:16, БЕЗ PostGIS: тесты tests/sql/ строят себе временные
# таблицы и не трогают ни geometry, ни реальную схему — bootstrap схемы
# здесь не нужен вовсе, в отличие от tradein-лэйна.
# postgis, а не plain postgres (#2962) — см. комментарий у job'а. Bootstrap
# схемы здесь не нужен вовсе, в отличие от tradein-лэйна.
run: |
set -u
docker rm -fv "$CI_PG" >/dev/null 2>&1 || true
docker run -d --name "$CI_PG" \
-e POSTGRES_DB=gendesign_ci -e POSTGRES_USER=gendesign -e POSTGRES_PASSWORD=gendesign \
postgres:16
postgis/postgis:16-3.4
ready=""
for _ in $(seq 1 45); do

View file

@ -8,7 +8,10 @@
Тест герметичный и прогоняет НАСТОЯЩИЕ `_COMPETITORS_SQL` и
`_OBJECTIVE_PRICE_FALLBACK_SQL`: временные таблицы затеняют боевые в пределах сессии.
Нужен Postgres с PostGIS, иначе skip.
Нужен Postgres с PostGIS (ST_DWithin по geography). В CI он есть
(.forgejo/workflows/ci.yml, образ postgis/postgis), и там тест не пропускается
никогда: без PostGIS он падает с настоящей причиной. Пропуск разрешён только вне CI,
на машине без базы, и объявлен в skip_allowlist.txt.
"""
from __future__ import annotations
@ -43,7 +46,10 @@ def _postgis_reachable() -> tuple[bool, str]:
_DB_OK, _DB_ERR = _postgis_reachable()
pytestmark = pytest.mark.skipif(not _DB_OK, reason=f"Postgres/PostGIS недоступен: {_DB_ERR}")
_IN_CI = bool(os.environ.get("GITHUB_ACTIONS") or os.environ.get("CI"))
pytestmark = pytest.mark.skipif(
not _DB_OK and not _IN_CI, reason=f"Postgres/PostGIS недоступен: {_DB_ERR}"
)
_SCHEMA = [
"""CREATE TEMP TABLE domrf_kn_objects (

View file

@ -144,6 +144,19 @@ tests/sql/test_2464_area_bin_unknown.py::test_lot_without_area_is_not_counted_as
tests/sql/test_2464_area_bin_unknown.py::test_unknown_area_gets_its_own_bucket
tests/sql/test_2464_area_bin_unknown.py::test_total_lots_preserved
tests/sql/test_2464_area_bin_unknown.py::test_normal_buckets_unchanged
# ── #2962: мост gap-fill конкурентов (complex_sources → project_name) ─────────
# Нужен Postgres С PostGIS: тесты затеняют боевые таблицы временными и гоняют
# НАСТОЯЩИЕ _COMPETITORS_SQL и _OBJECTIVE_PRICE_FALLBACK_SQL, а там ST_DWithin по
# geography. В CI ИДУТ (ci.yml поднимает postgis/postgis:16-3.4) и пропуститься
# там НЕ МОГУТ: при CI=true skipif выключен, без PostGIS тест падает. Записи нужны
# только для машины без базы.
tests/services/site_finder/test_2962_competitors_gapfill_bridge.py::test_gapfill_velocity_counts_only_own_project
tests/services/site_finder/test_2962_competitors_gapfill_bridge.py::test_gapfill_price_is_median_of_own_lots
tests/services/site_finder/test_2962_competitors_gapfill_bridge.py::test_wrong_fuzzy_link_gives_no_numbers
tests/services/site_finder/test_2962_competitors_gapfill_bridge.py::test_punctuation_difference_still_matches
tests/services/site_finder/test_2962_competitors_gapfill_bridge.py::test_explicit_mapping_unchanged
# ── #2464: backfill act_date (миграция 191) ──────────────────────────────────
# Нужен живой Postgres: тесты создают ВРЕМЕННУЮ копию land_reservation в прод-форме
# (9+2 строки с датой Генплана + контрольные посторонние) и прогоняют ТЕЛО миграции