Skip to content

July Part 2: consolidated PR fixes + Fenland, MSDC issue fixes - #2189

Merged
robbrad merged 9 commits into
masterfrom
claude/open-issues-rkmshu
Jul 25, 2026
Merged

July Part 2: consolidated PR fixes + Fenland, MSDC issue fixes#2189
robbrad merged 9 commits into
masterfrom
claude/open-issues-rkmshu

Conversation

@robbrad

@robbrad robbrad commented Jul 25, 2026

Copy link
Copy Markdown
Owner

Summary

This consolidates the vetted open PRs from the last week into a single release, tested together on one branch, plus two issue fixes picked up along the way.

From PR consolidation

Issue fixes picked up in the same pass

  • fix(ha): correct inverted manual_refresh_only logic, expose Fenland postcodemanual_refresh_only was wired backwards (True enabled polling, False disabled it). Also declared a postcode field for Fenland in input.json so the config flow actually exposes it — Fenland's API only understands its own PremiseID, not a national UPRN, so without a postcode field, users could only enter a UPRN that gets misused as a raw PremiseID, causing the reported 500s. Fixes Error 500 - Fenland #2174.
  • feat(midsuffolk): surface the Following Collection Date column — the results table already includes a "Following Collection Date" column that was never read. Now emitted as a second entry per bin type. Fixes [Enhancement] Future Collection Dates #1986.

Not included

#2180 ("harden South Kesteven scraper and Home Assistant runtime") is intentionally excluded. It's a 199-file, +13,506/-3,654 line change touching 83 council adapters, the release workflow, and HA config-migration logic. All 26 of its CI checks pass, but a change of that size and blast radius needs dedicated maintainer review rather than being folded into a routine consolidation — I've left a comment on that PR flagging it for review.

Test plan

  • poetry install on Python 3.12, ran the non-live unit suite (uk_bin_collection/tests/test_*.py excluding the live BDD suite, plus custom_components/uk_bin_collection/tests/): 227 passed, 3 pre-existing failures unrelated to this change (sandbox blocks api.postcodes.io and has no Chrome binary — confirmed these also fail on master).
  • black --check clean on all changed files.
  • poetry check --lock clean after resolving a poetry.lock merge conflict between the pillow and setuptools bumps.
  • Added regression tests: 4 for the Lichfield card-pairing fix, 2 for the manual_refresh_only polarity fix, 3 for the MidSuffolk following-date extraction — all pass.
  • Manually verified the Bedfordshire parser against synthetic fixture HTML, including the duplicate-collection de-dup path.
  • Live scraper verification against the real Lichfield/Bedfordshire/Cardiff/Blackburn/MidSuffolk sites was not possible from this sandbox (outbound proxy blocks arbitrary council domains) — worth a live smoke test before/after merge if you can run one locally.

Summary by CodeRabbit

  • Improvements
    • Enhanced collection schedule parsing for Bedfordshire and Lichfield, including more accurate collectionDate computation (leap-year handling, year rollover), improved bin naming (multi-word bins), and de-duplication.
    • Improved automatic refresh scheduling: manual refresh disables polling; automatic refresh uses the configured interval.
  • Bug Fixes
    • Corrected Blackburn and Cardiff council website links.
    • Updated Fenland instructions to clarify postcode vs PremiseID behavior.
  • Tests / Chores
    • Expanded council parsing tests (Lichfield, Mid Suffolk) and added coordinator scheduling coverage.
    • Updated CI workflows to use the newer Python setup action version.

deal0f49-21 and others added 6 commits July 25, 2026 19:53
Cardiff Council's url was set to the generic gov.uk homepage instead
of cardiff.gov.uk, and Blackburn with Darwen's was set to Blaby's
domain (a completely unrelated council). Found while building an
attribution feature that surfaces each council's own url field to end
users, which is used correctly for the actual scraper logic (both
entries have skip_get_url: true so this didn't affect date-fetching),
but was factually wrong for display/reference purposes.

Verified the correct domains directly against each council's real
website before fixing.
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 6 to 7.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v6...v7)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [pillow](https://github.com/python-pillow/Pillow) from 12.1.1 to 12.3.0.
- [Release notes](https://github.com/python-pillow/Pillow/releases)
- [Changelog](https://github.com/python-pillow/Pillow/blob/main/CHANGES.rst)
- [Commits](python-pillow/Pillow@12.1.1...12.3.0)

---
updated-dependencies:
- dependency-name: pillow
  dependency-version: 12.3.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Bumps [setuptools](https://github.com/pypa/setuptools) from 78.1.1 to 83.0.0.
- [Release notes](https://github.com/pypa/setuptools/releases)
- [Changelog](https://github.com/pypa/setuptools/blob/main/NEWS.rst)
- [Commits](pypa/setuptools@v78.1.1...v83.0.0)

---
updated-dependencies:
- dependency-name: setuptools
  dependency-version: 83.0.0
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
Central Bedfordshire's site changed to a new waste-collection-schedule
page layout with duplicated entries. Re-derive bins from the new
li.waste-collection__day markup, mapping raw type strings back to the
original bin names, and de-duplicate repeated entries.

Fixes #2185. Adapted from PR #2186 by ChadH360.
LichfieldDistrictCouncil zipped a page-wide heading list and a
page-wide date list together by index. Two things on the current page
break that: the calendar-download link reuses the heading class but
has no date, and a bin with no scheduled collection (Food Waste Caddy)
renders a "Collected every <day>" frequency instead of a date. Either
one shifts every later bin onto the wrong date and drops the last bin.

Iterate each card and read its own date instead of pairing by
position. When a card has no date but does have a weekly frequency,
derive the next occurrence of that weekday so the entity keeps
reporting (previously it silently inherited a neighboring bin's date).
Extract the bin name by removing the visually-hidden heading spans
rather than slicing words, so three-word names like "Food Waste Caddy"
survive; that value is then mapped back to "Food Waste" to preserve
the existing Home Assistant entity identity. Also fix year rollover to
compare against today's date directly instead of a month heuristic.

Synthesizes PR #2179 by JasSmiths and PR #2187 by alec-pinson, which
independently reported and fixed this bug.
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6b31ff95-a296-406b-bd2f-28e44a779ba7

📥 Commits

Reviewing files that changed from the base of the PR and between 40702ba and dc0a876.

📒 Files selected for processing (4)
  • uk_bin_collection/tests/test_lichfield_district_council.py
  • uk_bin_collection/tests/test_mid_suffolk_district_council.py
  • uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/MidSuffolkDistrictCouncil.py

📝 Walkthrough

Walkthrough

The pull request updates three council collection parsers, adds parser tests, clarifies refresh scheduling behavior, upgrades GitHub Actions Python setup steps, and corrects council test configuration data.

Changes

Council parser updates

Layer / File(s) Summary
Bedfordshire schedule parsing
uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py
Bedfordshire parsing now fetches schedules by UPRN, validates responses, parses collection dates and types, and removes duplicate entries.
Lichfield card parsing and tests
uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py, uk_bin_collection/tests/test_lichfield_district_council.py
Lichfield parsing processes cards individually, handles explicit and recurring dates, preserves bin names, skips invalid cards, and adds fixture-based tests.
Mid Suffolk table parsing and tests
uk_bin_collection/uk_bin_collection/councils/MidSuffolkDistrictCouncil.py, uk_bin_collection/tests/test_mid_suffolk_district_council.py
Mid Suffolk parsing uses a helper for next and following collection dates, missing tables, empty cells, and invalid dates, with corresponding tests.

Integration refresh scheduling

Layer / File(s) Summary
Refresh scheduling behavior
custom_components/uk_bin_collection/__init__.py, custom_components/uk_bin_collection/tests/test_init.py
Manual refresh mode sets no update interval, while automatic mode uses the validated configured interval; both paths are tested.

Workflow and council data updates

Layer / File(s) Summary
GitHub Actions Python setup
.github/workflows/*.yml
Seven workflows replace actions/setup-python@v6 with @v7.
Council test data corrections
uk_bin_collection/tests/input.json
Blackburn and Cardiff URLs are corrected, and Fenland guidance describes postcode lookup and UPRN override behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

  • Error 500 - Fenland #2174: Covers the Fenland configuration guidance and manual_refresh_only behavior updated in this pull request.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is relevant to the changeset and mentions two of the issue-fix areas, though it is broader than the main workflow and parser updates.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/open-issues-rkmshu

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 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.33962% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.23%. Comparing base (36d9205) to head (dc0a876).
⚠️ Report is 11 commits behind head on master.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
...n_collection/councils/MidSuffolkDistrictCouncil.py 85.00% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2189      +/-   ##
==========================================
- Coverage   86.89%   83.23%   -3.67%     
==========================================
  Files           9       11       +2     
  Lines        1160     1306     +146     
==========================================
+ Hits         1008     1087      +79     
- Misses        152      219      +67     

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

claude added 2 commits July 25, 2026 20:05
…ostcode

manual_refresh_only was wired backwards: setting it to True switched
the coordinator into automatic polling, and False disabled polling
entirely. Swap the branches so True means no automatic updates and
False means poll on update_interval, matching the option's name.

Separately, Fenland's config-flow schema only exposed a UPRN field.
Fenland's API doesn't understand national UPRNs, only its own numeric
PremiseID, so any real UPRN entered there was sent straight through as
premisesid and rejected by the council API with a 500. Declare a
postcode in Fenland's input.json entry so the integration's own
postcode-to-PremiseID resolution (already implemented in
FenlandDistrictCouncil._resolve_premise) is reachable from the config
flow instead of being dead code.

Fixes #2174.
The results table already includes a "Following Collection Date"
column alongside the next one, but the parser only ever read the
"Next collection" cell. Extract the table parsing into a testable
helper and emit a second entry per bin type from that column when
present, so a second future collection date is available rather than
just the nearest one.

Fixes #1986.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (3)
uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py (1)

15-78: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Missing automated regression tests for the rewritten parser.

This is a full rewrite of the schedule-fetching and card-parsing logic, but no pytest module was added for Bedfordshire (per the PR description, only manual synthetic-HTML testing was done). The Lichfield changes in this same PR added fixture-based regression tests (test_lichfield_district_council.py) that mock requests.get/datetime — the same pattern could be reused here to lock in the new UPRN-based parsing, dedup, and type-mapping behavior.

Would you like me to draft a test_bedfordshire_council.py module using synthetic HTML fixtures, mirroring the Lichfield test pattern?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py` around
lines 15 - 78, Add a pytest module for BedfordshireCouncil.parse_data, mirroring
the fixture-based pattern used by the Lichfield council tests. Mock requests.get
and datetime as needed, and cover UPRN-based URL fetching, successful synthetic
HTML parsing, duplicate bin suppression, type mapping, and relevant
invalid-response or malformed-element errors.
uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py (2)

66-73: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Feb 29 crash in explicit-date parsing has no regression coverage. The root-cause bug (strptime defaulting to non-leap year 1900, raised separately) means a real 29 February collection date would crash the whole parse — and none of the four new fixture tests would catch it.

  • uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py#L66-L73: fix the leap-year handling as proposed in the per-site comment (parse with an explicit reference year, retry across the year boundary).
  • uk_bin_collection/tests/test_lichfield_district_council.py#L104-L114: once fixed, add a regression test replacing a fixture date with "29th February" and asserting it resolves to the correct leap year instead of raising.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py`
around lines 66 - 73, The explicit-date parsing in LichfieldDistrictCouncil must
handle 29 February without relying on strptime’s default year: parse using
now.year, retry with now.year + 1 when the date falls across the year boundary,
and retain the existing rollover behavior. In
uk_bin_collection/tests/test_lichfield_district_council.py lines 104-114,
replace a fixture date with “29th February” and assert it resolves to the
correct leap year without raising.

82-84: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Unrecognized weekday text silently drops the bin instead of surfacing format drift.

When a card does have a frequency element but its text doesn't match any known weekday, the bin is silently skipped (continue) — indistinguishable from the legitimate "not a bin card" case at line 78-80. If the council changes the frequency wording (e.g., "fortnightly" instead of a weekday), a real bin would quietly vanish from the output rather than failing loudly, per the explicit-failure preference noted for this file. Since test_parse_data_skips_a_dateless_card_with_no_recognisable_frequency already locks in the "skip" return value for this branch, consider keeping the skip but adding a log warning so format drift is at least observable.

🔍 Add observability without changing the return contract
                 weekday = frequency_day.get_text(strip=True).title()
                 if weekday not in days_of_week:
+                    _LOGGER.warning(
+                        "Lichfield: unrecognized frequency text %r for %s",
+                        weekday, bin_name(heading),
+                    )
                     continue

Based on learnings: "In uk_bin_collection/**/*.py, when parsing council bin collection data, prefer explicit failures... over silent defaults or swallowed errors... to ensure format changes are detected early."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py`
around lines 82 - 84, The weekday validation branch in the council parser should
remain a skip to preserve the existing return contract, but must emit a warning
before continuing when frequency_day text is not in days_of_week. Update the
logic around frequency_day and weekday to include the unrecognized value and
sufficient card context in the warning, while leaving valid weekdays and
missing-frequency handling unchanged.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 19-22: Disable dependency caching in the release job by removing
the pip cache configuration from actions/setup-python and removing or
restricting the adjacent Poetry dependency cache for tag-triggered runs, while
preserving the release build and publish steps.

In `@uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py`:
- Around line 66-73: Update the date parsing in parse_data around date_element
to parse the day/month against a concrete candidate year, such as now.year,
instead of relying on strptime’s default year 1900; then retain the existing
future rollover check to move past dates into now.year + 1, including valid
handling of 29 February.

---

Nitpick comments:
In `@uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py`:
- Around line 15-78: Add a pytest module for BedfordshireCouncil.parse_data,
mirroring the fixture-based pattern used by the Lichfield council tests. Mock
requests.get and datetime as needed, and cover UPRN-based URL fetching,
successful synthetic HTML parsing, duplicate bin suppression, type mapping, and
relevant invalid-response or malformed-element errors.

In `@uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py`:
- Around line 66-73: The explicit-date parsing in LichfieldDistrictCouncil must
handle 29 February without relying on strptime’s default year: parse using
now.year, retry with now.year + 1 when the date falls across the year boundary,
and retain the existing rollover behavior. In
uk_bin_collection/tests/test_lichfield_district_council.py lines 104-114,
replace a fixture date with “29th February” and assert it resolves to the
correct leap year without raising.
- Around line 82-84: The weekday validation branch in the council parser should
remain a skip to preserve the existing return contract, but must emit a warning
before continuing when frequency_day text is not in days_of_week. Update the
logic around frequency_day and weekday to include the unrecognized value and
sufficient card context in the warning, while leaving valid weekdays and
missing-frequency handling unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d30b80b0-01b1-4521-b79e-e246f01f2532

📥 Commits

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

⛔ Files ignored due to path filters (1)
  • poetry.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • .github/workflows/behave_pull_request.yml
  • .github/workflows/behave_schedule.yml
  • .github/workflows/bump.yml
  • .github/workflows/release.yml
  • .github/workflows/rollback-release.yml
  • .github/workflows/validate-release-ready.yml
  • .github/workflows/wiki.yml
  • uk_bin_collection/tests/input.json
  • uk_bin_collection/tests/test_lichfield_district_council.py
  • uk_bin_collection/uk_bin_collection/councils/BedfordshireCouncil.py
  • uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py

Comment on lines +19 to 22
uses: actions/setup-python@v7
with:
python-version: '3.12'
cache: 'pip'

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow files =="
git ls-files .github/workflows || true

echo
echo "== release.yml excerpt =="
if [ -f .github/workflows/release.yml ]; then
  nl -ba .github/workflows/release.yml | sed -n '1,220p'
fi

echo
echo "== setup-python occurrences =="
rg -n "setup-python|cache:|poetry|pypi|publish|artifact" .github/workflows || true

echo
echo "== repo relevant files =="
git ls-files | egrep '(^pyproject\.toml$|^poetry\.lock$|^\.github/workflows/|setup\.py|setup\.cfg|tox\.ini|uv\.lock|requirements.*\.txt)'

Repository: robbrad/UKBinCollectionData

Length of output: 684


🌐 Web query:

actions/setup-python v7 cache pip option GitHub Actions restore cache publishing workflow security

💡 Result:

The actions/setup-python action, now at version 7, provides built-in dependency caching to accelerate workflows by restoring and saving dependency files [1][2]. ### Using the Pip Cache Option To enable caching for pip, you must explicitly set the cache input to 'pip' within your workflow step [1][3]. Caching is disabled by default [1]. yaml steps: - uses: actions/checkout@v7 - uses: actions/setup-python@v7 with: python-version: '3.13' cache: 'pip' # Enables caching for pip - run: pip install -r requirements.txt By default, the action searches for dependency files like requirements.txt or pyproject.toml and generates a cache key based on the file hash [1][4]. You can customize the dependency file location or use wildcards by providing the cache-dependency-path input [5][3]. ### Security and Best Practices When using the built-in cache, keep the following security and operational considerations in mind: * Deterministic Versions: The pip cache mechanism relies on your dependency file hashes. If your requirements.txt file uses loose versioning (e.g., chardet>=3.0.4 or no version specified), pip will attempt to install the latest available versions even when a cache hit occurs [1][6]. This can lead to non-deterministic builds and potential security risks if a dependency is compromised. To ensure security and reproducibility, always pin dependencies to specific versions [1][7]. * Cache Integrity: The action utilizes @actions/cache (upgraded to version 6.2.0 in v7) under the hood [1][2]. While this automates cache management, it does not provide cryptographic verification of the cached packages themselves. Relying on cached content assumes the cache has not been tampered with, which is generally protected by the GitHub Actions cache isolation boundaries. * Performance: If your dependency file is not updated for a long time, and a newer version of a dependency is released, the restored cache may become effectively obsolete, potentially increasing total build time if pip still performs network checks or downloads newer versions [8][7]. * Cache Scope: Caches are scoped to the repository and branch. If you have multiple jobs or branches, they may share the cache based on the generated key, which is standard behavior for GitHub Actions [9][10]. For complex setups involving multiple dependency files or subdirectories, use the cache-dependency-path parameter to ensure all relevant files are included in the hash calculation [5][3].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== release.yml excerpt =="
if [ -f .github/workflows/release.yml ]; then
  awk '{printf "%6d  %s\n", NR, $0}' .github/workflows/release.yml | sed -n '1,220p'
fi

echo
echo "== setup-python / cache / publish occurrences in workflows =="
python3 - <<'PY'
import pathlib, re
for p in sorted(pathlib.Path('.github/workflows').glob('*')):
    if p.is_file():
        txt=p.read_text(errors='replace')
        if any(s in txt for s in ['setup-python', 'cache:', 'poetry', 'publish', 'pypi', 'artifact']):
            print(f'--- {p}')
            for i, line in enumerate(txt.splitlines(), 1):
                if any(s in line for s in ['setup-python', 'cache:', 'poetry', 'publish', 'pypi', 'artifact', 'on:']):
                    print(f'{i:4}: {line}')
PY

echo
echo "== relevant repo dependency files =="
git ls-files | python3 - <<'PY'
import sys
for line in sys.stdin:
    p=line.strip()
    if any(p in {x for x in ('pyproject.toml','poetry.lock','requirements.txt','uv.lock','setup.py','tox.ini')} or p.startswith('.github/workflows/')):
        print(p)
PY

Repository: robbrad/UKBinCollectionData

Length of output: 10314


🌐 Web query:

zizmor GitHub Actions cache pip publishing workflow security disabled cache recommendation

💡 Result:

The zizmor tool flags usage of GitHub Actions caching in workflows that publish artifacts (e.g., release workflows) under the audit rule cache-poisoning [1][2]. This is because an attacker with access to a repository's GITHUB_TOKEN could potentially poison the cache, leading to the execution of unauthorized or malicious code when subsequent, privileged workflows restore those cache entries [1][3]. Recommendation: Zizmor recommends avoiding the use of cached state in workflows that publish artifacts [1][2]. When a cache is necessary, you should implement security measures to ensure it is not exploited. Common remediation approaches include: 1. Disabling the cache in publishing workflows: If possible, remove cache-aware actions (e.g., actions/cache) or disable them entirely in your release workflows [1][2]. 2. Using conditional logic: Use if: conditions to skip caching steps during release or tag-based events [1][2]. For example: if: github.event_name!= 'release' 3. Using action-specific inputs: Many actions allow you to disable cache restoration or set it to a lookup-only mode via specific inputs [1][2]. Examples provided in documentation include: - @Swatinem/rust-cache: use lookup-only: true [1][2] - @actions/setup-node: use package-manager-cache: false [1][2] - @astral-sh/setup-uv: use enable-cache: false [1][2] If you believe a finding is a false positive (e.g., the cache is used in a way that cannot be poisoned), you can use zizmor's mechanisms to ignore specific results [4]. However, the security-focused recommendation remains to minimize or eliminate cache usage in high-privilege publishing environments [1][3].

Citations:


Disable dependency caching in the release job.

This tag-triggered workflow restores the pip cache before building and publishing to PyPI. Remove cache: 'pip' from actions/setup-python, and also review the adjacent Poetry dependency cache; remove or scope it for release/tag runs to avoid injecting compromised build dependencies into published artifacts.

🧰 Tools
🪛 zizmor (1.26.1)

[error] 19-19: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): this step

(cache-poisoning)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 19 - 22, Disable dependency
caching in the release job by removing the pip cache configuration from
actions/setup-python and removing or restricting the adjacent Poetry dependency
cache for tag-triggered runs, while preserving the release build and publish
steps.

Sources: MCP tools, Linters/SAST tools

Comment thread uk_bin_collection/uk_bin_collection/councils/LichfieldDistrictCouncil.py Outdated
@robbrad robbrad changed the title July Part 2: consolidated fixes (Cardiff/Blackburn URLs, Lichfield, Bedfordshire, dependency bumps) July Part 2: consolidated PR fixes + Fenland, MSDC issue fixes Jul 25, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
uk_bin_collection/tests/test_mid_suffolk_district_council.py (1)

33-66: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add an invalid-date regression test.

The suite covers valid dates, empty cells, and missing tables, but not malformed non-empty dates. Add a pytest.raises(ValueError) case so future council format changes cannot silently produce incomplete output.

Based on learnings, parser tests should verify that unexpected formats raise explicitly.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@uk_bin_collection/tests/test_mid_suffolk_district_council.py` around lines 33
- 66, Add a regression test alongside the existing _parse_collection_table tests
that replaces a valid collection date with a non-empty malformed date, invokes
CouncilClass()._parse_collection_table, and asserts pytest.raises(ValueError).
Keep the fixture and expected behavior focused on explicit failure for invalid
dates.

Source: Learnings

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@uk_bin_collection/uk_bin_collection/councils/MidSuffolkDistrictCouncil.py`:
- Around line 167-176: Update the date parsing in the council parser’s
collection-date loop so non-empty, unrecognized date_text values raise a clear
ValueError instead of being skipped. Preserve the existing handling for missing
cells and empty text, and keep successfully parsed dates unchanged.

---

Nitpick comments:
In `@uk_bin_collection/tests/test_mid_suffolk_district_council.py`:
- Around line 33-66: Add a regression test alongside the existing
_parse_collection_table tests that replaces a valid collection date with a
non-empty malformed date, invokes CouncilClass()._parse_collection_table, and
asserts pytest.raises(ValueError). Keep the fixture and expected behavior
focused on explicit failure for invalid dates.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 1ef5c288-6767-4ea1-b0fb-980f4aba2f60

📥 Commits

Reviewing files that changed from the base of the PR and between e1e1937 and 40702ba.

📒 Files selected for processing (5)
  • custom_components/uk_bin_collection/__init__.py
  • custom_components/uk_bin_collection/tests/test_init.py
  • uk_bin_collection/tests/input.json
  • uk_bin_collection/tests/test_mid_suffolk_district_council.py
  • uk_bin_collection/uk_bin_collection/councils/MidSuffolkDistrictCouncil.py

Comment thread uk_bin_collection/uk_bin_collection/councils/MidSuffolkDistrictCouncil.py Outdated
Lichfield: strptime on an explicit date defaulted to year 1900 when no
year was given, which isn't a leap year - a genuine 29 February
collection date would crash the whole parse instead of just that row.
Parse against now.year directly and fall back to now.year + 1 when
that year can't hold the date (non-leap year, or the date's already
passed), instead of parsing first and patching the year in after.
Also log a warning when a card's frequency text doesn't match a known
weekday, so future wording changes on the council's side are visible
instead of silently dropping a bin.

MidSuffolk: a malformed but non-empty date was silently skipped rather
than raising, masking future format drift on the council's table. Let
it raise like the rest of the codebase does for unexpected formats.
@robbrad
robbrad merged commit 222f5a6 into master Jul 25, 2026
19 of 20 checks passed
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.

Central Bedfordshire Issues Error 500 - Fenland [Enhancement] Future Collection Dates

3 participants