feat: auto-repair loop for failing auto-update PRs #48

Merged
pazpi merged 7 commits from feat/auto-repair-loop into master 2026-08-14 15:05:07 +02:00
Owner

Problema

Le PR di aggiornamento settimanale del flake (auto-update-*, create da .forgejo/workflows/auto-update-pr.yaml) vengono buildate da .forgejo/workflows/auto-update-build.yaml. Quando un aggiornamento rompe la build, il workflow attuale si limita a commentare i fallimenti sulla PR e si ferma: la PR resta aperta, non-mergeabile (es. PR #47 "WIP"), e richiede intervento manuale.

Soluzione

Questa PR aggiunge un repair-loop automatico (.forgejo/workflows/auto-repair.yaml) che usa un coding agent (pi, tramite OpenRouter) per tentare di sistemare la build fallita direttamente sul branch della PR:

  1. Trigger: gira sulle stesse PR auto-update/* per gli eventi opened e synchronize di pull_request verso master.
  2. Solo PR non mergeabili: via API Forgejo controlla lo stato mergeable; se la PR è già mergeable la build è ok ed esce senza fare nulla (niente lavoro inutile).
  3. Build: ripete la build degli host LXC (stessa logica di auto-update-build.yaml, colmena). Se passa, non fa nulla.
  4. Repair: se la build fallisce, raccoglie i log in /tmp/build-failures.txt, prepara un prompt e lancia pi (con NOT_SYS=true e OPENROUTER_API_KEY) per correggere flake.nix/flake.lock. L'agente committa fix: auto-repair attempt N e pusha sul branch della PR (mai force-push, mai merge). Il push genera un nuovo evento synchronize → la build riparte.
  5. Anti-loop: il contatore dei tentativi è basato sui commit fix: auto-repair attempt nella storia del branch — max 3 tentativi. Oltre il terzo, il workflow commenta "🛑 Auto-repair gave up" sulla PR e si ferma senza pushare, lasciando l'intervento all'uomo.

Secrets usati (stesso runner nix): MINE_API_TOKEN (già presente) e OPENROUTER_API_KEY (da aggiungere ai secrets del repo).

Il README viene aggiornato con una sezione "Auto-repair" che documenta il flusso.

File modificati

  • + .forgejo/workflows/auto-repair.yaml (nuovo workflow di repair-loop)
  • M README.md (documentazione del flusso)

Azioni necessarie prima/col merge

  • Aggiungere il secret OPENROUTER_API_KEY al repository (Settings → Actions → Secrets).
  • Aggiungere il secret CURSOR_API_KEY al repository
  • Verificare che pi sia installato sul runner nix (il workflow lo richiama come pi -p ...).
## Problema Le PR di aggiornamento settimanale del flake (`auto-update-*`, create da `.forgejo/workflows/auto-update-pr.yaml`) vengono buildate da `.forgejo/workflows/auto-update-build.yaml`. Quando un aggiornamento rompe la build, il workflow attuale **si limita a commentare i fallimenti sulla PR** e si ferma: la PR resta aperta, non-mergeabile (es. PR #47 "WIP"), e richiede intervento manuale. ## Soluzione Questa PR aggiunge un **repair-loop automatico** (`.forgejo/workflows/auto-repair.yaml`) che usa un coding agent (`pi`, tramite OpenRouter) per tentare di sistemare la build fallita direttamente sul branch della PR: 1. **Trigger**: gira sulle stesse PR `auto-update/*` per gli eventi `opened` e `synchronize` di pull_request verso `master`. 2. **Solo PR non mergeabili**: via API Forgejo controlla lo stato `mergeable`; se la PR è già mergeable la build è ok ed esce senza fare nulla (niente lavoro inutile). 3. **Build**: ripete la build degli host LXC (stessa logica di `auto-update-build.yaml`, colmena). Se passa, non fa nulla. 4. **Repair**: se la build fallisce, raccoglie i log in `/tmp/build-failures.txt`, prepara un prompt e lancia `pi` (con `NOT_SYS=true` e `OPENROUTER_API_KEY`) per correggere `flake.nix`/`flake.lock`. L'agente committa `fix: auto-repair attempt N` e **pusha sul branch della PR** (mai force-push, mai merge). Il push genera un nuovo evento `synchronize` → la build riparte. 5. **Anti-loop**: il contatore dei tentativi è basato sui commit `fix: auto-repair attempt` nella storia del branch — **max 3 tentativi**. Oltre il terzo, il workflow commenta "🛑 Auto-repair gave up" sulla PR e **si ferma senza pushare**, lasciando l'intervento all'uomo. Secrets usati (stesso runner `nix`): `MINE_API_TOKEN` (già presente) e `OPENROUTER_API_KEY` (da aggiungere ai secrets del repo). Il README viene aggiornato con una sezione "Auto-repair" che documenta il flusso. ## File modificati - `+ .forgejo/workflows/auto-repair.yaml` (nuovo workflow di repair-loop) - `M README.md` (documentazione del flusso) ## Azioni necessarie prima/col merge - Aggiungere il secret `OPENROUTER_API_KEY` al repository (Settings → Actions → Secrets). - Aggiungere il secret `CURSOR_API_KEY` al repository - Verificare che `pi` sia installato sul runner `nix` (il workflow lo richiama come `pi -p ...`).
docs: document auto-repair flow
All checks were successful
Auto Repair / repair (pull_request) Has been skipped
Auto Update Build / build (pull_request) Has been skipped
485a9bb5e3
feat: add PR #48 workflow helpers and use CURSOR_API_KEY
All checks were successful
Auto Repair / repair (pull_request) Has been skipped
Auto Update Build / build (pull_request) Has been skipped
6ef0e6f04d
Switch auto-repair from OPENROUTER_API_KEY to CURSOR_API_KEY for pi
(Cursor SDK). Add local test script, just recipes, and agent skill.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add pi agent where needed
All checks were successful
Auto Repair / repair (pull_request) Has been skipped
Auto Update Build / build (pull_request) Has been skipped
b05650e542
pazpi force-pushed feat/auto-repair-loop from e69904f3bc to ac86de27d6
All checks were successful
Auto Update / build-and-repair (pull_request) Has been skipped
2026-08-13 15:53:30 +02:00
Compare
Steps
All checks were successful
Auto Update / build-and-repair (pull_request) Has been skipped
2f0b030631
Moved from pi to cursor-sdk. Simpler and less boilerplate
All checks were successful
Auto Update / build-and-repair (pull_request) Has been skipped
52dba88a15
Author
Owner

Update: switched from pi to Cursor SDK

The repair step no longer runs pi with pi-cursor-sdk on the runner. It now uses @cursor/sdk via a small script at
scripts/auto-repair/auto-repair.mjs.

Why

  • Less runner setup — no pi-coding-agent, no pi-cursor-sdk, no agenix pi-env, no forgejo-runner-pi-setup systemd unit
  • Simpler secrets — one Forgejo repo secret (CURSOR_API_KEY) instead of runner-side env files
  • Clearer split of responsibilities — the agent edits files; the workflow handles git commit / git push

What changed

Before (pi) After (Cursor SDK)
NOT_SYS=true pi --provider cursor ... on the runner node scripts/auto-repair/auto-repair.mjs
CURSOR_API_KEY / OPENROUTER_API_KEY in agenix pi-env on forgejo-runner CURSOR_API_KEY as Forgejo Actions secret
services.forgejo-runner.pi.* NixOS module Removed — runner only needs nodejs (already in hostPackages)
Agent prompted to commit and push Agent edits only; workflow commits fix: auto-repair attempt N and pushes

The repair step calls Agent.prompt(..., { local: { cwd, settingSources: [] } }) with build logs in the prompt. Model defaults to composer-2.5;
override with repo variable CURSOR_MODEL.

Setup before merge

  1. Add CURSOR_API_KEY under repo → Settings → Actions → Secrets (remove OPENROUTER_API_KEY if it was added for the old approach)
  2. No runner redeploy needed for pi — only ensure the nix runner has nodejs (already the case)
  3. Optional: set CURSOR_MODEL as a repository variable if you want something other than composer-2.5

Unchanged

  • Trigger: auto-update/* PRs, opened / synchronize
  • Build all LXC hosts via colmena; comment on failure
  • Max 3 repair attempts (fix: auto-repair attempt commits on the PR branch)
  • Push retriggers the workflow via synchronize
Update: switched from pi to Cursor SDK The repair step no longer runs pi with pi-cursor-sdk on the runner. It now uses @cursor/sdk via a small script at scripts/auto-repair/auto-repair.mjs. ### Why - Less runner setup — no pi-coding-agent, no pi-cursor-sdk, no agenix pi-env, no forgejo-runner-pi-setup systemd unit - Simpler secrets — one Forgejo repo secret (CURSOR_API_KEY) instead of runner-side env files - Clearer split of responsibilities — the agent edits files; the workflow handles git commit / git push ### What changed | Before (`pi`) | After (Cursor SDK) | |---|---| | `NOT_SYS=true pi --provider cursor ...` on the runner | `node scripts/auto-repair/auto-repair.mjs` | | `CURSOR_API_KEY` / `OPENROUTER_API_KEY` in agenix `pi-env` on `forgejo-runner` | `CURSOR_API_KEY` as Forgejo Actions secret | | `services.forgejo-runner.pi.*` NixOS module | Removed — runner only needs `nodejs` (already in `hostPackages`) | | Agent prompted to commit and push | Agent edits only; workflow commits `fix: auto-repair attempt N` and pushes | The repair step calls `Agent.prompt(..., { local: { cwd, settingSources: [] } })` with build logs in the prompt. Model defaults to composer-2.5; override with repo variable CURSOR_MODEL. ### Setup before merge 1. Add CURSOR_API_KEY under repo → Settings → Actions → Secrets (remove `OPENROUTER_API_KEY` if it was added for the old approach) 2. No runner redeploy needed for pi — only ensure the nix runner has nodejs (already the case) 3. Optional: set `CURSOR_MODEL` as a repository variable if you want something other than composer-2.5 ### Unchanged - Trigger: auto-update/* PRs, opened / synchronize - Build all LXC hosts via colmena; comment on failure - Max 3 repair attempts (fix: auto-repair attempt commits on the PR branch) - Push retriggers the workflow via synchronize
pazpi merged commit c22ba8e9d3 into master 2026-08-14 15:05:07 +02:00
pazpi deleted branch feat/auto-repair-loop 2026-08-14 15:05:08 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
pazpi/nix!48
No description provided.