Skip to content

fix: harden South Kesteven scraper and Home Assistant runtime - #2180

Open
Dozi3 wants to merge 14 commits into
robbrad:masterfrom
Dozi3:codex/skdc-ha-hardening-0.170.6
Open

fix: harden South Kesteven scraper and Home Assistant runtime#2180
Dozi3 wants to merge 14 commits into
robbrad:masterfrom
Dozi3:codex/skdc-ha-hardening-0.170.6

Conversation

@Dozi3

@Dozi3 Dozi3 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Review status: All upstream checks pass. Ready for maintainer review,
with particular attention requested for the cross-council import sweep and
release-workflow changes.

This PR hardens the South Kesteven District Council (SKDC) scraper and the
Home Assistant/Selenium path that runs it.

  • Reworks SKDC to use one bounded remote-browser session from the public
    /binday page, without the standalone HTTP preflight that could receive a
    403 even when the browser flow remained usable.
  • Detects and explains Home Assistant dependency shadowing before Selenium
    imports the wrong top-level websocket package.
  • Defers browser-only imports so a Selenium dependency problem cannot prevent
    non-Selenium councils from loading.
  • Preserves the existing collection JSON shape and sensor/calendar identity
    contracts while tightening argument propagation, migrations, refresh
    coordination, diagnostics, redaction, and WebDriver cleanup.
  • Adds deterministic package, Home Assistant, release-contract, and isolated
    runtime validation.

This is follow-up hardening to the SKDC work discussed in #1928 and #2000,
originally reviewed in #2121 and incorporated through #2154. It is not a
resubmission of the original scraper change.

Detailed implementation and validation notes are in
docs/south-kesteven-ha-hardening-candidate.md.

Root cause

The reported Home Assistant failure happened before the SKDC scraper ran.
Selenium imports websocket-client as the top-level module websocket, but
Home Assistant's /config path contained another top-level
/config/websocket/__init__.py. Python loaded that file instead, and its
parent-relative import failed with:

ImportError: attempted relative import beyond top-level package

The failure was consequently presented as a repeatedly retried generic
coordinator error. Independently, SKDC's generic requests.get() preflight
could receive an environment-dependent 403 before the real browser workflow
was attempted.

What changed

South Kesteven

  • Starts at https://www.southkesteven.gov.uk/binday and follows only the
    supported HTTPS self-service checker.
  • Uses one Selenium session and removes the separate HTTP preflight.
  • Selects a property by exact normalized house-number or house-name match;
    missing and ambiguous matches fail explicitly.
  • Distinguishes browser denial, address mismatch, site drift, timeout, and
    WebDriver unavailability.
  • Bounds page and element waits to 30 seconds, the scraper to 90 seconds, and
    the Home Assistant outer wait to 125 seconds.
  • Always closes the WebDriver in finally.
  • Keeps diagnostic artifacts opt-in and redacted.

Core package

  • Resolves council modules from a validated registry using fully qualified
    package names instead of modifying sys.path.
  • Validates that websocket belongs to the installed websocket-client
    distribution before Selenium is imported.
  • Moves Selenium and other browser-only imports out of module scope.
  • Adds typed errors for dependency shadowing, missing optional dependencies,
    browser failures, upstream denial, address mismatch, and site drift.
  • Redacts household identifiers and identifier-bearing URLs from normal logs.
  • Propagates supported USRN, user-agent, WebDriver, and Boolean flag options
    consistently.
  • Removes Birmingham's undeclared yarl dependency.

Home Assistant

  • Replaces generic argument forwarding with an explicit typed mapping;
    Boolean options are emitted as flags rather than --flag=True.
  • Adds sequential config-entry migration to schema version 4 and normalizes
    legacy PAON/house-number, WebDriver, and Boolean aliases.
  • Requires reconfiguration for incomplete historical SKDC entries instead of
    guessing address or browser values.
  • Uses the same normalized council registry in setup, options, and
    reconfiguration flows.
  • Creates actionable Repairs for dependency shadowing, incomplete
    configuration, and unavailable Selenium.
  • Corrects manual-refresh scheduling, serializes per-entry refresh work, and
    removes the calendar platform's duplicate initial scrape.
  • Retains existing collection payload and entity-identity contracts.

CI and release safety

  • Adds Python 3.14 coverage and exact Home Assistant compatibility checks.
  • Separates deterministic parser contracts from scheduled live canaries.
  • Pins changed third-party Actions to immutable commit SHAs.
  • Adds reproducible-wheel, manifest-pinning, release-order, PyPI digest, and
    rollback checks.

Review scope

This is intentionally broader than a one-file council fix: 199 files change
with approximately 13,506 additions and 3,654 deletions, including 122 council
adapters. Most council changes are mechanical import deferral and log
redaction; 83 adapters move Selenium imports out of module scope. That sweep
is what prevents a browser-stack collision from breaking unrelated imports.

Suggested review order:

  1. 183afcbe for the functional core, SKDC, and Home Assistant changes.
  2. uk_bin_collection/uk_bin_collection/councils/SouthKestevenDistrictCouncil.py.
  3. uk_bin_collection/uk_bin_collection/dependency_validation.py,
    collect_data.py, and shared WebDriver helpers.
  4. custom_components/uk_bin_collection migration, coordinator, and Repair
    behavior.
  5. The mechanical council import changes.
  6. The subsequent focused test and runtime-safety commits.

The branch is based directly on current upstream master
(36d920520e4a4c64fb6278557d357b948bf95e88), is 14 commits ahead, and is not
behind upstream.

Validation

For the exact runtime/documentation candidate
0dd7060d71998a254812666a6cc7ae5af7e89d43:

  • 309 deterministic tests passed in a clean clone on Python 3.12.
  • The 30-test SKDC parser contract passed in a dedicated rerun.
  • All 352 registered council modules imported successfully.
  • Two isolated wheel builds were byte-for-byte identical:
    FA950C5EC71603B28EF6322EDF6A2BFC9E5807BB7191669011A42C2C79D2C5B3.
  • Core/component version, wheel metadata, Python >=3.12,<3.15, release
    contract, and manifest-pinning checks passed.
  • The functional runtime parent (9139a7a0) passed the focused changed-code
    selection on Python 3.12, 3.13, and 3.14: 145 tests on each runtime.
  • HassFest passed on the fork branch. The fork HACS action's only failures
    were repository-level metadata checks because Issues are disabled and the
    fork has no repository topics.

Commit 07d5de7890a49b24d71f5fdcbc4ff49d710ae6ed adds only two
upstream-CI compatibility corrections discovered by the first PR run: the
observed Python 3.13 mapping for HA 2026.1/2026.2, and removal of calendar-test
autospeccing that evaluated an unresolved EntityPlatform annotation inside
HA 2026.4/2026.5.

Current branch tip fc133d3cbed66482a659edf24715645bb4f9eb46 adds only focused
behavioral tests for the coverage gaps reported by that first run. In a clean
checkout, the exact non-live suite passed 348 tests (2 deselected) and measured
88% project coverage, above the 86.89% upstream baseline. The release scripts
reached 100%, collect_data.py 99%, shared helpers 95%, and SKDC 89%. Neither
CI follow-up commit changes integration runtime code; the upstream matrix is
rerun by this PR.

At this head, all 27 upstream checks pass, including Python 3.12/3.13/3.14
unit tests, deterministic integration tests, CodeQL, HACS, HassFest, release
prerequisites, Codecov patch/project gates, and Home Assistant 2025.12.5,
2026.1.3 through 2026.7.2, and dev.

The exact runtime candidate was also exercised in a controlled, reversible
trial on Home Assistant 2026.7.2/Python 3.14 with remote Selenium 4.46.0:

  • one real SKDC lookup using the repository's public test fixture succeeded;
  • 10 integration devices and 36 entities were present with populated sensor
    and calendar data;
  • no UK Bin Collection entity was displayed as unavailable or unknown;
  • the original relative-import failure and generic UKBCD unexpected-error
    tracebacks did not recur; and
  • Selenium returned to ready state with zero active sessions.

No private address, token, server address, backup location, or raw live log is
included in this PR.

Compatibility and limitations

  • SKDC was the only council exercised against a live council service. Other
    councils are covered by deterministic tests and import isolation; this is
    not a claim that every external council website was live-tested.
  • New English form, validation, and Repair strings still need translation
    synchronization for Welsh, Irish, Scottish Gaelic, and Portuguese.
  • Broader TLS/network-client centralization, the collection-event model,
    supplier adapters, and registry caching remain out of scope.

Release boundary

This source branch is not itself a HACS release. Its development manifest
still requests uk-bin-collection>=0.170.6, while the already-published
0.170.6 wheel predates this candidate. The successful live trial therefore
used a separately built, SHA-256-pinned prerelease wheel.

The added release workflow is intended to handle the durable path atomically:
assign a new version, publish and verify the matching core artifact, exact-pin
the component manifest, and only then publish the component/tag. The branch
should not be manually tagged or advertised as directly installable before
that release sequence completes.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Too many files!

This PR contains 198 files, which is 98 over the limit of 100.

To get a review, narrow the scope:
• coderabbit review --type committed # exclude uncommitted changes
• coderabbit review --dir # limit to a subdirectory
• coderabbit review --base # compare against a closer base

Upgrade to a paid plan to raise the limit.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f6fff0e3-9419-4295-a3af-d03eaf741210

📥 Commits

Reviewing files that changed from the base of the PR and between 36d9205 and fc133d3.

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (198)
  • .github/commitizen-requirements.txt
  • .github/workflows/behave_pull_request.yml
  • .github/workflows/behave_schedule.yml
  • .github/workflows/bump.yml
  • .github/workflows/codeql-analysis.yml
  • .github/workflows/docker-image.yml
  • .github/workflows/ha_compatibility_test.yml
  • .github/workflows/hacs_validation.yml
  • .github/workflows/lint.yml
  • .github/workflows/release.yml
  • .github/workflows/rollback-release.yml
  • .github/workflows/validate-release-ready.yml
  • .github/workflows/wiki.yml
  • .gitignore
  • Makefile
  • conftest.py
  • custom_components/uk_bin_collection/__init__.py
  • custom_components/uk_bin_collection/calendar.py
  • custom_components/uk_bin_collection/config_flow.py
  • custom_components/uk_bin_collection/const.py
  • custom_components/uk_bin_collection/sensor.py
  • custom_components/uk_bin_collection/strings.json
  • custom_components/uk_bin_collection/tests/common_utils.py
  • custom_components/uk_bin_collection/tests/test_calendar.py
  • custom_components/uk_bin_collection/tests/test_config_flow.py
  • custom_components/uk_bin_collection/tests/test_init.py
  • custom_components/uk_bin_collection/tests/test_sensor.py
  • custom_components/uk_bin_collection/translations/en.json
  • docs/south-kesteven-ha-hardening-candidate.md
  • pyproject.toml
  • scripts/pin_release_manifest.py
  • scripts/validate_release_contract.py
  • tests/__init__.py
  • tests/disposable_ha/Compatibility.Containerfile
  • tests/disposable_ha/Containerfile
  • tests/disposable_ha/FixtureCouncil.py
  • tests/disposable_ha/ImportGate.Containerfile
  • tests/disposable_ha/LIVE_CANARY.md
  • tests/disposable_ha/LiveCanary.Containerfile
  • tests/disposable_ha/LiveProxy.Containerfile
  • tests/disposable_ha/SouthKestevenFixtureCouncil.py
  • tests/disposable_ha/WheelBuilder.Containerfile
  • tests/disposable_ha/__init__.py
  • tests/disposable_ha/collision_probe.py
  • tests/disposable_ha/containerignore
  • tests/disposable_ha/fixture_server.py
  • tests/disposable_ha/import_all_councils.py
  • tests/disposable_ha/live_allowlist_proxy.py
  • tests/disposable_ha/live_canary_runner.py
  • tests/disposable_ha/live_canary_safety_check.py
  • tests/disposable_ha/migration_runner.py
  • tests/disposable_ha/offline_runner.py
  • tests/disposable_ha/pod_safety_check.py
  • tests/disposable_ha/prepare_config.py
  • tests/disposable_ha/test_live_canary_harness.py
  • tests/disposable_ha/test_migration_runner.py
  • tests/disposable_ha/test_offline_runner.py
  • tests/disposable_ha/test_runtime_requirements.py
  • tests/disposable_ha/test_safety_validators.py
  • tests/disposable_ha/verify_runtime_requirements.py
  • tests/test_pin_release_manifest.py
  • tests/test_release_workflow_order.py
  • tests/test_validate_release_contract.py
  • tests/test_workflow_actions_pinned.py
  • uk_bin_collection/tests/test_birmingham_city_council.py
  • uk_bin_collection/tests/test_collect_data.py
  • uk_bin_collection/tests/test_common_functions.py
  • uk_bin_collection/tests/test_core_import_hardening.py
  • uk_bin_collection/tests/test_council_log_redaction.py
  • uk_bin_collection/uk_bin_collection/collect_data.py
  • uk_bin_collection/uk_bin_collection/common.py
  • uk_bin_collection/uk_bin_collection/councils/AdurAndWorthingCouncils.py
  • uk_bin_collection/uk_bin_collection/councils/AngusCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ArgyllandButeCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ArunCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/AshfieldDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/AshfordBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BaberghDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BarkingDagenham.py
  • uk_bin_collection/uk_bin_collection/councils/BarnetCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BasildonCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BexleyCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BirminghamCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BlaenauGwentCountyBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BoltonCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BostonBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BrentCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BrightonandHoveCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BroadlandDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BromleyBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BroxbourneCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BroxtoweBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/BuckinghamshireCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/CanterburyCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/CardiffCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/CastlepointDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/CeredigionCountyCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ChelmsfordCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ChesterfieldBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ChichesterDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ColchesterCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/CotswoldDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/CroydonCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/DacorumBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/DerbyshireDalesDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/DurhamCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/EastLindseyDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/EastRenfrewshireCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/EastStaffordshireBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/EastSuffolkCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/EastleighBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/EnfieldCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/EpsomandEwellBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/FalkirkCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/FifeCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ForestOfDeanDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/GatesheadCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/GlasgowCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/GloucesterCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/GreatYarmouthBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/GuildfordCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/HaltonBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/HerefordshireCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/HertsmereBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/HighPeakCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/Hillingdon.py
  • uk_bin_collection/uk_bin_collection/councils/HyndburnBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/IsleOfAngleseyCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/IsleOfWightCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/KingstonUponThamesCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/KnowsleyMBCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/LeedsCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/LondonBoroughHarrow.py
  • uk_bin_collection/uk_bin_collection/councils/LondonBoroughRedbridge.py
  • uk_bin_collection/uk_bin_collection/councils/MaidstoneBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ManchesterCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/MeltonBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/MidSuffolkDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/MidSussexDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/MidUlsterDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/MiddlesbroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/MidlothianCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NeathPortTalbotCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NewForestCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NewportCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NorthDevonCountyCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NorthEastDerbyshireDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NorthHertfordshireDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NorthNorfolkDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NorthTynesideCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NorthumberlandCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/NuneatonBedworthBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/PembrokeshireCountyCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/PeterboroughCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/PortsmouthCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/PrestonCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ReigateAndBansteadBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/RotherhamCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/RoyalBoroughofGreenwich.py
  • uk_bin_collection/uk_bin_collection/councils/RushcliffeBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SandwellBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SevenoaksDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SomersetCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SouthGloucestershireCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SouthKestevenDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SouthLanarkshireCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SouthTynesideCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/StHelensBC.py
  • uk_bin_collection/uk_bin_collection/councils/StaffordshireMoorlandsDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/StocktonOnTeesCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/StroudDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/SwaleBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/TeignbridgeCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/TendringDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/TestValleyBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/TewkesburyBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ThanetDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/ThreeRiversDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/TorbayCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/TorfaenCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/TowerHamletsCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/UttlesfordDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WakefieldCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WalsallCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WalthamForest.py
  • uk_bin_collection/uk_bin_collection/councils/WestBerkshireCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WestDevonBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WestLothianCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WestOxfordshireDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WinchesterCityCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WirralCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WrexhamCountyBoroughCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/WychavonDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/tests/test_south_kesteven_district_council.py
  • uk_bin_collection/uk_bin_collection/councils/tests/test_south_kesteven_integration.py
  • uk_bin_collection/uk_bin_collection/dependency_validation.py
  • uk_bin_collection/uk_bin_collection/exceptions.py
  • uk_bin_collection/uk_bin_collection/get_bin_data.py

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • Review on demand using usage pricing
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 91.73838% with 48 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.74%. Comparing base (36d9205) to head (fc133d3).
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...ollection/councils/SouthKestevenDistrictCouncil.py 88.96% 32 Missing ⚠️
uk_bin_collection/uk_bin_collection/common.py 83.54% 13 Missing ⚠️
conftest.py 57.14% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2180      +/-   ##
==========================================
+ Coverage   86.89%   87.74%   +0.85%     
==========================================
  Files           9       11       +2     
  Lines        1160     1102      -58     
==========================================
- Hits         1008      967      -41     
+ Misses        152      135      -17     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

@Dozi3
Dozi3 marked this pull request as ready for review July 19, 2026 23:03
Copilot AI review requested due to automatic review settings July 19, 2026 23:03
@Dozi3

Dozi3 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

@robbrad This is now ready for maintainer review. All 27 upstream checks pass, including the Python 3.12/3.13/3.14 suites, deterministic integration tests, Codecov, and the full Home Assistant compatibility matrix. The PR description includes the live SKDC validation evidence, cross-council scope, suggested review order, and the release-boundary caveat. I am happy to split the import isolation, SKDC, Home Assistant, and release-workflow changes if that would make review easier.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot wasn't able to review this pull request because it exceeds the maximum number of lines (20,000). Try reducing the number of changed lines and requesting a review from Copilot again.

robbrad commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Flagging this for dedicated maintainer review rather than folding it into the routine "July Part 2" consolidation (#2189).

This PR is a 199-file, +13,506/-3,654 line change touching 83 council adapters, core module resolution, the Home Assistant config-entry migration path, and the release/CI workflow itself. That's a much larger blast radius than a typical council fix or hardening patch, and it's not something that should go through a batch consolidation alongside routine dependency bumps and single-council fixes — it deserves its own focused review pass by @robbrad, ideally reading the commits in the order the PR description itself suggests.

Not making any judgment on correctness here — all 26 CI checks do pass — just noting the scope warrants a closer look before merge given how much surface area it touches (including release-process changes). No action taken on this PR; leaving it open for you to review.


Generated by Claude Code

robbrad commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Thanks for the detailed writeup — before this can get a proper review, could you help break down why the diff is ~200 files / +13.5k / -3.6k for what's described as an SKDC scraper + HA runtime hardening fix?

Looking at the actual file list, this appears to bundle at least four distinct changes:

  1. The stated fix: SouthKestevenDistrictCouncil.py (558 lines) + its new test file, plus deferring Selenium imports into function scope (behind ensure_selenium_dependencies()) for the ~15-20 councils that actually use Selenium (Broxbourne, Basildon, Forest of Dean, Cotswold, Epsom & Ewell, Boston, Isle of Wight, etc.).
  2. A repo-wide print-statement redaction sweep across roughly 100 other council files that don't touch Selenium at all (Canterbury, Castlepoint, Derbyshire Dales, Glasgow, Melton, Nuneaton & Bedworth, Pembrokeshire, South Tyneside, Stroud, Walsall, and more) — replacing print(collection) / print(data) / print(bin_day_response.content) with generic messages. Looks like a reasonable privacy cleanup on its own, but unrelated to the SKDC/websocket-shadowing fix.
  3. A new tests/disposable_ha/ directory — 27 files, ~4,300 lines: Containerfiles, a fixture server, migration runner, offline runner, live-canary safety checks, an allowlisted live proxy, etc. This looks like a substantial new test harness rather than something needed to fix SKDC.
  4. A rewrite of all 12 GitHub Actions workflow files, including release.yml, bump.yml, and ha_compatibility_test.yml, plus root-level Makefile/conftest.py/pyproject.toml changes.

Given the size and that this touches the release pipeline and 100+ unrelated councils, would you be open to splitting this into separate PRs — the actual SKDC fix + Selenium import deferral as one, the print-redaction sweep as another, the new test harness and CI/release changes as their own? That would make each piece reviewable on its own merits, and it's hard for a maintainer to sign off on the release-workflow and cross-council changes bundled in with a single-council bugfix.

Not passing judgment on whether the individual pieces are good — just flagging that "SKDC hardening" undersells what's actually in the diff, and a maintainer needs to understand why each piece is necessary before merging something this broad.


Generated by Claude Code

@robbrad robbrad self-assigned this Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants