4 min

Claude Code dla awarii CI: prompty do małych poprawek i testów

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

Claude Code dla awarii CI: prompty do małych poprawek i testów

Co idzie nie tak, gdy CI pada i AI zgaduje

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:

  • Przeczytaj output z błędem.
  • Zidentyfikuj najmniejszą zmianę, która sprawi, że krok się powiedzie.
  • Zostaw resztę bez zmian.

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ą.

Co zebrać zanim poprosisz o pomoc

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):

  • Pełny log błędu od pierwszej linii błędu aż do końca (nie tylko końcowy stack trace).\
  • Dokładne polecenie, które uruchomiło CI (np. go test ./..., npm test, flutter test, golangci-lint run).\
  • Ścieżki plików wymienione w błędzie oraz istotne pliki konfiguracyjne (konfiguracja testów, lintera, skrypty build).\
  • Co zmieniło się ostatnio: streszczenie diffu PR, bump zależności, zmiany konfiguracji CI.\
  • Czy to jest flaky: dwa–trzy nieudane uruchomienia i jedno udane, jeśli masz takie dane.

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):

Reguły promptu, które zmuszają do czytania outputu

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.

Reguły, które utrzymują model uczciwym

Wymagaj dowodu i małego planu. Dobry prompt wymusza pięć rzeczy:

  • Zacytuj dokładne linie błędu z logu CI (errors, stack trace, file:line) i wyraźnie napisz „Używam tych linii.”\
  • Podaj diagnozę w jednym zdaniu, bez wycofywania się.\
  • Zaproponuj minimalny plan patcha z 1–3 edycjami, nazywając dokładne pliki, które dotknie.\
  • Unikaj niezwiązanych zmian (bez formatowania, zmian nazw, refaktorów, bumpów zależności) chyba że wcześniej wyrazisz zgodę.\
  • Wypisz, czego nie jest pewne i jedną rzecz, która potwierdzi diagnozę.

Niepewność jest w porządku. Ukryta niepewność marnuje czas.

Fragment promptu gotowy do wklejenia

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.

Szablon promptu do awarii CI — do skopiowania

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ę:

  • Dołącz dokładne polecenie, które nie powiodło się, i pierwszy błąd (nie tylko podsumowanie).\
  • Jeśli jest wiele błędów, powiedz, który naprawić najpierw (zwykle najwcześniejszy realny błąd w logu).

Jak wymusić najmniejszą poprawkę, a nie przebudowę

Zamień logi CI na poprawki
Wklej log z nieudanego CI i wygeneruj możliwie najmniejszą poprawkę w Koder.ai w czacie.

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."

Prompt na test follow-up, który zapobiega powtórkom

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:

  • Jeśli awaria to crash w teście jednostkowym, prawdopodobnie chcesz nowy test lub wzmocnioną asercję.\
  • Jeśli awaria to build/lint, chcesz sprawdzenie, które wymusi regułę, żeby ten rodzaj błędu nie wrócił.

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:

  • Napisz jeden test regresyjny, który pada na aktualnym branchu main i przechodzi po poprawce.\
  • Niech celuje w tę samą klasę awarii, nie tylko w dokładną linię, która pękła.\
  • Umieść test w: <ścieżka/folder>. Stosuj konwencję nazewnictwa: <twoja konwencja>.\
  • Jeśli to reguła lint/build, dodaj lub doprecyzuj sprawdzenie, które wymusi regułę.\
  • Dodaj 2–3 zdania: dlaczego ten test złapie podobny błąd w przyszłości.

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.

Workflow krok po kroku, którego możesz używać

1) Daj mu awarię jak jest

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ł.

2) Wymagaj najmniejszego patcha najpierw

Poproś o najmniejszą możliwą zmianę w kodzie, która sprawi, że polecenie przejdzie. Odrzucaj refaktory. Zanim zastosujesz cokolwiek, niech wypisze:

  • Plik(i), które dotknie\
  • Dokładne zachowanie, które się zmieni\
  • Co nie zostanie zmienione

3) Uruchom ponownie to samo polecenie, trzymaj pętlę krótką

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ź.

4) Dodaj test regresyjny dla klasy awarii

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.

5) Przygotuj porządny pakiet PR

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.

Realistyczny przykład: od outputu do poprawki i testu

Zarabiaj za udostępnianie
Podziel się tym, jak naprawiasz awarie CI z Koder.ai i zdobądź kredyty za swój wkład.

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.

Typowe błędy, które marnują czas (i jak ich unikać)

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:

  • Wklejasz tylko ostatnią czerwoną linię (np. "exit 1") i ukrywasz prawdziwą przyczynę wcześniej (brakująca zmienna środowiskowa, padnięty snapshot, pierwszy test, który się wywalił). Naprawa: dołącz polecenie i okno logu z pierwszym realnym błędem.\
  • Pozwalasz modelowi "posprzątać" przy okazji (formatowanie, bump zależności, refaktory): to utrudnia review i łatwo złamać coś innego. Naprawa: zablokuj zakres na najmniejszym patchu i odrzuć wszystko niezwiązane.\
  • Przyjmujesz poprawkę niezweryfikowaną poleceniem CI: zawsze uruchom dokładnie to samo polecenie.\
  • Piszesz test, który nadal przechodzi po przywróceniu błędu: wymagaj testu, który padał na starym kodzie i przechodzi po poprawce.\
  • Mylisz flaky z realną regresją: zdecyduj, czy to nondeterministyczność (timing, sieć, kolejność) czy logiczny błąd, i traktuj odpowiednio.

Jeśli podejrzewasz flakiness, nie maskuj go retry — usuń losowość (zamrożony czas, seed RNG, izolowane temp dir), żeby sygnał był czysty.

Szybkie kontrole zanim zepchniesz poprawkę

Zweryfikuj poprawki w rzeczywistym wdrożeniu
Wdróż i hostuj aplikację po przejściu CI, żeby zweryfikować zachowanie end-to-end.

Zanim wypchniesz, zrób krótką kontrolę sanity:

  • Dowód: czy wyjaśnienie cytuje dokładne linie błędu?\
  • Zakres: czy zmiany są ograniczone do niezbędnego minimum?\
  • Kausalność: czy wyjaśnia, dlaczego zmiana odwraca warunek z fail na pass?\
  • Repro: czy uruchomiłeś dokładne polecenie CI (te same flagi, katalog roboczy)?\
  • Regresja: czy nowy test pada przed poprawką i przechodzi po niej?

Na koniec uruchom trochę szerszy zestaw niż tylko jedno zadanie (np. lint + unit tests). Czasem poprawka przepuszcza oryginalne zadanie, ale łamie inny target.

Następne kroki: zamień to w nawyk

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.

Często zadawane pytania

Gdzie w logu CI powinienem najpierw szukać, gdy zadanie się nie powiedzie?

Zacznij od pierwszego prawdziwego błędu, a nie od końcowego exit 1.

  • Znajdź najwcześniejszą linię pokazującą co się nie powiodło (nazwa testu, file:line, polecenie).\
  • Przeczytaj ~20–40 linii powyżej dla kontekstu i ustawienia.\
  • Ignoruj późniejsze „kaskadowe” błędy, dopóki nie naprawisz pierwszego.
Jak powstrzymać AI od zgadywania i podawania ogólnej poprawki?

Poproś, żeby udowodniło, że przeczytało log.

Użyj ograniczeń typu:

  • „Zacytuj dokładne linie błędu, których używasz.”\
  • „Jednozdaniowa diagnoza.”\
  • „Najmniejsza poprawka: 1–3 edycje z dokładnymi ścieżkami plików.”\
  • „Zatrzymaj się i dopytaj, jeśli log jest niekompletny.”
Co właściwie oznacza „najmniejsza poprawka” dla awarii CI?

Domyślnie: najmniejszy patch, który powoduje, że nieudany krok zakończy się sukcesem.

Zazwyczaj oznacza to:

  • Jedna ukierunkowana zmiana w kodzie (warunek zabezpieczający, poprawny import/ścieżka).\
  • Jedna zmiana konfiguracyjna specyficzna dla CI.\
  • Przywrócenie przypadkowo wprowadzonej zmiany zamiast przebudowy.

Unikaj "czyszczenia" dopóki CI nie jest zielone.

Co powinienem dołączyć, gdy proszę o pomoc przy nieudanym przebiegu CI?

Wklej wystarczający kontekst, żeby odtworzyć błąd, nie tylko ostatnią czerwoną linię.

Dołącz:

  • Dokładne polecenie CI (go test ./..., npm test, flutter test itp.).\
  • Log od pierwszej linii błędu do końca.\
  • Ścieżki plików wspomniane w błędach.\
  • Co zmieniło się ostatnio (bump zależności, edycja konfiguracji CI, streszczenie PR).\
  • Czy to jest flaky (parę nieudanych uruchomień i jedno udane).
Czy mogę jawnie powiedzieć modelowi, żeby nie refaktoryzował ani nie formatował niczego?

Tak — powiedz to wyraźnie w ograniczeniach.

Przykładowe ograniczenia:

  • „Brak refaktorów, zmiany nazw, formatowania ani podbijań zależności.”\
  • „Dotykaj tylko plików niezbędnych do poprawki.”\
  • „Jeśli zmienia się zachowanie, opisz dokładnie co i dlaczego to poprawne.”

To utrzymuje odpowiedź skupioną i łatwą do review.

Jeśli CI pokazuje wiele błędów, który mam naprawić najpierw?

Najpierw napraw najwcześniejszy realny błąd.

  • Późniejsze błędy często wynikają z pierwszego (np. build nieudany → testy/lint nie uruchamiają się poprawnie).\
  • Jeśli błędy są niezależne, wybierz ten, który najbardziej blokuje (zwykle build/lint przed integracją).

W razie wątpliwości poproś model o wskazanie pierwszego kroku, który zawiódł w logu i trzymaj się go.

Jak rozpoznać, czy awaria CI jest flaky i co wtedy zrobić?

Traktuj flakiness jako sygnał do usunięcia losowości, nie do dodawania retries.

Typowe stabilizatory:

  • Zamróź czas (wstrzyknij zegar, użyj stałych timestampów).\
  • Seed RNG.\
  • Unikaj wywołań sieciowych (mock/stub).\
  • Użyj izolowanych katalogów tymczasowych i unikalnych portów.

Gdy stanie się deterministyczne, „najmniejsza poprawka” staje się oczywista.

Jaki jest najlepszy sposób, by zweryfikować, że poprawka odpowiada CI i nie jest "szczęśliwym" przejściem?

Uruchom dokładne polecenie, które CI wykonało, lokalnie.

  • To samo polecenie i flagi co w CI.\
  • Dopasuj wersje środowiska (Go/Node/Flutter, OS) jeśli to możliwe.

Jeśli ciężko odtworzyć lokalnie, poproś o minimalny repro w repo, który wywołuje ten sam błąd (jeden test/target).

Co stanowi dobry test follow-up po naprawieniu awarii CI?

Napisz jednen skoncentrowany test regresyjny, który zawiedzie przed poprawką i przejdzie po niej.

Dobre cele:

  • Brzegowy przypadek, który spowodował awarię (null input, strefa czasowa, zaokrąglanie, uprawnienia).\
  • Nieco szersza klasa błędów (np. różne nieprawidłowe ID, a nie tylko jedno).

Jeśli to błąd lintera/builda, ekwiwalent testu może być zaostrzeniem reguły lint lub dodaniem sprawdzenia wymuszającego regułę.

Jak szybko iterować, nie zamieniając repo w bałagan podczas debugowania CI?

Używaj snapshotów/rollbacków, żeby eksperymenty były odwracalne.

Praktyczna pętla:

  • Wykonaj najmniejszą zmianę.\
  • Uruchom dokładne polecenie, które zawiodło.\
  • Jeśli nadal nie działa, cofnij się do snapshotu i spróbuj innego małego patcha.

Jeśli używasz Koder.ai, snapshoty ułatwiają iterację bez mieszania eksperymentalnych zmian z końcowym patchem.

Related posts