diff --git a/.claude/skills/recipe-upgrade/SKILL.md b/.claude/skills/recipe-upgrade/SKILL.md index 072a678..f21c3a5 100644 --- a/.claude/skills/recipe-upgrade/SKILL.md +++ b/.claude/skills/recipe-upgrade/SKILL.md @@ -40,16 +40,32 @@ test** to make a PR green. > (`git`/other commands do NOT need the wrapper — only `abra`.) Do this for every abra command below. ### 1. Plan the upgrade (research — follow recipe-upgrade-plan methodology) -On cc-ci, refresh the recipe and see what's available (each abra call wrapped per the box above): + +> ### ⚠️ Two gotchas that silently skip recipes — handle BOTH before the version check +> 1. **go-git auth to the private mirror.** Recipes hosted on `git.autonomic.zone` (custom-html(-tiny), +> discourse, ghost, immich, lasuite-docs, plausible, uptime-kuma) fail with +> **`FATA unable to fetch tags … authentication required: Unauthorized`** because abra's embedded +> go-git reads `remote.origin.url` from `.git/config` **literally** and **ignores `git url.insteadOf` +> / credential helpers**. Fix: bake the bot creds into the origin URL first (idempotent): +> `git -C ~/.abra/recipes/ remote set-url origin "https://$GITEA_USERNAME:$GITEA_PASSWORD@git.autonomic.zone/recipe-maintainers/.git"` (only when origin is on git.autonomic.zone). +> 2. **Dirty worktree** is usually just the untracked cc-ci overlay (`compose.ccci.yml`) — don't skip on +> that. `git stash -u` before the checks and `stash pop` after. + +On cc-ci, refresh the recipe and see what's available (creds + stash first; each abra call pty-wrapped): ``` -ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; \ - git -C ~/.abra/recipes/ status --short; \ - script -qec "abra recipe fetch --force -n" /dev/null; \ - git -C ~/.abra/recipes/ fetch origin main; \ - script -qec "abra recipe versions -m -n" /dev/null; \ - script -qec "abra recipe upgrade -m -n" /dev/null' +ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; R=; \ + url=$(git -C ~/.abra/recipes/$R config --get remote.origin.url); \ + case "$url" in https://git.autonomic.zone/*) \ + git -C ~/.abra/recipes/$R remote set-url origin "https://'"$GITEA_USERNAME"':'"$GITEA_PASSWORD"'@${url#https://}";; esac; \ + git -C ~/.abra/recipes/$R stash -u >/dev/null 2>&1 || true; \ + script -qec "abra recipe fetch $R --force -n" /dev/null; \ + git -C ~/.abra/recipes/$R fetch origin main; \ + script -qec "abra recipe versions $R -m -n" /dev/null; \ + script -qec "abra recipe upgrade $R -m -n" /dev/null; \ + git -C ~/.abra/recipes/$R stash pop >/dev/null 2>&1 || true' ``` -- **Dirty worktree on cc-ci → abort this recipe** (status `SKIPPED — dirty-worktree`); don't prompt. +- 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. - **Reconcile the mirror first (always, even if up to date).** Run: ``` set -a; . /srv/cc-ci/.testenv; set +a diff --git a/.claude/skills/upgrade-all/SKILL.md b/.claude/skills/upgrade-all/SKILL.md index 0393256..0a32fff 100644 --- a/.claude/skills/upgrade-all/SKILL.md +++ b/.claude/skills/upgrade-all/SKILL.md @@ -32,17 +32,28 @@ 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. -> ⚠️ **Run abra over a pseudo-TTY** or it FATAs `inappropriate ioctl for device` (no TTY under plain -> ssh). Wrap every abra call in `script` (the working-harness fix in `runner/harness/abra.py`) and pass -> `-n`: `ssh cc-ci 'script -qec "abra -n" /dev/null'`. `git`/other commands need no wrapper. +> ⚠️ **Three things that silently skip recipes — do ALL THREE 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 … +> authentication required: Unauthorized` — abra/go-git reads `remote.origin.url` literally and ignores +> `git url.insteadOf`. Bake creds into origin first (idempotent, only if origin is git.autonomic.zone): +> `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. ``` -ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; \ - git -C ~/.abra/recipes/ status --short; \ - script -qec "abra recipe fetch --force -n" /dev/null; \ - script -qec "abra recipe upgrade -m -n" /dev/null' +ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; R=; \ + url=$(git -C ~/.abra/recipes/$R config --get remote.origin.url); \ + case "$url" in https://git.autonomic.zone/*) \ + git -C ~/.abra/recipes/$R remote set-url origin "https://'"$GITEA_USERNAME"':'"$GITEA_PASSWORD"'@${url#https://}";; esac; \ + git -C ~/.abra/recipes/$R stash -u >/dev/null 2>&1 || true; \ + script -qec "abra recipe fetch $R --force -n" /dev/null; \ + script -qec "abra recipe upgrade $R -m -n" /dev/null; \ + git -C ~/.abra/recipes/$R stash pop >/dev/null 2>&1 || true' ``` -Build `RECIPES_TO_UPGRADE` = recipes with a **clean worktree** AND **≥1 available upgrade**. Others go -to `SKIPPED_UPFRONT` with a reason (`dirty-worktree`, `up-to-date`, `not-fetchable`). +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`). **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