diff --git a/.claude/skills/recipe-upgrade/SKILL.md b/.claude/skills/recipe-upgrade/SKILL.md index 1af482b..ce6fa55 100644 --- a/.claude/skills/recipe-upgrade/SKILL.md +++ b/.claude/skills/recipe-upgrade/SKILL.md @@ -82,24 +82,28 @@ the real current recipe, not a stale mirror. ``` Skip a recipe as `SKIPPED — dirty-worktree` **only if it is still dirty with TRACKED changes after the stash** (real local edits), not for the untracked overlay. -- **abra says no upgrades → do NOT conclude `up-to-date` yet; cross-check upstream directly first.** - `abra recipe upgrade` is the **first** approach, but it is **blind to images abra can't evaluate** — - most importantly **tag+digest pins** (`image:tag@sha256:…`), where abra FATAs `Docker references with - both a tag and digest are currently not supported` and silently contributes **no** candidate (this is - exactly how **immich** kept getting skipped). A digest-only pin or a non-semver tag can likewise yield - nothing. So **before** writing `SKIPPED — up-to-date`, do a **direct upstream check** for every service - whose image abra did **not** produce a clean upgrade decision for (any tag+digest / digest-only / - abra-FATA / abra-returned-nothing image): +- **abra says no upgrades → trust abra for every image whose tag it CAN read; only cross-check upstream + for images whose tag format abra CAN'T parse.** `abra recipe upgrade` is the **first and trusted** + approach: for a normally-tagged image (a plain semver/calver tag abra can evaluate) where abra finds no + newer version, that service genuinely **is** up-to-date — do **not** second-guess it with an upstream + check. The blind spot is **only** images with a tag format abra cannot handle, where it silently + contributes **no** candidate: + - **tag+digest pins** (`image:tag@sha256:…`) — abra FATAs `Docker references with both a tag and digest + are currently not supported` (this is exactly how **immich** kept getting skipped); + - a **digest-only pin** (`image@sha256:…`, no tag) — nothing for abra to compare. + So **before** writing `SKIPPED — up-to-date`, do a **direct upstream check ONLY for those abra-unparseable + images** (not for images abra evaluated fine): 1. Read `cc-ci-plan/upstream/.md` (per-image releases/changelog URLs; discover + write it per the registry bullet below if missing). 2. For each such image, list the **upstream registry tags** and pick the newest tag the app version supports (the §2 "list the registry tags, pick the newest one the app supports — don't blindly take the max" method), and compare it to the **currently pinned** tag. - 3. If any service has a newer supported upstream tag than what's pinned → there **is** an upgrade: - proceed to plan/implement it (per §2, preserving any digest pin). - - **Only conclude `SKIPPED — up-to-date` when BOTH agree** there is nothing newer: abra found no bump - **and** the direct upstream check finds no newer supported tag for any abra-blind image. A - `tag and digest … not supported` FATA is a **trigger for the upstream check, never a skip on its own.** + 3. If any has a newer supported upstream tag than what's pinned → there **is** an upgrade: proceed to + plan/implement it (per §2, preserving any digest pin). + - **Conclude `SKIPPED — up-to-date` only when** abra found no bump for the images it could read **and** + the direct check finds nothing newer for the abra-unparseable images. If every image had a normal tag + abra could read, abra's verdict stands alone — no upstream check needed. A `tag and digest … not + supported` FATA is a **trigger for the upstream check on that image, never a skip on its own.** - Check `git log HEAD..origin/main` and upstream PRs (`git.coopcloud.tech/coop-cloud//pulls`) — if someone already started the bump, **re-plan from the tip of `origin/main`**, not from scratch. - **Release-notes registry (discover once, reuse — parity with recipe-maintainer's `upstream.md`).**