feat(apps): track the last untracked apps' upstreams

Five apps had no app.upstream block, so nothing could ever tell us
when their pins fell behind upstream:

  barkd           gitlab ark-bitcoin/bark   (GitLab-only project)
  immich-postgres ghcr  immich-app/postgres (image exists only on ghcr.io)
  indeedhub-minio github minio/minio
  pine-whisper    dockerhub rhasspy/wyoming-whisper
  lightning-stack manual — no public listing exists for
                   lightninglabs/lightning-stack anywhere (docker.io,
                   ghcr.io, github.com all checked), so it is tracked by hand

This adds two fetchers to scripts/check-upstream-releases.py to reach the
first two: latest_gitlab (GitLab releases API; strips the project-name
tag prefix, e.g. bark-0.6.2 -> 0.6.2) and latest_ghcr (anonymous pull
token + tags/list, the same handshake a docker pull performs).

Live-verified after the change:
  barkd            0.3.0 -> 0.6.2   (bump gated on ark_client.rs REST compat)
  immich-postgres  14-vectorchord0.4.3-pgvectors0.2.0 -> 17-vectorchord0.4.3-pgvector0.8.0
  indeedhub-minio  RELEASE.2024-11-07T00-52-20Z -> latest (date-opaque: UNCOMPARABLE, shown for hand comparison)
  pine-whisper     3.4.1 -> 3.6.0   (tuned-args revision needs re-basing, not just a pin move)

Offline coverage check: 59 apps, 0 untracked.
This commit is contained in:
archipelago
2026-08-30 16:22:11 -04:00
parent 698e915df2
commit b12d1d3826
6 changed files with 79 additions and 1 deletions
+8
View File
@@ -2,6 +2,14 @@ app:
id: barkd id: barkd
name: Ark Wallet name: Ark Wallet
version: 0.3.0 version: 0.3.0
# Where this app comes from, so scripts/check-upstream-releases.py can
# tell us when the pin below has fallen behind. bark ships on GitLab only
# (no GitHub mirror), so the gitlab fetcher is the one that can see it.
# NOTE: a version bump is code work, not a pin move — the REST shapes are
# coded in core/archipelago/src/wallet/ark_client.rs (see Dockerfile note).
upstream:
kind: gitlab
repo: ark-bitcoin/bark
description: Ark protocol wallet daemon (barkd). Lets the node hold self-custodial off-chain bitcoin via an Ark server; the wallet talks to it over a local REST API. Signet by default while Ark matures. description: Ark protocol wallet daemon (barkd). Lets the node hold self-custodial off-chain bitcoin via an Ark server; the wallet talks to it over a local REST API. Signet by default while Ark matures.
container: container:
+6
View File
@@ -2,6 +2,12 @@ app:
id: immich-postgres id: immich-postgres
name: Immich Postgres name: Immich Postgres
version: "14-vectorchord0.4.3-pgvectors0.2.0" version: "14-vectorchord0.4.3-pgvectors0.2.0"
# Upstream is the Immich-built Postgres image, published only on ghcr.io
# (no GitHub release tags, no Docker Hub repo) — the ghcr fetcher in
# scripts/check-upstream-releases.py is the only one that can see it.
upstream:
kind: ghcr
repo: immich-app/postgres
description: Postgres (pgvecto.rs / vectorchord) backend for Immich. description: Postgres (pgvecto.rs / vectorchord) backend for Immich.
# Container named immich_postgres (underscore) to match the runtime's existing # Container named immich_postgres (underscore) to match the runtime's existing
+6
View File
@@ -2,6 +2,12 @@ app:
id: indeedhub-minio id: indeedhub-minio
name: IndeedHub MinIO name: IndeedHub MinIO
version: "RELEASE.2024-11-07T00-52-20Z" version: "RELEASE.2024-11-07T00-52-20Z"
# MinIO's release tags are date-opaque (RELEASE.YYYY-MM-DD…), so the
# checker reports them as UNCOMPARABLE rather than ordering them — the
# latest tag is still shown for hand comparison, which is the point.
upstream:
kind: github
repo: minio/minio
description: MinIO S3-compatible object storage for IndeedHub media. description: MinIO S3-compatible object storage for IndeedHub media.
category: community category: community
+6
View File
@@ -2,6 +2,12 @@ app:
id: lightning-stack id: lightning-stack
name: Lightning Stack name: Lightning Stack
version: 0.12.0 version: 0.12.0
# No public listing exists for lightninglabs/lightning-stack (checked
# docker.io, ghcr.io and github.com) — nothing can be queried automatically,
# so this one is tracked by hand.
upstream:
kind: manual
url: no public listing for lightninglabs/lightning-stack — verify by hand
description: Complete Lightning Network implementation. Includes LND, CLN, and management tools. description: Complete Lightning Network implementation. Includes LND, CLN, and management tools.
container: container:
+8
View File
@@ -6,6 +6,14 @@ app:
# pick up the args change; the pre-release form "3.4.1-1" would compare # pick up the args change; the pre-release form "3.4.1-1" would compare
# LOWER than 3.4.1 under semver and never roll out. # LOWER than 3.4.1 under semver and never roll out.
version: "3.4.2" version: "3.4.2"
# Tracks the rhasspy/wyoming-whisper image we pin (Docker Hub — the
# project's GitHub tags are not the image tags). NOTE: this manifest
# deliberately ships an args-tuned revision AHEAD of the image tag (see
# comment above) — BEHIND here means the image tag moved and the tuned
# revision needs re-basing onto it, not just a pin bump.
upstream:
kind: dockerhub
repo: rhasspy/wyoming-whisper
description: Wyoming-protocol faster-whisper speech-to-text engine. Internal Pine voice-assistant stack member — turns speech captured by a PineVoice satellite into text for Home Assistant Assist. description: Wyoming-protocol faster-whisper speech-to-text engine. Internal Pine voice-assistant stack member — turns speech captured by a PineVoice satellite into text for Home Assistant Assist.
category: home category: home
+45 -1
View File
@@ -39,6 +39,7 @@ import os
import re import re
import sys import sys
import urllib.error import urllib.error
import urllib.parse
import urllib.request import urllib.request
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
@@ -191,7 +192,50 @@ def _highest(tags: list[str], current: str = "") -> str:
return max(ranked)[1] return max(ranked)[1]
FETCHERS = {"github": latest_github, "dockerhub": latest_dockerhub} def latest_gitlab(project: str, current: str = "") -> str:
"""Newest release tag for a GitLab `group/project`.
Some projects publish releases only on GitLab with no GitHub mirror
(bark lives at ark-bitcoin/bark and nowhere else). GitLab release tags
sometimes carry the project name as a prefix (`bark-0.6.2`); strip it so
version ordering can see the number.
"""
esc = urllib.parse.quote(project, safe="")
releases = http_json(
f"https://gitlab.com/api/v4/projects/{esc}/releases?per_page=100"
)
tags = [str(r["tag_name"]) for r in releases]
prefix = project.rsplit("/", 1)[-1].lower() + "-"
tags = [t[len(prefix):] if t.lower().startswith(prefix) else t for t in tags]
return _highest(tags, current)
def latest_ghcr(repo: str, current: str = "") -> str:
"""Newest version-like tag on GitHub's container registry.
Some images exist only on ghcr.io (immich-app/postgres publishes there
and nowhere else), so neither the GitHub-release nor the Docker Hub
fetcher can see them. Anonymous pull token first, then the tag list —
the same handshake any `docker pull ghcr.io/...` performs.
"""
token = http_json(
f"https://ghcr.io/token?scope=repository:{repo}:pull&service=ghcr.io"
)["token"]
req = urllib.request.Request(
f"https://ghcr.io/v2/{repo}/tags/list",
headers={"User-Agent": USER_AGENT, "Authorization": f"Bearer {token}"},
)
with urllib.request.urlopen(req, timeout=TIMEOUT) as res: # noqa: S310
tags = [str(t) for t in json.loads(res.read().decode()).get("tags", [])]
return _highest(tags, current)
FETCHERS = {
"github": latest_github,
"dockerhub": latest_dockerhub,
"gitlab": latest_gitlab,
"ghcr": latest_ghcr,
}
# ── Manifest reading ─────────────────────────────────────────────────────── # ── Manifest reading ───────────────────────────────────────────────────────