Gå til hovedindhold

Løbsk CI

En kodeagent, der pusher, kører igen eller åbner pull requests i en løkke, kan bruge dine runner-minutter op på få timer, og intet siger det til dig før mailen ved 80 % forbrug. fremforge holder øje med det.

Hvad der måles

Hvert 5. minut ser fremforge for hver organisation på de seneste 60 minutters Actions-kørsler på sine hostede runnere og måler:

SignalHvadGrænse
Kørsler pr. personKørsler, som én person har startet i organisationenOver 3 gange personens travleste normale time og aldrig under 80
Runner-minutter pr. personRunner-minutter, som de kørsler har brugtOver 3 gange personens travleste normale time og aldrig under 600
Push til én pull requestForskellige commits, som én person har pushet til én pull requestFlere end 12

“Personens travleste normale time” er deres 99. percentil-time over de seneste 14 dage, beregnet igen én gang i døgnet. En person med under 20 aktive timer i den periode måles i stedet mod organisationens travleste normale time. Et team, hvis agenter kører CI hele dagen, måles altså mod sit eget normale niveau og ikke mod et stille teams.

Grænsen for pull requests tæller push, ikke kørsler: ét push starter lige så mange kørsler, som repositoriet har workflows til det.

Det er altid en person, der måles. En kørsel, som en agent starter på nogens vegne, er den persons kørsel (kørslens trigger-bruger), og der findes ingen agentkonti. Bots som Renovate måles på samme måde og markeres som bots. Kørsler, som fremforge selv starter, f.eks. opdatering af lockfiler, måles ikke.

Kalibrering

Grænserne blev sat ud fra en måneds CI, hvor de fleste kørsler kommer fra kodeagenter. Afspillet gennem detektoren giver den måned ingen løbsk CI, så snart hver person har 14 dages historik.

Hvad der sker

Når et tal krydser sin grænse, registrerer fremforge løbsk CI, én gang:

  • En mail til alle organisationens ejere, der nævner personen, hvor det sker (organisationen eller én pull request) og tallene.
  • En mail til den person, kørslerne tilhører, skrevet til dem, så de kan stoppe deres session. Ikke til en bot, og en ejer, hvis kørsler det er, får én mail, ikke to.
  • En ci.runaway-hændelse i hændelsesstrømmen, én pr. repository, kørslerne ligger i, så en agentsession, der læser feedet, også ser den.
  • En audit-hændelse (ci_runaway.detected).
  • En række på siden CI-forbrug (se I konsollen).

Så længe tallet ligger over grænsen, bliver registreringen opdateret, men der sendes ikke en ny mail. Den afsluttes af sig selv efter 60 minutter under grænsen igen.

Intet stoppes, medmindre organisationen har slået pausen til.

Pausen (frivillig)

Med pausen slået til forhindrer løbsk CI også fremforges runnere i at starte personens nye kørsler, eller ved løbsk CI på en pull request personens nye kørsler på den pull request, indtil en administrator genoptager dem. Pausen er slået fra som standard.

Det gør pausen aldrig:

  • Den annullerer aldrig noget. En tilbageholdt kørsel venter i køen, vises på Udforsk → Actions som sat på pause og starter få sekunder efter en genoptagelse.
  • Den stopper aldrig en kørsel, der er startet. En kørsel med et job, der allerede kører, gøres færdig, også dens senere jobs.
  • Den holder aldrig andre tilbage. Kun kørsler, som den person, der er sat på pause, har udløst (på den pull request, der er sat på pause), venter.
  • Den svigter åbent. Kan fremforge ikke læse pausen, starter kørslerne som normalt.

Den holder kun fremforges hostede runnere tilbage. En runner, som organisationen selv driver, kan stadig tage jobbet.

Løbsk CI, der er sat på pause, afsluttes ikke af sig selv. En ejer genoptager den eller slår pausen fra, hvilket genoptager alle tilbageholdte kørsler på én gang. Efter en genoptagelse markeres den samme person ikke igen de næste 60 minutter.

Forgejos planlagte workflows (brugeren forgejo-actions) måles og giver varsler, men sættes aldrig på pause.

I konsollen

Organisationens ejere finder løbsk CI under Byg og udrul → CI-forbrug, afsnittet Løbsk CI (https://frem.sh/<org>/_admin/ci-usage#runaways): pauseknappen og derefter hver forekomst med person, sted, travleste time, status og en Genoptag-knap (eller Afvis). Et banner øverst på siden fortæller, når der er en aktiv.

API

Tokenet skal have runners:read for at liste og runners:write for at genoptage eller slå pausen til og fra. Hver ændring auditeres som den person, kalderen handler på vegne af.

# List (state=live for open and paused only)
curl https://frem.sh/_app/api/v1/orgs/<org>/ci-runaways \
  -H "Authorization: Bearer $FREMFORGE_TOKEN"

# Turn the pause on (or off: off resumes every paused runaway)
curl -X PUT https://frem.sh/_app/api/v1/orgs/<org>/ci-runaways/settings \
  -H "Authorization: Bearer $FREMFORGE_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"pause": true}'

# Resume one (or close an open one)
curl -X POST https://frem.sh/_app/api/v1/orgs/<org>/ci-runaways/<id>/resume \
  -H "Authorization: Bearer $FREMFORGE_TOKEN"

En forekomst i listen:

{
  "id": "4f0c…",
  "status": "paused",
  "scope": "pr",
  "person": "alice",
  "person_kind": "person",
  "repo": "api",
  "pr_number": 42,
  "signals": ["pr_pushes"],
  "runs": 48,
  "heads": 16,
  "minutes": 0,
  "detected_at": "2026-10-25T09:40:00.000Z",
  "paused_at": "2026-10-25T09:40:00.000Z",
  "resumed_at": null
}

status er open (varslet), paused, ended eller resumed. MCP-serveren lister dem med list_ci_runaways.

Sådan stopper du selve løkken

Varslet fortæller dig, hvis arbejde kører i løkke; sessionen er deres. Stop agentsessionen, eller tilbagekald det token, den bruger. Med on-behalf-of-tokens stopper du sessionen ved at tilbagekalde det delegerede token uden at røre personens øvrige arbejde.