Files
Anthias/tests/test_github.py
Viktor Petersson c28da3b294 fix(server): compare against latest release tag, not branch HEAD (#2831)
* fix(server): compare against latest release tag, not branch HEAD

`is_up_to_date()` previously compared the device's baked-in `GIT_HASH`
to the master branch's HEAD SHA, with a GHCR-image-digest fallback.
That answered "is your commit at master tip?" instead of "is there a
newer release?", so devices on the last release artefact flipped to
"out of date" the moment master moved one commit forward, and any
GitHub API hiccup silently flipped the indicator back to "up to date".

Rewrite around `/repos/Screenly/Anthias/releases/latest`:

- Cache the `tag_name` for 24h; honour the existing 5-minute error
  backoff key.
- Compare with `packaging.version.Version` so CalVer ordering is
  numeric (`2026.10.0 > 2026.5.0`).
- On API failure or malformed remote tag, return the last
  successfully-computed verdict (persisted in Redis on every fresh
  check); fall back to `False` if there's no cached verdict — never
  optimistic.
- Suppress the indicator on dev/branch builds whose local CalVer
  doesn't parse.
- Drop `fetch_remote_hash`, `remote_branch_available`,
  `is_running_latest_published_image` and the GHCR helpers.

Closes #2819

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* style: ruff-format new github module + tests

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(server): scope verdict cache by local release, back off on malformed 200s

Two follow-ups to the release-tag rewrite:

- Scope the last-verdict cache key by the installed CalVer
  (`is-up-to-date:last-verdict:<release>`). After an upgrade during a
  GitHub outage, the previous version's verdict no longer applies; an
  unscoped cache could keep the indicator wrong until GitHub came
  back. Falling back to the no-cache path (False) for an upgraded
  release is the safer choice the issue's "first-run pessimistic"
  rule already prescribed.
- Trip the existing 5-minute backoff on malformed 200 responses (bad
  JSON, missing/non-string `tag_name`). Without this, an upstream
  payload regression would re-fire the GitHub call on every page
  render until the body was fixed.

Also pin `packaging==26.1` directly in the server group instead of
relying on its transitive arrival via celery → kombu.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(server): don't cache an unparseable release tag

Per Copilot review: `_fetch_latest_release_tag()` previously cached
any non-empty `tag_name` for 24h before validating parseability. A
hand-edited release returning `nightly` (or similar) would pin
`is_up_to_date()` to the fallback verdict for the full TTL even
after upstream corrected the tag.

Validate `_parse_version(tag) is not None` before writing the cache;
treat an unparseable tag as a malformed-body error and trip the
existing 5-minute backoff. Once the backoff clears, the next request
re-fetches and picks up the corrected tag.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-05 15:59:49 +01:00

12 KiB