diff --git a/.claude/skills/recipe-upgrade/SKILL.md b/.claude/skills/recipe-upgrade/SKILL.md index 2dba526..4a52be8 100644 --- a/.claude/skills/recipe-upgrade/SKILL.md +++ b/.claude/skills/recipe-upgrade/SKILL.md @@ -106,6 +106,15 @@ On cc-ci's `~/.abra/recipes/` (wrap every abra call per the pseudo-TTY b `ssh cc-ci 'script -qec "abra … -n" /dev/null'`): - `script -qec "abra recipe upgrade -n" /dev/null` for the tags it can bump; hand-edit `compose.yml` for any tags it won't, plus the config/env/volume/label changes the plan calls for. +- **tag+digest pins (`image:tag@sha256:…`) — abra can't bump these (it FATAs `tag and digest … not + supported`), so do it by hand, and KEEP the digest pin:** decide the new tag from the direct + upstream-tag check (see `/upgrade-all` box item 4 — list the registry tags, pick the newest one the + app version supports; do not blindly take the max). Then **re-resolve the digest for the new tag** and + re-append it so the pin style is preserved (a digest is a reproducibility/security pin — never silently + drop it): `docker buildx imagetools inspect : --format '{{.Manifest.Digest}}'` (or + `docker manifest inspect`), then write `image: :@`. If the app and its + digest-pinned sidecars must move together (e.g. immich-server ↔ its `postgres:…-vectorchord…` DB), + bump them as a matched, compatibility-checked set per the plan. - Bump the `coop-cloud.${STACK_NAME}.version` label to the new version string from the plan. - `script -qec "abra recipe lint -C -n" /dev/null` — fix obvious lint errors; if unfixable, record it and continue. diff --git a/.claude/skills/upgrade-all/SKILL.md b/.claude/skills/upgrade-all/SKILL.md index bb7ba57..13d8401 100644 --- a/.claude/skills/upgrade-all/SKILL.md +++ b/.claude/skills/upgrade-all/SKILL.md @@ -46,7 +46,7 @@ ssh cc-ci 'cd /root/cc-ci/tests && ls -d */' | sed 's#/##' | grep -vE '^(_generi ``` (or the names passed in `$ARGUMENTS`). For each, on cc-ci, check availability — skip dirty/up-to-date. -> ⚠️ **Three things that silently skip recipes — do ALL THREE per recipe before the version check:** +> ⚠️ **Four things that silently skip recipes — handle ALL FOUR per recipe before the version check:** > 1. **pseudo-TTY:** abra FATAs `inappropriate ioctl for device` under plain ssh — wrap every abra call > in `script`: `ssh cc-ci 'script -qec "abra -n" /dev/null'` (git/other commands need none). > 2. **go-git auth to git.autonomic.zone:** recipes on the private mirror FATA `unable to fetch tags … @@ -55,6 +55,23 @@ ssh cc-ci 'cd /root/cc-ci/tests && ls -d */' | sed 's#/##' | grep -vE '^(_generi > `git -C ~/.abra/recipes/ remote set-url origin "https://$GITEA_USERNAME:$GITEA_PASSWORD@git.autonomic.zone/recipe-maintainers/.git"`. > 3. **dirty worktree** is usually just the untracked cc-ci overlay (`compose.ccci.yml`) — `git stash -u` > before / `stash pop` after; only skip `dirty-worktree` if TRACKED changes remain. +> 4. **tag+digest image pins abra can't parse — DO NOT SKIP, check upstream directly.** abra FATAs +> `failed to parse image , saw: Docker references with both a tag and digest are currently not +> supported` and **aborts the WHOLE recipe** — even images it already parsed (e.g. immich: +> `immich-server` parses fine, then it dies on `postgres:14-vectorchord…@sha256:…`). This recipe is +> **NOT** `not-fetchable`. **Catch the failure and check the upstream registry yourself:** +> - Use abra's partial output for the images it DID parse. +> - Enumerate every `image:` ref in the compose; for each image abra could not parse (the FATA names +> it; plus any it never reached), strip the `@sha256:…` mentally and look up the **live upstream +> tags** directly — Docker Hub `https://hub.docker.com/v2/repositories//tags?page_size=100`, +> ghcr `https://ghcr.io/v2//tags/list` (anon bearer from +> `https://ghcr.io/token?scope=repository::pull&service=ghcr.io`), or +> `script -qec "abra ... " /dev/null`-free `docker buildx imagetools inspect :`. +> - **Use judgment** for non-semver tags: match the variant the app version supports, do NOT blindly +> take the highest (immich pins `-vectorchord-pgvectors` to a combo immich-server +> supports — pick the newest tag on the SAME scheme/compatibility, not pg-18 just because it exists). +> - A recipe is **upgradeable** if abra OR this direct check finds a newer tag. The actual bump + +> digest re-pin happens in `/recipe-upgrade` (see its Implement step). ``` ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; R=; \ url=$(git -C ~/.abra/recipes/$R config --get remote.origin.url); \ @@ -67,7 +84,10 @@ ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; R=; \ ``` Build `RECIPES_TO_UPGRADE` = recipes with **≥1 available upgrade** (after the stash, so the untracked overlay doesn't count as dirty). Others go to `SKIPPED_UPFRONT` with a reason (`dirty-worktree` only for -real TRACKED edits, `up-to-date`, `not-fetchable`). +real TRACKED edits, `up-to-date`, `not-fetchable`). **A `tag and digest … not supported` parse FATA is +NOT `not-fetchable`** — per box item 4, catch it and resolve availability via the direct upstream-tag +check; only `not-fetchable` when the mirror genuinely can't be fetched (network/auth), never for a +digest-pinned image. **Reconcile every candidate's mirror during the survey** (even the up-to-date ones), so merged-upstream PRs are closed and every mirror `main` tracks true upstream — fleet-wide, not just where there's a new