diff --git a/.claude/skills/recipe-upgrade/SKILL.md b/.claude/skills/recipe-upgrade/SKILL.md index 4cb8861..072a678 100644 --- a/.claude/skills/recipe-upgrade/SKILL.md +++ b/.claude/skills/recipe-upgrade/SKILL.md @@ -29,15 +29,25 @@ test** to make a PR green. ## Procedure +> ### ⚠️ Run abra over a pseudo-TTY (or it FATAs `inappropriate ioctl for device`) +> `abra` needs a TTY. Over plain `ssh cc-ci 'abra …'` there is none, so many abra commands die with +> **`FATA inappropriate ioctl for device`** / `the input device is not a TTY`. This is how the working +> harness avoids it (`runner/harness/abra.py`): wrap every abra call in a pseudo-TTY via util-linux +> `script`, and pass `-n` (`--no-input`) so it never prompts. **Always invoke abra like this:** +> ``` +> ssh cc-ci 'script -qec "abra -n" /dev/null' +> ``` +> (`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: +On cc-ci, refresh the recipe and see what's available (each abra call wrapped per the box above): ``` ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; \ git -C ~/.abra/recipes/ status --short; \ - abra recipe fetch --force; \ + script -qec "abra recipe fetch --force -n" /dev/null; \ git -C ~/.abra/recipes/ fetch origin main; \ - abra recipe versions -m; \ - abra recipe upgrade -m -n' + script -qec "abra recipe versions -m -n" /dev/null; \ + script -qec "abra recipe upgrade -m -n" /dev/null' ``` - **Dirty worktree on cc-ci → abort this recipe** (status `SKIPPED — dirty-worktree`); don't prompt. - **Reconcile the mirror first (always, even if up to date).** Run: @@ -61,11 +71,13 @@ ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; \ config changes, risks. (No human review gate — proceed straight to implement.) ### 2. Implement the upgrade (follow recipe-upgrade-apply methodology, on cc-ci) -On cc-ci's `~/.abra/recipes/`: -- `abra recipe upgrade -n` 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. +On cc-ci's `~/.abra/recipes/` (wrap every abra call per the pseudo-TTY box above — +`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. - Bump the `coop-cloud.${STACK_NAME}.version` label to the new version string from the plan. -- `abra recipe lint -C` — fix obvious lint errors; if unfixable, record it and continue. +- `script -qec "abra recipe lint -C -n" /dev/null` — fix obvious lint errors; if unfixable, + record it and continue. - Commit on a branch: `git commit -m "chore: upgrade to "` (the commit message drives the PR branch name `upgrade-`). Do **not** push to upstream; do **not** tag-push. diff --git a/.claude/skills/upgrade-all/SKILL.md b/.claude/skills/upgrade-all/SKILL.md index f35428c..0393256 100644 --- a/.claude/skills/upgrade-all/SKILL.md +++ b/.claude/skills/upgrade-all/SKILL.md @@ -30,12 +30,16 @@ Enrolled recipes = the cc-ci `tests//` dirs (same set `ci-test-review` s ``` ssh cc-ci 'cd /root/cc-ci/tests && ls -d */' | sed 's#/##' | grep -vE '^(_generic|unit|__pycache__)$' ``` -(or the names passed in `$ARGUMENTS`). For each, on cc-ci, check availability — skip dirty/up-to-date: +(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. ``` ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; \ git -C ~/.abra/recipes/ status --short; \ - abra recipe fetch --force; \ - abra recipe upgrade -m -n' + script -qec "abra recipe fetch --force -n" /dev/null; \ + script -qec "abra recipe upgrade -m -n" /dev/null' ``` 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`). @@ -103,7 +107,8 @@ End with the report path and a reminder that **nothing was merged**. ## Safety / coordination (this matters — shared host with the build loops) - **Sequential is the default for a reason.** Recipe deploys are **stateful on the shared Swarm** and parallel deploys can OOM/collide. Between sequential recipes, the per-recipe `recipe-upgrade` tears - down what it deployed; verify a recipe is undeployed before the next starts (`abra app ls` on cc-ci). + down what it deployed; verify a recipe is undeployed before the next starts + (`ssh cc-ci 'script -qec "abra app ls -n" /dev/null'` — pseudo-TTY wrapped, per the box above). - **Single-writer:** every PR (recipe or cc-ci test) is on a dedicated branch; **never push `main`**, never touch the build loops' `/cc-ci` `/cc-ci-adv` working clones or their in-flight state. - **Contention with active loop development:** while the loops are still building cc-ci, this run