Claude Code dla awarii CI: poproś, by zacytował linie błędu, zasugerował najmniejszą poprawkę i dodał test regresyjny, żeby zapobiec powtórkom.

Awaria CI zwykle nie jest tajemnicą. Log mówi, gdzie się zatrzymało, jakie polecenie zawiodło i jaki był komunikat błędu. Dobry log zawiera stack trace, błąd kompilatora z plikiem i numerem linii albo raport testu pokazujący, która asercja padła. Czasem dostaniesz wskazówkę w stylu diff: "expected X, got Y" albo wyraźny krok, który zawiódł, jak "lint", "build" czy "migrate database".
Prawdziwy problem polega na tym, że ludzie (i AI) często traktują log jako tło. Jeśli wkleisz długi log i poprosisz o "poprawkę", wiele modeli skacze do znanego wyjaśnienia zamiast czytać ostatnie sensowne linie. Zgadywanie pogarsza się, gdy błąd wygląda na typowy ("module not found", "timeout", "permission denied"). Kończy się to dużą przebudową, nową zależnością lub odpowiedzią "spróbuj zaktualizować wszystko", która nie pasuje do rzeczywistej awarii.
Celem nie jest „jakoś sprawić, żeby przeszło”. To prostsze:
W praktyce „najmniejsza poprawka” to zwykle jedna z tych rzeczy: kilkulinijkowa zmiana w jednym miejscu, brakujący import lub zła ścieżka, wartość konfiguracyjna ewidentnie niepasująca do środowiska CI, albo przywrócenie przypadkowo wprowadzonego breaking change zamiast projektowania od nowa.
Test regresyjny jako follow-up też ma znaczenie. Jednorazowe przejście CI to nie to samo co zapobieganie powtórkom. Jeśli awaria wynikała z przypadku brzegowego (null input, strefa czasowa, zaokrąglanie, uprawnienia), dodaj test regresyjny, który padał przed poprawką i przechodzi po niej. To zmienia jednorazową akcję ratunkową w barierę ochronną.
Większość złych poprawek zaczyna się od brakującego kontekstu. Jeśli wkleisz tylko ostatnią czerwoną linię, model musi zgadywać, co działo się wcześniej, a zgadywanki często prowadzą do przebudów.
Celem jest dostarczyć tyle informacji, żeby ktoś mógł prześledzić awarię od pierwszego prawdziwego błędu do końca i zmienić jak najmniej.
Wklejaj to w swojej wiadomości (dosłownie, jeśli możesz):
go test ./..., npm test, flutter test, golangci-lint run).\Dodaj ograniczenia prostym językiem. Jeśli chcesz malutką poprawkę, napisz to: bez refaktorów, bez zmiany zachowania, chyba że to konieczne, zostaw patch ograniczony do miejsca awarii.
Prosty przykład: CI pada na kroku lint po bumpie zależności. Wklej output lintera zaczynając od pierwszego ostrzeżenia, dołącz polecenie, którego użyło CI i wspomnij, która paczka zmieniła wersję. To wystarczy, żeby zasugerować jednolinijkową poprawkę konfiguracji lub małą zmianę w kodzie, zamiast formatowania połowy repo.
Jeśli chcesz coś do skopiowania, ta struktura zwykle wystarcza:
CI command:
Failing output (full):
Recent changes:
Constraints (smallest fix, no refactor):
Flaky? (runs attached):
Gdy model pudłuje na awarii CI, zwykle dlatego, że twój prompt pozwala mu zgadywać. Twoim zadaniem jest sprawić, żeby pokazał swoją pracę, używając dokładnego outputu z CI, a potem trzymał się najmniejszej zmiany, która może sprawić, że zadanie przejdzie.
Wymagaj dowodu i małego planu. Dobry prompt wymusza pięć rzeczy:
Niepewność jest w porządku. Ukryta niepewność marnuje czas.
Wklej to na początku pytania o awarię CI:
Use ONLY the evidence in the CI output below.
1) Quote the exact failing lines you are using.
2) Give ONE sentence: the most likely cause.
3) Propose the smallest fix: 1-3 edits, with file paths.
4) Do NOT do formatting/renames/refactors or "cleanup".
5) List uncertainties + the one extra detail that would confirm the diagnosis.
Jeśli log mówi "expected 200, got 500" plus stack trace do user_service.go:142, ta struktura popycha odpowiedź w stronę tej funkcji i małego warunku lub obsługi błędu, a nie przebudowy endpointu.
Najszybsze wygrane wynikają z promptu, który wymusza cytowanie logów, trzymanie się ograniczeń i zatrzymanie, gdy czegoś brakuje.
You are helping me fix a CI failure.
Repo context (short):
- Language/framework:
- Test/build command that failed: <PASTE THE EXACT COMMAND>
- CI environment (OS, Node/Go/Python versions, etc.):
Failing output (verbatim, include the first error and 20 lines above it):
<PASTE LOG>
Constraints:
- Propose the smallest possible code change that makes CI pass.
- Do NOT rewrite/refactor unrelated code.
- Do NOT touch files you do not need for the fix.
- If behavior changes, make it explicit and justify why it is correct.
Stop rule (no guessing):
- If the log is incomplete or you need more info (missing stack trace, config, versions, failing test name), STOP and ask only the minimum questions needed.
Your response format (follow exactly):
1) Evidence: Quote the exact log lines that matter.
2) Hypothesis: Explain the most likely cause in 2-4 sentences.
3) Smallest fix: Describe the minimal change and why it addresses the evidence.
4) Patch: Provide a unified diff.
5) Follow-up: Tell me the exact command(s) to rerun locally to confirm.
Then, write ONE regression test (or tweak an existing one) that would fail before this fix and pass after it, to prevent the same failure class.
- Keep the test focused. No broad test suites.
- If a test is not feasible, explain why and propose the next-best guardrail (lint rule, type check, assertion).
Dwie rzeczy, które skracają wymianę:
Najłatwiej stracić czas akceptując „cleanup”, który zmienia pięć rzeczy naraz. Zdefiniuj „minimalny” z góry: najmniejszy diff, który sprawia, że zadanie przejdzie, z najmniejszym ryzykiem i najszybszym sposobem weryfikacji.
Prosta reguła działa dobrze: napraw objaw najpierw, potem zdecyduj, czy większy refactor jest wart czasu. Jeśli log wskazuje na jeden plik, jedną funkcję, brakujący import lub przypadek brzegowy, skoncentruj się tam. Unikaj „przy okazji” edycji.
Jeśli naprawdę potrzebujesz alternatyw, poproś o dwie i tylko dwie: „najbezpieczniejsza minimalna poprawka” vs „najszybsza minimalna poprawka”. Chcesz trade-offów, nie menu.
Wymagaj też lokalnej weryfikacji zgodnej z CI. Poproś o to samo polecenie, które pipeline uruchamia (lub najbliższy odpowiednik), żebyś mógł potwierdzić w kilka minut:
# run the same unit test target CI runs
make test
# or the exact script used in CI
npm test
Jeśli odpowiedź sugeruje dużą zmianę, naciśnij: "Pokaż najmniejszy patch, który naprawia nieudaną asercję, bez niezwiązanych formatowań czy zmian nazw."
Poprawka bez testu to zakład, że problem się nie powtórzy. Zawsze poproś o follow-up test, który padał przed poprawką i przechodzi po niej.
Bądź konkretny co do tego, co znaczy „dobry” test:
Użyteczny wzorzec: określ cztery rzeczy — gdzie umieścić test, jak go nazwać, jakiego zachowania dotyczy i krótkie wyjaśnienie, dlaczego zapobiegnie regresji.
Gotowy fragment do dopisania:
Przykład: CI pokazuje panicę, gdy handler API dostaje pusty string jako ID. Nie proś o „test dla tej linii”. Poproś o test, który obejmuje nieprawidłowe ID (puste, białe spacje, zły format). Najmniejsza poprawka może być guard clause zwracający 400. Test follow-up powinien sprawdzać kilka nieprawidłowych wejść, żeby przy następnej refaktoryzacji parsowania CI natychmiast zasygnalizowało problem.
Jeśli projekt ma konwencje testowe, podaj je. Jeśli nie, poproś, by test był wzorowany na pobliskich testach w tym samym pakiecie/folderze i utrzymany krótki i czytelny.
Wklej sekcję logu CI zawierającą błąd i 20–40 linii powyżej. Dołącz też dokładne polecenie, które nie powiodło się, i kluczowe szczegóły środowiska (OS, wersje runtime, ważne flagi).
Poproś, żeby powtórzył, co dokładnie padło prostym językiem i wskazał linie w output, które to udowadniają. Jeśli nie potrafi zacytować logu, to go nie przeczytał.
Poproś o najmniejszą możliwą zmianę w kodzie, która sprawi, że polecenie przejdzie. Odrzucaj refaktory. Zanim zastosujesz cokolwiek, niech wypisze:
Zastosuj patch i uruchom dokładne polecenie, które padło, lokalnie (lub w tym samym zadaniu CI jeśli to jedyna opcja). Jeśli dalej pada, wklej tylko nowy fragment logu i powtórz. Mniejszy kontekst = bardziej skupiona odpowiedź.
Gdy jest zielono, dodaj jeden test, który przed poprawką padał, a po poprawce przechodzi. Niech będzie ukierunkowany: jeden test, jeden powód.
Uruchom polecenie ponownie z nowym testem, żeby upewnić się, że nie tylko zagłuszyłeś błąd.
Poproś o krótką wiadomość commit i opis PR zawierający: co padło, co się zmieniło, jak to zweryfikowałeś i jaki test zapobiega powtórce. Recenzenci działają szybciej, gdy powody są jasno opisane.
Częsta awaria: wszystko działa lokalnie, a mała zmiana powoduje, że testy padają na runnerze CI. Oto prosty przypadek z API w Go, gdzie handler zaczął akceptować datę w formacie tylko daty (2026-01-09), ale kod nadal parsował tylko pełne znaczniki RFC3339.
To jest fragment, który warto wkleić (krótko, ale z linią błędu):
--- FAIL: TestCreateInvoice_DueDate (0.01s)
invoice_test.go:48: expected 201, got 400
invoice_test.go:49: response: {"error":"invalid due_date: parsing time \"2026-01-09\" as \"2006-01-02T15:04:05Z07:00\": cannot parse \"\" as \"T\""}
FAIL
exit status 1
FAIL app/api 0.243s
Teraz użyj promptu, który wymusza dowód, minimalną poprawkę i test:
You are fixing a CI failure. You MUST use the log to justify every claim.
Context:
- Language: Go
- Failing test: TestCreateInvoice_DueDate
- Log snippet:
<PASTE LOG>
Task:
1) Quote the exact failing line(s) from the log and explain the root cause in 1-2 sentences.
2) Propose the smallest possible code change (one function, one file) to accept both RFC3339 and YYYY-MM-DD.
3) Show the exact patch.
4) Add one regression test that fails before the fix and passes after.
Return your answer with headings: Evidence, Minimal Fix, Patch, Regression Test.
Dobra odpowiedź wskaże mismatch w formacie parsowania, a potem dokona małej zmiany w jednej funkcji (np. parseDueDate w invoice.go) — spróbować RFC3339, a w razie niepowodzenia odpalić fallback 2006-01-02. Bez refaktoru, bez nowych pakietów.
Test regresyjny to strażnik: wysyłaj due_date: "2026-01-09" i oczekuj 201. Jeśli ktoś później usunie fallback, CI od razu zasygnalizuje problem.
Najkrótszy sposób, żeby stracić godzinę, to wkleić obcięty widok problemu. Logi CI są hałaśliwe, ale użyteczna część to często ~20 linii powyżej końcowego błędu.
Pułapki:
Jeśli podejrzewasz flakiness, nie maskuj go retry — usuń losowość (zamrożony czas, seed RNG, izolowane temp dir), żeby sygnał był czysty.
Zanim wypchniesz, zrób krótką kontrolę sanity:
Na koniec uruchom trochę szerszy zestaw niż tylko jedno zadanie (np. lint + unit tests). Czasem poprawka przepuszcza oryginalne zadanie, ale łamie inny target.
Jeśli chcesz, żeby to oszczędzało czas regularnie, traktuj prompt i strukturę odpowiedzi jak proces zespołowy. Celem są powtarzalne wejścia, powtarzalne wyjścia i mniej „misteryjnych poprawek”, które psują coś innego.
Zamień najlepszy prompt w snippet repozytoryjny i przypnij go w czacie zespołu. Kategoryzuj awarie CI (lint, unit, integration, packaging, deploy). Kiedy etykieta się powtarza, dodaj test lub check, który mógłby to wcześniej złapać. Trzymaj eksperymenty odwracalne, żeby móc szybko cofnąć.
Jeśli preferujesz workflow z czatem do budowania i iteracji, możesz przeprowadzić tę samą pętlę fix-test w Koder.ai, używać snapshotów podczas eksperymentów i eksportować kod, gdy poprawka jest gotowa do merge'u.
Zacznij od pierwszego prawdziwego błędu, a nie od końcowego exit 1.
Poproś, żeby udowodniło, że przeczytało log.
Użyj ograniczeń typu:
Domyślnie: najmniejszy patch, który powoduje, że nieudany krok zakończy się sukcesem.
Zazwyczaj oznacza to:
Unikaj "czyszczenia" dopóki CI nie jest zielone.
Wklej wystarczający kontekst, żeby odtworzyć błąd, nie tylko ostatnią czerwoną linię.
Dołącz:
Tak — powiedz to wyraźnie w ograniczeniach.
Przykładowe ograniczenia:
To utrzymuje odpowiedź skupioną i łatwą do review.
Najpierw napraw najwcześniejszy realny błąd.
W razie wątpliwości poproś model o wskazanie pierwszego kroku, który zawiódł w logu i trzymaj się go.
Traktuj flakiness jako sygnał do usunięcia losowości, nie do dodawania retries.
Typowe stabilizatory:
Gdy stanie się deterministyczne, „najmniejsza poprawka” staje się oczywista.
Uruchom dokładne polecenie, które CI wykonało, lokalnie.
Jeśli ciężko odtworzyć lokalnie, poproś o minimalny repro w repo, który wywołuje ten sam błąd (jeden test/target).
Napisz jednen skoncentrowany test regresyjny, który zawiedzie przed poprawką i przejdzie po niej.
Dobre cele:
Jeśli to błąd lintera/builda, ekwiwalent testu może być zaostrzeniem reguły lint lub dodaniem sprawdzenia wymuszającego regułę.
Używaj snapshotów/rollbacków, żeby eksperymenty były odwracalne.
Praktyczna pętla:
Jeśli używasz Koder.ai, snapshoty ułatwiają iterację bez mieszania eksperymentalnych zmian z końcowym patchem.
go test ./...npm testflutter test