fix(upgrade skills): real abra-auth fix — embed git.autonomic.zone creds in origin (go-git)

The actual 'abra auth error' that skipped 8 recipes was go-git failing to
fetch tags from the PRIVATE git.autonomic.zone mirror ('authentication
required: Unauthorized'), NOT the TTY issue. abra/go-git reads
remote.origin.url literally and IGNORES git url.insteadOf + credential
helpers (confirmed: insteadOf left immich Unauthorized; literal embedded URL
fixed it). Skill now bakes $GITEA_USERNAME:$GITEA_PASSWORD into origin for
git.autonomic.zone recipes before the version check, and stashes the
untracked cc-ci overlay so it isn't mis-counted as dirty-worktree.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
autonomic-bot
2026-06-02 04:40:59 +00:00
parent c0852d2302
commit 5c691cdb66
2 changed files with 44 additions and 17 deletions

View File

@ -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/<r> remote set-url origin "https://$GITEA_USERNAME:$GITEA_PASSWORD@git.autonomic.zone/recipe-maintainers/<r>.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/<recipe> status --short; \
script -qec "abra recipe fetch <recipe> --force -n" /dev/null; \
git -C ~/.abra/recipes/<recipe> fetch origin main; \
script -qec "abra recipe versions <recipe> -m -n" /dev/null; \
script -qec "abra recipe upgrade <recipe> -m -n" /dev/null'
ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; R=<recipe>; \
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

View File

@ -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 <args> -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 <args> -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/<r> remote set-url origin "https://$GITEA_USERNAME:$GITEA_PASSWORD@git.autonomic.zone/recipe-maintainers/<r>.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/<r> status --short; \
script -qec "abra recipe fetch <r> --force -n" /dev/null; \
script -qec "abra recipe upgrade <r> -m -n" /dev/null'
ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; R=<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