fix(updater): /releases?limit=1 instead of /releases/latest
Some checks failed
Build ISO / build-iso (push) Successful in 17m5s
CI / lint (push) Successful in 25s
CI / test (push) Successful in 33s
CI / validate-json (push) Successful in 23s
CI / markdown-links (push) Successful in 12s
Release / release (push) Has been cancelled

Forgejo's /releases/latest silently skips pre-releases (any release
with a -alpha / -beta / -rc suffix) and 404s when there's no stable
release. During Furtka's alpha stage every tag is a pre-release, so
the Check-for-updates button always 404'd against a perfectly-valid
releases page.

Switch check_update() to GET /releases?limit=1 and take the first
entry. Forgejo returns releases newest-first regardless of kind, so
this works whether the top of the list is pre-release or stable.
Empty list (no releases published yet) now returns a clean
"no releases" UpdateError instead of a raw 404.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Daniel Maksymilian Syrnicki 2026-04-16 16:29:11 +02:00
parent 46503daf14
commit b96f225c3c
3 changed files with 48 additions and 19 deletions

View file

@ -7,6 +7,12 @@ This project uses calendar versioning: `YY.N-stage` (e.g. `26.0-alpha` = 2026, r
## [Unreleased]
## [26.2-alpha] - 2026-04-16
### Fixed
- **Updater "Check for updates" no longer 404s when every release is a pre-release.** `check_update()` queried Forgejo's `/releases/latest`, which silently excludes pre-releases (anything tagged `-alpha`/`-beta`/`-rc`) and returns 404 when there is no stable release. Switched to `/releases?limit=1`, which Forgejo sorts newest-first across all release kinds. During the alpha stage where every tag is a pre-release this is the only thing that works; once we tag a stable release, the same query still picks it up.
## [26.1-alpha] - 2026-04-16
### Added
@ -59,6 +65,7 @@ First tagged snapshot. Pre-alpha — the installer does not yet boot, but the de
- **Containers:** Docker + Compose
- **License:** AGPL-3.0
[Unreleased]: https://forgejo.sourcegate.online/daniel/furtka/compare/26.1-alpha...HEAD
[Unreleased]: https://forgejo.sourcegate.online/daniel/furtka/compare/26.2-alpha...HEAD
[26.2-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.2-alpha
[26.1-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.1-alpha
[26.0-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.0-alpha

View file

@ -124,12 +124,22 @@ def _version_tuple(v: str) -> tuple:
def check_update() -> UpdateCheck:
"""Return current + latest versions and whether an update is available."""
"""Return current + latest versions and whether an update is available.
Forgejo's /releases/latest endpoint skips anything marked as a
pre-release, so during the CalVer alpha/beta stage where every tag
carries a suffix, that endpoint always 404s. Query the paginated
/releases list instead and take the first entry Forgejo returns
them newest-first, including pre-releases.
"""
current = read_current_version()
release = _forgejo_api("/releases/latest")
releases = _forgejo_api("/releases?limit=1")
if not isinstance(releases, list) or not releases:
raise UpdateError("no releases published yet")
release = releases[0]
latest = str(release.get("tag_name") or "").strip()
if not latest:
raise UpdateError("no latest release (empty tag_name)")
raise UpdateError("latest release has empty tag_name")
tarball_url = None
sha256_url = None
for asset in release.get("assets") or []:

View file

@ -308,12 +308,14 @@ def test_rollback_flips_to_previous_slot(tmp_path, updater, monkeypatch):
def test_check_update_queries_forgejo_and_compares(updater, monkeypatch):
# Stub the API and the current-version read.
# Stub the API and the current-version read. Forgejo's /releases list
# returns most-recent first, including pre-releases — we take [0].
monkeypatch.setattr(updater, "read_current_version", lambda: "26.0-alpha")
monkeypatch.setattr(
updater,
"_forgejo_api",
lambda path: {
lambda path: [
{
"tag_name": "26.1-alpha",
"assets": [
{
@ -325,7 +327,8 @@ def test_check_update_queries_forgejo_and_compares(updater, monkeypatch):
"browser_download_url": "https://x/t.tar.gz.sha256",
},
],
},
}
],
)
check = updater.check_update()
assert check.current == "26.0-alpha"
@ -340,7 +343,16 @@ def test_check_update_reports_up_to_date_when_same_version(updater, monkeypatch)
monkeypatch.setattr(
updater,
"_forgejo_api",
lambda path: {"tag_name": "26.1-alpha", "assets": []},
lambda path: [{"tag_name": "26.1-alpha", "assets": []}],
)
check = updater.check_update()
assert check.update_available is False
def test_check_update_raises_when_no_releases_published(updater, monkeypatch):
# Newly-created repo with zero releases: don't crash, surface a clean
# error the UI can show instead of "HTTP 404 Not Found".
monkeypatch.setattr(updater, "read_current_version", lambda: "26.0-alpha")
monkeypatch.setattr(updater, "_forgejo_api", lambda path: [])
with pytest.raises(updater.UpdateError, match="no releases"):
updater.check_update()