fix(upgrade skills): run abra over a pseudo-TTY (fixes FATA inappropriate ioctl)
abra over plain 'ssh cc-ci abra ...' has no TTY -> FATA 'inappropriate ioctl for device' (the abra error). The working harness (runner/harness/abra.py) wraps abra in util-linux 'script' for a pseudo-TTY + passes -n. Apply the same in the recipe-upgrade and upgrade-all skills: every abra call becomes ssh cc-ci 'script -qec "abra <args> -n" /dev/null'. Confirmed: abra server ls FATAs plain, works pty-wrapped. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -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 <args> -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/<recipe> status --short; \
|
||||
abra recipe fetch <recipe> --force; \
|
||||
script -qec "abra recipe fetch <recipe> --force -n" /dev/null; \
|
||||
git -C ~/.abra/recipes/<recipe> fetch origin main; \
|
||||
abra recipe versions <recipe> -m; \
|
||||
abra recipe upgrade <recipe> -m -n'
|
||||
script -qec "abra recipe versions <recipe> -m -n" /dev/null; \
|
||||
script -qec "abra recipe upgrade <recipe> -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/<recipe>`:
|
||||
- `abra recipe upgrade <recipe> -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/<recipe>` (wrap every abra call per the pseudo-TTY box above —
|
||||
`ssh cc-ci 'script -qec "abra … -n" /dev/null'`):
|
||||
- `script -qec "abra recipe upgrade <recipe> -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 <recipe> -C` — fix obvious lint errors; if unfixable, record it and continue.
|
||||
- `script -qec "abra recipe lint <recipe> -C -n" /dev/null` — fix obvious lint errors; if unfixable,
|
||||
record it and continue.
|
||||
- Commit on a branch: `git commit -m "chore: upgrade to <new-version>"` (the commit message drives the
|
||||
PR branch name `upgrade-<new-version>`). Do **not** push to upstream; do **not** tag-push.
|
||||
|
||||
|
||||
@ -30,12 +30,16 @@ Enrolled recipes = the cc-ci `tests/<recipe>/` 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 <args> -n" /dev/null'`. `git`/other commands need no wrapper.
|
||||
```
|
||||
ssh cc-ci 'export PATH=/run/current-system/sw/bin:$PATH; \
|
||||
git -C ~/.abra/recipes/<r> status --short; \
|
||||
abra recipe fetch <r> --force; \
|
||||
abra recipe upgrade <r> -m -n'
|
||||
script -qec "abra recipe fetch <r> --force -n" /dev/null; \
|
||||
script -qec "abra recipe upgrade <r> -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
|
||||
|
||||
Reference in New Issue
Block a user