Commit graph

2159 commits

Author SHA1 Message Date
bot-backend
7800f6014a refactor(tradein/scraper-kit): yandex providers on shared _base.py (#2363)
All checks were successful
CI / changes (pull_request) Successful in 10s
CI Trade-In / changes (pull_request) Successful in 11s
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
CI Trade-In / backend-tests (pull_request) Successful in 1m48s
F4c-yandex (epic #2277 Group F, parent #2352): migrate the SERP scraper's
BrowserFetcher construction onto build_browser_fetcher() from the Foundation
module (#2358, providers/_base.py) instead of local ad-hoc construction.

- yandex/serp.py::__aenter__ now calls build_browser_fetcher(config, source=,
  proxy_provider=, fetch_timeout_s=) instead of constructing BrowserFetcher(...)
  directly. Preserves the existing fetch_timeout_s=30 (see caveat below),
  endpoint/proxy_provider/use_pool resolution byte-for-byte. The retry/tarpit
  logic in fetch_around() (rotate_ip + sleep on status==0/JSON-error) is
  untouched, per the Foundation module's documented exclusion.

Left unchanged (deliberate, not an oversight):
- yandex/serp.py::_rotate_ip's curl_cffi AsyncSession(timeout=30) — this hits
  the mobile-proxy provider's own changeip API, not Yandex; it intentionally
  carries no impersonate/headers/proxy (same as the mirrored avito/serp.py
  rotate-ip session). Not listed among the _base.py docstring's documented
  extraction sites -- consistent exclusion, not a new one.
- yandex/detail.py -- no BrowserFetcher/curl_cffi construction exists in this
  file (uses BaseScraper's httpx-based _http_get). Nothing to migrate.
- yandex/newbuilding.py -- both BrowserFetcher(...) call sites take an
  OPTIONAL `config: ScraperConfig | None`, a genuinely different contract from
  build_browser_fetcher's mandatory `config`. Migrating would require making
  config mandatory (breaking admin.py:1511, yandex_newbuilding_sweep.py:353,
  and several tests that call without config -- out of scope for a call-site
  swap) and breaks test_scraper_kit_newbuilding_endpoint.py's "without config,
  endpoint=None" regression case (its SimpleNamespace mock lacks
  use_proxy_pool_browser, and the mock config path can never satisfy a
  mandatory-config helper). Left untouched; the class-bug #2322/#2330 this
  file already fixed (config now threaded, just not via the shared helper)
  remains fixed.

Also updates test_kit_serp_proxy_pool.py's 3 yandex-specific tests: they
monkeypatched the module-local `yandex_serp.BrowserFetcher` name, which the
migrated call path no longer references directly (it now goes through
scraper_kit.providers._base.build_browser_fetcher -> _base's own BrowserFetcher
import). Patch target moved to scraper_kit.providers._base.BrowserFetcher;
every assertion is unchanged -- this adapts the mock to the new (intentional)
call path, it does not weaken what the test verifies. Cian's tests in the same
file are untouched (cian/serp.py is not migrated yet, separate F4b issue).
2026-07-04 09:38:43 +03:00
758a4b06d4 Merge pull request 'refactor(tradein/scraper-kit): avito providers on shared _base.py (#2361)' (#2375) from feat/tradein-scraper-kit-f4a-avito into main
All checks were successful
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m39s
Deploy Trade-In / build-backend (push) Successful in 1m23s
Deploy Trade-In / changes (push) Successful in 14s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / deploy (push) Successful in 1m31s
2026-07-04 06:34:59 +00:00
53947015e9 Merge pull request 'refactor(tradein/scraper-kit): cian providers on shared _base.py (#2362)' (#2374) from feat/tradein-scraper-kit-f4b-cian into main
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 13s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m39s
Deploy Trade-In / build-backend (push) Has been cancelled
2026-07-04 06:32:30 +00:00
bot-backend
b445c34863 refactor(tradein/scraper-kit): avito providers on shared _base.py (#2361)
All checks were successful
CI / changes (pull_request) Successful in 10s
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 11s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m44s
Мигрирует avito/{serp,detail}.py на build_browser_fetcher()/
build_document_session() из scraper_kit.providers._base (Foundation #2358):

- serp.py: BrowserFetcher(source="avito", endpoint=...) в __aenter__ ->
  build_browser_fetcher(config, "avito"); _build_cffi_session() (25s
  timeout, document headers, scraper_proxy_url) -> build_document_session().
- detail.py: _build_detail_session() (тот же document-headers dict,
  25s timeout) -> build_document_session(proxy_url=..., timeout=25).

Caveat (#2361, проверено explicit): serp.py __aenter__ раньше конструировал
BrowserFetcher БЕЗ proxy_provider/use_pool (implicit None/False). После
миграции use_pool читает config.use_proxy_pool_browser вместо hardcoded
False - НО proxy_provider остаётся None (build_browser_fetcher default), а
BrowserFetcher._use_pool гейтится `and self._proxy_provider is not None`
(browser_fetcher.py:215) - при proxy_provider=None use_pool всегда
эффективно False независимо от config. Verified: behavior-preserving,
не тихая смена прод-поведения.

imv.py: НЕ мигрирован (единственное отклонение от issue). Own-session
curl_cffi construction (headers=_DOC_HEADERS - тот же дублированный dict)
технически подходит под миграцию, но build_document_session() резолвит
AsyncSession через module-level импорт _base.py (biндится один раз при
первом импорте _base), а tests/scrapers/test_avito_imv_kit_parity.py
(#2334) патчит curl_cffi.requests.AsyncSession через unittest.mock -
это работает только с локальным call-time импортом (как было). Миграция
роняет 2 реальных теста (test_kit_evaluate_via_imv_{with,without}_config_
uses_proxy) - не шум, зелёные на main. Прод-поведение идентично в обоих
вариантах, но задача явно запрещает weaken/skip parity-тесты - оставлено
как есть + inline-комментарий с находкой. Follow-up для будущих групп
(cian/yandex/domclick F4b-d): тот же паттерн теста сломает миграцию любого
provider с аналогичным unittest.mock.patch("curl_cffi.requests.AsyncSession").

Tests: full backend suite 3278 passed, 1 known pre-existing flake
(test_search_api.py::test_search_cache_hit, #2208), 6 skipped. Все avito
kit_parity/golden_parity тесты + test_scraper_kit_pipeline_parity2.py
(cross-provider) зелёные.
2026-07-04 09:31:27 +03:00
bot-backend
96dd27c4ae refactor(tradein/scraper-kit): cian providers on shared _base.py (#2362)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 12s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / changes (pull_request) Successful in 15s
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 / backend-tests (pull_request) Successful in 1m41s
Мигрирует call-site'ы cian/{serp,detail,newbuilding,session}.py на shared
фабрики Foundation-модуля (#2358): build_browser_fetcher() (serp.py __aenter__)
и build_curl_cffi_session() (detail.py own-session path, newbuilding.py
resolve_cian_zhk_url[_via_search], session.py verify_session). Headers/timeout/
proxy-resolution сохранены байт-в-байт — чистый call-site swap, без изменения
поведения.

Caveat (config Optional footgun): newbuilding.py::fetch_newbuilding() НЕ
переведена на build_browser_fetcher() — build_browser_fetcher() требует
ScraperConfig mandatory (весь смысл фабрики, закрывает класс багов #2322/#2330),
но здесь config: ScraperConfig | None = None легитимно Optional (admin.py
debug-роут и test_scraper_kit_newbuilding_endpoint.py вызывают функцию без
config= и ожидают graceful endpoint=None). Подмена уронила бы AttributeError
на config=None вместо текущего degrade — реальная регрессия, не call-site swap.
Оставлено как есть с комментарием в коде.

Companion test updates (не ослабление, retarget под рефактор): CianScraper
теперь строит BrowserFetcher внутри _base.py, а не в serp.py — два теста в
test_kit_serp_proxy_pool.py, патчившие cian_serp.BrowserFetcher напрямую,
переключены на scraper_kit.providers._base.BrowserFetcher (тот же инвариант,
другая точка патча). Аналогично test_scraper_kit_pricehistory_session_parity.py
::test_fetch_detail_own_session_proxy_wiring_parity — патч AsyncSession
переключён с cian.detail на _base (тот же assert на итоговый proxies=dict).

Tests: full backend suite 3278 passed, 1 pre-existing flake
(test_search_api.py::test_search_cache_hit, #2208), 6 skipped. Все
parity/regression тесты (test_scraper_kit_pipeline_parity2.py,
test_scraper_kit_newbuilding_endpoint.py, test_scraper_kit_cian_golden_parity.py,
test_kit_serp_proxy_pool.py, test_scraper_kit_pricehistory_session_parity.py,
test_cian_serp_scraper.py, test_cian_session.py, test_cian_detail.py) зелёные.
ruff check + format --check чисто на всех изменённых файлах.
2026-07-04 09:29:49 +03:00
53e7834f19 Merge pull request 'refactor(tradein/scraper-kit): domclick providers on shared _base.py (#2364)' (#2372) from feat/tradein-scraper-kit-f4d-domclick into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m35s
Deploy Trade-In / build-backend (push) Successful in 1m23s
Deploy Trade-In / deploy (push) Successful in 3m1s
2026-07-04 06:24:06 +00:00
bot-backend
debe55b8a0 refactor(tradein/scraper-kit): domclick providers on shared _base.py (#2364)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / 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 / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m42s
Group F4d (epic #2277, parent #2352). Migrated the ad-hoc BrowserFetcher
construction in providers/domclick/serp.py::fetch_city to the shared
build_browser_fetcher(config, source) helper from Foundation (#2358).

Scope actually touched:
- serp.py: replaced the local BrowserFetcher(source="domclick", endpoint=...)
  construction with build_browser_fetcher(self._config, "domclick").
- detail.py: NO changes needed. Grepped for BrowserFetcher(/AsyncSession(/
  curl_cffi and found none - fetch_detail() receives an already-constructed
  browser_fetcher from the caller (orchestrator owns the session lifecycle,
  per its own module docstring), so there was nothing to migrate here.

Caveat verified (same class as avito, per issue instructions): the old
call site omitted use_pool, so it implicitly defaulted to False via the
BrowserFetcher class default. build_browser_fetcher(config, source) reads
use_pool=config.use_proxy_pool_browser instead - a real difference in the
value passed in. However this call site does not pass proxy_provider
(stays the default None), and BrowserFetcher._pool_proxy computes
`use_pool and proxy_provider is not None` before ever using the pool - so
with proxy_provider=None the effective behavior is identical regardless
of what use_pool evaluates to (confirmed by reading browser_fetcher.py
directly, matching the build_browser_fetcher docstring's own note that
domclick is one of the providers not yet wired to the proxy pool, #2160
P4). No observable behavior change. Documented inline at the call site.

Tests: domclick-specific suite (91 tests: golden parity, sweep, admin
ingest parity, detail + detail kit parity) all green, plus cross-provider
test_scraper_kit_pipeline_parity2.py (8 tests). Full backend suite:
3278 passed, 6 skipped, 1 pre-existing flake (test_search_cache_hit,
#2208) - no new failures.
2026-07-04 09:18:04 +03:00
ae3278f92f fix(gisogd66): битый 500-сегмент портала — no-retry карточек, circuit breaker, периодический commit (#2371)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m51s
Deploy / build-worker (push) Successful in 3m3s
Deploy / deploy (push) Successful in 1m31s
2026-07-04 04:33:44 +00:00
282c92747e feat(scrapers): реестр РНС/РВЭ ГИСОГД-СО из открытого API — миграция + лоадер (#2367 PR-1) (#2370)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 2m40s
Deploy / build-worker (push) Successful in 3m27s
Deploy / build-frontend (push) Successful in 4m0s
Deploy / deploy (push) Successful in 1m41s
2026-07-04 03:26:07 +00:00
ae814706a2 feat(forecast-ui): confidence band на ForecastChart — качественный интервал уверенности (#1926) (#2368)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m10s
Deploy / deploy (push) Successful in 1m16s
2026-07-04 02:21:44 +00:00
57d156973e feat(chat): tool get_parcel_info — курируемый градрегламент/ЗОУИТ/ЕГРН в контекст чата (#2366)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m44s
Deploy / build-worker (push) Successful in 2m46s
Deploy / deploy (push) Successful in 1m31s
2026-07-04 01:24:42 +00:00
38f703c8ec fix(landing): Trade-In nav как внешний <a> на /trade-in/v2 (ChunkLoadError) (#2365)
All checks were successful
Deploy / changes (push) Successful in 10s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / build-frontend (push) Successful in 3m18s
Deploy / deploy (push) Successful in 1m20s
2026-07-04 01:10:57 +00:00
d31fabd102 Merge pull request 'feat(tradein/scraper-kit): shared base/utils для providers/* (#2358, Foundation)' (#2360) from feat/tradein-scraper-kit-base-2358 into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 9s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m32s
Deploy Trade-In / build-backend (push) Successful in 1m16s
Deploy Trade-In / deploy (push) Successful in 1m11s
2026-07-04 00:56:13 +00:00
bot-backend
51e2e545b7 fix(tradein/scraper-kit): точность докстринга http_proxies() про httpx-совместимость
All checks were successful
CI / changes (pull_request) Successful in 7s
CI Trade-In / changes (pull_request) Successful in 7s
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
CI Trade-In / backend-tests (pull_request) Successful in 1m35s
code-reviewer отметил: httpx>=0.28 больше не принимает dict в proxies= (только
одиночный proxy= строкой). Docstring ошибочно называл эту функцию
"httpx-совместимой" — уточнено что это только для curl_cffi, чтобы будущий
мигратор F4a-d не словил TypeError.
2026-07-04 03:50:55 +03:00
bot-backend
9b4cdf8ec6 feat(tradein/scraper-kit): shared base/utils для providers/* (#2358, Foundation)
Аддитивный Foundation-модуль (эпик #2277 Group F4): scraper_kit/providers/_base.py
извлекает 3 реально повторяющихся паттерна, найденных чтением avito/cian/yandex/
domclick providers (~13k строк):

- build_browser_fetcher(config: ScraperConfig, source, ...) — config MANDATORY,
  устраняет footgun-класс #2322/#2330 (BrowserFetcher конструировался вручную в
  6+ местах, endpoint/proxy-pool wiring легко забыть/потерять).
- build_curl_cffi_session / build_document_session + http_proxies() — общий
  curl_cffi AsyncSession(impersonate=chrome120, proxies=..., headers=...)
  boilerplate, дублированный в avito/serp.py, avito/detail.py, avito/imv.py,
  cian/detail.py, cian/newbuilding.py (x2), cian/session.py.
- DOCUMENT_HEADERS — идентичный "document" headers dict, дублированный трижды.

Retry/backoff-циклы (yandex tarpit-retry, avito page-retry, tenacity в
BaseScraper) сознательно НЕ обобщены — разная семантика ошибок/действий между
попытками, обобщение дало бы leaky abstraction (см. docstring модуля).

Existing providers/{avito,cian,yandex,domclick}/*.py НЕ тронуты — миграция
call-site'ов на новый модуль это отдельные future issues (F4a-d).

Заодно: актуализирован устаревший докстринг app/services/scraper_adapters.py
("Пока НИКТО их не использует") — адаптеры wired в прод с #2192 через
app.scheduler_main._run_kit_scheduler.
2026-07-04 03:50:55 +03:00
91c8365d91 fix(tradein/houses): персистить house_class из avito «Класс жилья» и yandex parse (#2003) (#2359)
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m31s
Deploy Trade-In / build-backend (push) Successful in 1m23s
Deploy Trade-In / deploy (push) Successful in 53s
2026-07-04 00:49:48 +00:00
6468bd6b37 fix(report-pdf): best-effort inline §22-форсайт на холодном участке — отчёт самодостаточен (#2357)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m55s
Deploy / build-worker (push) Successful in 2m52s
Deploy / deploy (push) Successful in 1m37s
2026-07-04 00:30:12 +00:00
1e5fc13635 Merge pull request 'fix(tradein/scraper-kit): проброс endpoint= в yandex/cian newbuilding BrowserFetcher (#2322)' (#2356) from fix/tradein-scraper-kit-newbuilding-endpoint into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m30s
Deploy Trade-In / build-backend (push) Successful in 1m18s
Deploy Trade-In / deploy (push) Successful in 1m10s
2026-07-04 00:17:09 +00:00
758d7c6bf8 fix(tradein/estimator): честная маркировка quarter-precision дат ДКП + insufficient_data флаг для sell-time-sensitivity (#1995) (#2355)
Some checks failed
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m36s
Deploy Trade-In / build-backend (push) Successful in 1m7s
Deploy Trade-In / deploy (push) Has been cancelled
2026-07-04 00:14:02 +00:00
bot-backend
ccf716119c fix(tradein/scraper-kit): проброс config= в pipeline.py::fetch_newbuilding call
All checks were successful
CI Trade-In / changes (pull_request) Successful in 8s
CI / changes (pull_request) Successful in 8s
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
CI Trade-In / backend-tests (pull_request) Successful in 1m37s
Найдено при code-review этого же PR (F1, #2349) и независимо подтверждено
F3-аудитом (#2351): run_cian_city_sweep's houses-фаза звала
fetch_newbuilding(zhk_url) без config=, хотя config — mandatory параметр
enclosing-функции, тривиально в scope. Сейчас dormant (USE_KIT_SCHEDULER=False +
cian_city_sweep.enabled=false в SQL seed), но при включении флага/расписания
каждый house молча падал бы AssertionError (перехватывается except → houses_failed,
sweep не крашится целиком, но newbuilding-enrichment был бы 100% failing silently).
2026-07-04 03:12:08 +03:00
bot-backend
b89e0c3daf fix(tradein/scraper-kit): проброс endpoint= в yandex/cian newbuilding BrowserFetcher (#2322) 2026-07-04 03:12:08 +03:00
c4201f7d2a Merge pull request 'fix(tradein/scraper-kit): проброс config= в avito build_warmed_session (#2330)' (#2354) from fix/tradein-avito-warmed-session-config into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m38s
Deploy Trade-In / build-backend (push) Successful in 1m22s
Deploy Trade-In / deploy (push) Successful in 1m36s
2026-07-04 00:04:46 +00:00
c778e4c85d fix(report-ui): ретрай docx-preflight против 502-гонки сразу после ready (#2353)
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 / build-frontend (push) Successful in 3m26s
Deploy / deploy (push) Successful in 1m19s
2026-07-04 00:03:12 +00:00
bot-backend
ecec9ff6d7 fix(tradein/scraper-kit): точность докстрингов про прод-путь build_warmed_session
All checks were successful
CI Trade-In / changes (pull_request) Successful in 10s
CI / changes (pull_request) Successful in 9s
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
CI Trade-In / backend-tests (pull_request) Successful in 1m40s
code-reviewer отметил: формулировка "PROD DEFAULT" в докстрингах могла ввести в
заблуждение — прод-путь сегодня всё ещё легаси (avito_detail_backfill.py
импортирует build_warmed_session из legacy-модуля), этот фикс — advance-prep,
не изменение живого прод-поведения.
2026-07-04 03:01:27 +03:00
bot-backend
fea054d24f fix(tradein/scraper-kit): проброс config= в avito build_warmed_session (#2330) 2026-07-04 02:55:44 +03:00
7ebeddc2bc Merge pull request 'feat(tradein/estimator): switch core valuation call sites to scraper_kit (#2337)' (#2348) from feat/tradein-estimator-kit-switch into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m35s
Deploy Trade-In / build-backend (push) Successful in 59s
Deploy Trade-In / deploy (push) Successful in 44s
2026-07-03 23:49:10 +00:00
36fe33750f fix(report): дата сборки в POST-ответе на fast-path из кэша (последний хвост R2 #2259) (#2347)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-backend (push) Successful in 2m6s
Deploy / build-frontend (push) Successful in 3m36s
Deploy / build-worker (push) Successful in 4m3s
Deploy / deploy (push) Successful in 1m34s
2026-07-03 23:44:19 +00:00
bot-backend
4a6820b8f7 feat(tradein/estimator): switch core valuation call sites to scraper_kit (#2337)
All checks were successful
CI / changes (pull_request) Successful in 9s
CI Trade-In / changes (pull_request) Successful in 9s
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 / frontend-checks (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m48s
Group E4 (final, highest-risk step of scraper_kit migration epic #2277):
estimator.py and house_imv_backfill.py's avito_imv/cian_valuation/
yandex_valuation call sites now import from scraper_kit.providers.* instead
of app.services.scrapers.*, following the exact wiring proven safe by E1/E2/E3
(#2334/#2335/#2336):

- estimator.py's avito IMV (_get_or_fetch_imv_cached, both call sites) and
  house_imv_backfill.py's _process_one_house: add config=RealScraperConfig()
  — kit's evaluate_via_imv silently drops the configured proxy without it.
- estimator.py's cian valuation (Stage 9): add config=RealScraperConfig() —
  mandatory kwarg on the kit function (TypeError if omitted).
- estimator.py's yandex valuation: add config=RealScraperConfig() (mandatory)
  and delay_provider=get_scraper_delay — without it kit silently falls back
  to a hardcoded 5.0s throttle instead of the DB-configured anti-ban delay.
- All exception classes imported consistently from the same kit module as
  evaluate_via_imv (not just the function) — mixing legacy/kit exception
  classes would break `except IMVAddressNotFoundError` etc. via identity
  mismatch (caught by an existing test that assumed the legacy class,
  fixed alongside).

Observability: both cian_valuation and yandex_valuation graceful-degradation
except-blocks upgraded from logger.warning to logger.exception. GlitchTip's
LoggingIntegration listens at event_level=ERROR (main.py/scheduler_main.py) —
a WARNING never reaches GlitchTip as an event regardless of exc_info, so a
future config-wiring mistake at these call sites needs ERROR level to be
visible in monitoring.

house_imv_backfill.py: RealScraperConfig is imported lazily inside
_process_one_house (not at module level) to avoid a circular import —
app.services.scraper_adapters imports backfill_house_imv/
process_houses_imv_batch from this module at module level. Verified via
direct import in both orders plus a full `app.main` import.

Also fixes a stale docstring claiming process_houses_imv_batch is "not wired
into scheduler" — it is, via scrape_pipeline.py's run_avito_city_sweep.

Test updates: 2 pre-existing tests (test_backfill_wave2.py) mocked the legacy
IMVAddressNotFoundError/IMVEvaluation/IMVGeo classes, now updated to import
from scraper_kit to match the production exception identity. Added
config=/delay_provider= regression-guard asserts to the relevant estimator
and backfill tests, mirroring the existing #2306 cian_price_history pattern.

Legacy app/services/scrapers/{avito_imv,cian_valuation,yandex_valuation}.py
are untouched and still imported by cian_history_backfill.py's valuation
block (separately scoped, not touched here) — revert is a clean single-commit
revert, no schema/data migration involved.
2026-07-04 02:40:34 +03:00
5fa505b809 fix(tradein/scrapers): подключить geoportal coords backfill в scheduler (#1967) (#2346)
All checks were successful
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Successful in 52s
Deploy Trade-In / changes (push) Successful in 9s
Deploy Trade-In / test (push) Successful in 1m30s
Deploy Trade-In / deploy (push) Successful in 1m48s
2026-07-03 23:25:47 +00:00
9289c3d69d fix(reports): HEAD-поддержка на /report/download — qa поймал 405, DOCX не скачивался из UI (#2343)
All checks were successful
Deploy / changes (push) Successful in 6s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m0s
Deploy / build-worker (push) Successful in 2m53s
Deploy / deploy (push) Successful in 1m35s
2026-07-03 23:13:23 +00:00
f872f5636b Merge pull request 'test(tradein/scraper-kit): prove yandex_valuation kit path safe for #2337 (#2336)' (#2345) from feat/tradein-migrate-yandex-valuation-kit into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m35s
Deploy Trade-In / build-backend (push) Successful in 28s
Deploy Trade-In / deploy (push) Successful in 46s
2026-07-03 23:04:13 +00:00
aa2b33f264 Merge pull request 'test(tradein/scraper-kit): golden-parity + config-footgun proof for avito_imv (#2334)' (#2344) from feat/tradein-migrate-avito-imv-kit into main
Some checks failed
Deploy Trade-In / test (push) Blocked by required conditions
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / build-frontend (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Has been cancelled
2026-07-03 23:04:11 +00:00
17cf7344b3 Merge pull request 'test(tradein/scraper-kit): prove cian_valuation kit path safe for #2337 (#2335)' (#2342) from feat/tradein-migrate-cian-valuation-kit into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 18s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m40s
Deploy Trade-In / build-backend (push) Successful in 29s
Deploy Trade-In / deploy (push) Successful in 47s
2026-07-03 22:59:44 +00:00
bot-backend
53287da886 test(tradein/scraper-kit): prove cian_valuation kit path safe for #2337 (#2335)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 6s
CI / changes (pull_request) Successful in 7s
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
CI Trade-In / backend-tests (pull_request) Successful in 1m35s
scraper_kit.providers.cian.valuation.estimate_via_cian_valuation (and
session.load_session) already existed with mandatory config: ScraperConfig
(no default) — this was ground prepared ahead of Group E2, not new work here.
This change proves it's safe to switch estimator.py's import to it (#2337):

- Extends the existing _parse_valuation_state golden-parity test with a
  full-pipeline parity test (cache-miss -> load_session -> curl_cffi fetch ->
  extract_state -> auth-check -> parse -> sanity-check), wired with
  config=RealScraperConfig() per the #2306 convention
  (app/services/cian_price_history.py).
- Adds a regression guard proving estimate_via_cian_valuation raises TypeError
  when config= is omitted, and documents why that must stay mandatory:
  estimator.py's call site (line ~3143) sits inside a blanket
  `except Exception` that only does `logger.warning(..., exc)` (no exc_info,
  no logger.exception) -- below GlitchTip's ERROR-level capture threshold
  (see LoggingIntegration(event_level=logging.ERROR) in app/main.py), so a
  TypeError from a missing config= would be logged but invisible in
  GlitchTip/Sentry, indistinguishable from ordinary graceful degradation.
- Documents an asymmetry vs. the task's initial assumption: kit's
  load_session requires config= mandatorily, but mark_session_invalid does
  NOT take a config parameter at all (confirmed by inspection, not a
  footgun -- just noting the actual contract).
- Confirms app/services/estimator.py is not the only real caller:
  app/tasks/cian_history_backfill.py also imports estimate_via_cian_valuation
  directly and deliberately stays on the legacy import for now (see its own
  comment referencing issue #2308) -- out of scope for this change, flagged
  for whoever picks up cian_history_backfill's migration.

Full backend test suite: 3211 passed, 6 skipped, 1 pre-existing unrelated
failure (test_search_api.py::test_search_cache_hit, 401 vs 200 auth issue,
reproduces identically on main without this change).
2026-07-04 01:51:30 +03:00
bot-backend
7546868535 test(tradein/scraper-kit): prove yandex_valuation kit-wiring safety (#2336)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 17s
CI / changes (pull_request) Successful in 16s
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
CI Trade-In / backend-tests (pull_request) Successful in 1m50s
Group E3 recon confirmed `scraper_kit.providers.yandex.valuation` is already a
strangler-copy (#2133) and already used via admin.py's debug route (#2305,
Group A) with the established config=RealScraperConfig()/delay_provider=
get_scraper_delay convention. estimator.py (the real caller, #2337's scope)
still imports the legacy module directly with no arguments -- not touched here.

Adds regression coverage for the two confirmed footguns before #2337 switches
that call site:
- mandatory `config: ScraperConfig` raises TypeError when omitted (same
  discipline as the cian_valuation footgun, #2335)
- optional `delay_provider` silently falls back to hardcoded 5.0s when not
  wired, discarding admin-tuned anti-ban throttling (scraper_settings.
  get_scraper_delay)

Also extends the existing `.parse()` golden-parity test (test_scraper_kit_
yandex_golden_parity.py, SimpleNamespace config) with an assert_parity-based
proof over the REAL production construction path (RealScraperConfig() +
get_scraper_delay), plus a harness-catches-divergence sanity check.

No production code changed -- app/services/scrapers/yandex_valuation.py and
scraper_kit/providers/yandex/valuation.py are both pre-existing.
2026-07-04 01:50:55 +03:00
bot-backend
7049717782 test(tradein/scraper-kit): golden-parity + config-footgun proof for avito_imv (#2334)
All checks were successful
CI Trade-In / changes (pull_request) Successful in 11s
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 11s
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) Successful in 1m56s
Group E1 of the scraper_kit migration epic (#2277 -> #2308 -> #2334): prepares the
kit side of app/services/scrapers/avito_imv.py -> scraper_kit.providers.avito.imv
WITHOUT switching any real call site (estimator.py is #2337, a separate final step;
house_imv_backfill.py is deliberately deferred too, see report).

- Golden-parity: full evaluate_via_imv() async flow (geocode A/B + evaluate C) proven
  byte-identical between legacy and kit on REAL live-captured Avito API responses
  (tests/fixtures/avito_imv_geo_position.json + avito_imv_getdata.json), routed through
  the browser_fetcher transport to stay offline/deterministic. Previously this function
  had zero parity coverage (only _parse_price was covered, via admin.py Group A).
  Added cheap pure-function parity for compute_imv_cache_key/_parse_geo_position/
  _parse_placement_history/_parse_suggestions too.
- Config-footgun regression: kit evaluate_via_imv only reads config.scraper_proxy_url
  when config= is explicitly passed; called bare it silently builds a proxy-less
  curl_cffi session even with a real proxy configured. Two tests lock this down
  (without config= -> proxies=None, with config=RealScraperConfig() -> proxies wired) —
  manually verified by breaking scraper_kit/providers/avito/imv.py's config threading,
  watching the "with config" test fail on the exact proxies assertion, then reverting.

No production import switched in this commit — see PR/issue report for the full
caller audit and the house_imv_backfill.py deferral rationale.
2026-07-04 01:49:21 +03:00
1d9e25ce07 fix(tradein/v2): подключить реальные данные location-coef в LocationDrawer + HeroBar (#2317) (#2341)
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m37s
Deploy Trade-In / build-frontend (push) Successful in 2m12s
Deploy Trade-In / build-backend (push) Successful in 53s
Deploy Trade-In / deploy (push) Successful in 1m9s
2026-07-03 22:47:40 +00:00
e7f97f1355 fix(tradein/avito): консолидировать house_type normalizer + актуализировать docstring (#2009) (#2340)
Some checks failed
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
2026-07-03 22:47:05 +00:00
e3d26f0aae fix(tradein/scrapers): cian_city_sweep честный статус при defensive abort (#1949) (#2339)
Some checks failed
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-backend (push) Blocked by required conditions
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Has been cancelled
2026-07-03 22:45:47 +00:00
49304a78bc feat(ptica/reports): DOCX-скачивание полного отчёта в UI (#2259 R2) (#2338)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Successful in 3m12s
Deploy / build-backend (push) Has been skipped
Deploy / build-worker (push) Has been skipped
Deploy / deploy (push) Successful in 1m19s
2026-07-03 22:40:11 +00:00
f41ca530c5 Merge pull request 'feat(tradein/scraper-kit): migrate backfill/enrichment tasks to kit (#2310)' (#2333) from feat/tradein-migrate-backfill-tasks-kit into main
All checks were successful
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m32s
Deploy Trade-In / build-backend (push) Successful in 55s
Deploy Trade-In / deploy (push) Successful in 1m7s
2026-07-03 22:28:10 +00:00
30e033d653 perf(sql): покрывающий индекс под offer-trend §4.3 — 6.8с → 1.1с (миграция 186) (#2331)
All checks were successful
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 2m2s
Deploy / build-worker (push) Successful in 3m7s
Deploy / deploy (push) Successful in 1m42s
2026-07-03 22:26:29 +00:00
9feadc8458 fix(market-metrics): offer-trend таймаут — warning вместо exception (ложные GlitchTip-события) (#2329)
Some checks failed
Deploy / build-backend (push) Has been cancelled
Deploy / deploy (push) Blocked by required conditions
Deploy / changes (push) Successful in 7s
Deploy / build-frontend (push) Has been skipped
Deploy / build-worker (push) Has been cancelled
2026-07-03 22:26:19 +00:00
bot-backend
116cd10046 test(tradein/scraper-kit): assert config= at avito_detail_backfill call sites (#2310)
All checks were successful
CI / changes (pull_request) Successful in 9s
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 / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI Trade-In / backend-tests (pull_request) Successful in 1m39s
Code-review follow-up: the Group C regression tests for the fetch_detail
backconnect footgun and AvitoScraper's config requirement proved the KIT
LIBRARY behavior in isolation, but nothing asserted the actual call sites in
avito_detail_backfill.py still pass config=RealScraperConfig() at fetch_detail
and AvitoScraper construction. Mirrors #2306's test_backfill_wave2.py:282-286
pattern -- isinstance-checks the captured call_args instead of a bare
assert_called().

Verified the new assertions actually catch the regression: temporarily
removed both config=RealScraperConfig() call-site args from
avito_detail_backfill.py, confirmed test_backfill_processes_snapshot_to_completion
fails exactly on the new assertion line, then restored (git diff was empty
afterward).

Refs #2310
2026-07-04 01:22:50 +03:00
bot-backend
eb564cfc01 feat(tradein/scraper-kit): migrate backfill-task imports to kit, Group C (#2310)
Migrates legacy app.services.scrapers.* imports to scraper_kit equivalents for
house_imv_backfill.py, avito_detail_backfill.py, cian_history_backfill.py,
ekb_geoportal_ingest.py, and yandex_detail_backfill.py, proving parity via
tests/support/parity.assert_parity per the epic's gate (#2304).

newbuilding_enrich_backfill.py and yandex_newbuilding_sweep.py are left fully
on legacy imports: both call into scraper_kit.providers.{cian,yandex}.newbuilding,
which construct BrowserFetcher(source=...) without the now-mandatory endpoint=
kwarg (issue #2322, verified still open against the actual provider source, not
just issue status) -- no caller-side fix is possible, matching Group A's (#2305)
precedent for the same bug in admin.py.

Config-gated kit function footguns found and fixed (Group B #2306 pattern):
  - avito fetch_detail's backconnect-on-403 retry silently drops when config=
    is omitted -- now passes config=RealScraperConfig() explicitly, with a
    regression test proving the gate.
  - kit AvitoScraper's constructor now requires ScraperConfig positionally --
    wired via RealScraperConfig(), which _rotate_ip() reads for
    avito_proxy_rotate_url.
  - BrowserFetcher(source=...) call sites (house_imv_backfill, avito/cian
    detail backfills) now pass the mandatory endpoint=settings.browser_http_endpoint.

New footgun discovered (NOT #2322, flagged for follow-up): kit's
build_warmed_session() builds its curl_cffi session via _build_detail_session()
with no config parameter at all, unlike fetch_detail -- migrating it would
silently drop the sticky MGTS-proxy egress on avito_detail_backfill's
warm-batch path (the prod default). Left build_warmed_session/
_AVITO_WARM_SEARCH_URL on legacy imports, documented inline.

Refs #2310
2026-07-04 01:19:34 +03:00
793234cff1 fix(tradein/v2): гейтить PDF-кнопку на hasEstimate (#2081 M4) (#2332)
All checks were successful
Deploy Trade-In / changes (push) Successful in 10s
Deploy Trade-In / test (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / build-backend (push) Has been skipped
Deploy Trade-In / build-frontend (push) Successful in 1m56s
Deploy Trade-In / deploy (push) Successful in 42s
2026-07-03 22:16:00 +00:00
308eeac214 fix(tradein/scrapers): wire proxy_pool into Avito legacy pipeline, rotate on ban (#2202) (#2328)
All checks were successful
Deploy Trade-In / changes (push) Successful in 15s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m34s
Deploy Trade-In / build-backend (push) Successful in 1m5s
Deploy Trade-In / deploy (push) Successful in 59s
2026-07-03 21:48:15 +00:00
01f2c5290d fix(freshness): пороги nspd_geo под on-demand каденцию (убирает еженедельный ложный stale) (#2325)
All checks were successful
Deploy / changes (push) Successful in 8s
Deploy / build-frontend (push) Has been skipped
Deploy / build-backend (push) Successful in 1m50s
Deploy / build-worker (push) Successful in 3m3s
Deploy / deploy (push) Successful in 1m43s
2026-07-03 21:46:30 +00:00
7fd80adfa7 fix(tradein/pdf): sold-price consistency + актуальные допущения + свой дизайн отчёта (#2327)
All checks were successful
Deploy Trade-In / changes (push) Successful in 12s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m38s
Deploy Trade-In / build-backend (push) Successful in 1m4s
Deploy Trade-In / deploy (push) Successful in 56s
2026-07-03 21:43:40 +00:00
86af5b78bf Merge pull request 'feat(tradein/scraper-kit): migrate admin debug endpoints + domclick ingest to kit (#2305)' (#2326) from feat/tradein-migrate-admin-debug-kit into main
Some checks failed
Deploy Trade-In / deploy (push) Blocked by required conditions
Deploy Trade-In / changes (push) Successful in 11s
Deploy Trade-In / build-frontend (push) Has been skipped
Deploy Trade-In / build-browser (push) Has been skipped
Deploy Trade-In / test (push) Successful in 1m43s
Deploy Trade-In / build-backend (push) Has been cancelled
2026-07-03 21:41:11 +00:00