Przejdź do głównej zawartości

Przećwiczony pipeline rollbacku cofa szkodliwą zmianę produkcyjną jednym chronionym poleceniem. Wersjonowany kontrakt wskazuje docelowy release, warunki wstępne i kontrole powrotu do normy, a wykonuje go job wdrożeniowy z krótkotrwałymi poświadczeniami. Agenci przygotowują decyzję i weryfikują powrót do normy, a rollback uruchamia wskazany człowiek albo deterministyczna reguła alertu dla usług niskiego ryzyka.

Piątek, 16:40. Release, który agent napisał w porze lunchu, przeszedł wszystkie kontrole, a błędy w checkoucie właśnie wzrosły trzykrotnie. Ktoś otwiera terminal, żeby zrobić git revert, ktoś inny pyta, czy migracja z zeszłego tygodnia jest odwracalna, a nikt nie pamięta, kiedy skrypt rollbacku ostatnio działał. Ta strona jest dla programisty, który odpowiada za pipeline wydań, i dla tech leada, który ma dyżur. Zamienia rollback z improwizacji w najlepiej przećwiczoną ścieżkę, jaką masz.

Pytanie scorecardu (Q21): Jak zarządzany jest rollback, jeśli wdrożenie wprowadzi regresję?

Odpowiedź za maksimum punktów: Przećwiczony rollback jedną komendą przez narzędzia MCP o ograniczonym zakresie (scoped), gotowy do automatycznego wywołania przy naruszeniu pasm metryk.

Kluczowe słowo to „scoped”. Na tej stronie narzędzia MCP agenta czytają stan wdrożeń i przygotowują decyzję, a samo polecenie działa w chronionym jobie. Uruchamia je człowiek albo deterministyczna reguła alertu, nigdy ocena modelu. Dzięki temu bramka akceptacji produkcji zostaje nienaruszona w czasie incydentu, czyli wtedy, gdy najbardziej kusi, żeby ją obejść.

  • Kontrakt rollbacku w YAML, który leży obok workflow wdrożenia i wskazuje cel, warunki wstępne, warunki przerwania i kontrole powrotu do normy.
  • Job rollbacku w GitHub Actions, który przechodzi przez tę samą bramkę akceptacji co deploy, jako jedyne wymagane wejście przyjmuje identyfikator release’u i nie ma żadnych stałych poświadczeń.
  • Konfigurację agenta tylko do odczytu dla Claude Code, Codeksa i Cursora, która przygotowuje rekord decyzji o rollbacku, zanim zespół zbierze się na kanale incydentu.
  • Trzy prompty do skopiowania: rekord decyzji, werdykt o powrocie do normy i audyt ćwiczenia.
  • Rytm ćwiczeń i checklistę gotowości, które dowodzą, że ścieżka działa, bez czytania skryptu linijka po linijce.

Dlaczego rollback zyskuje na znaczeniu, gdy kod piszą agenci

Dział zatytułowany „Dlaczego rollback zyskuje na znaczeniu, gdy kod piszą agenci”

Agenci zwiększają liczbę zmian, a każda zmiana to okazja, żeby zepsuć produkcję. Raport DORA z 2025 roku pokazał obie strony tego kompromisu: „we observe a positive relationship between AI adoption on both software delivery throughput and product performance” oraz „AI adoption does continue to have a negative relationship with software delivery stability” (Google Cloud / DORA, 2025-09-23). DORA wskazuje mechanizm: brak systemów kontroli takich jak „strong automated testing, mature version control practices, and fast feedback loops”.

Przećwiczony rollback jest jednym z tych systemów. To on pozwala też przestać czytać każdy diff: gdy zła zmiana kosztuje kilka minut częściowego wpływu zamiast wieczoru hotfixów, ryzyko mogą nieść testy, progressive delivery i kontrole powrotu do normy.

Rollback nie jest automatycznie bezpieczną opcją. Decyduj według tego, czego dotknęła zmiana, i zapisz odpowiedź w kontrakcie przed incydentem, nie w trakcie.

Szkodliwa zmiana…WybierzDlaczego
Jest za feature flagąWyłącz flagęDziała w kilka sekund, nie wymaga deployu i zostawia release na miejscu
To bezstanowy kod lub konfiguracja, a poprzedni release jest zachowanyRollback do poprzedniego niezmiennego release’uNajszybsze pełne odwrócenie; główna ścieżka tej strony
Zawiera migrację typu expand (nowa kolumna nullable, nowa tabela)Cofnij kod, zostaw schematStary release ignoruje nowy schemat
Zawiera migrację typu contract (drop, rename, zmiana typu) lub przepisała daneWdróż poprawkę (roll forward) albo uruchom przetestowany plan odtworzenia danychStary release nie odczyta nowych danych
Zmieniła format komunikatów w kolejce, format cache albo publiczne API, z którego korzystają już klienciWdróż poprawkę albo cofnij tylko wtedy, gdy oba formaty są czytelneStarzy konsumenci wyłożą się na komunikatach wyprodukowanych przez nowy release
Trafiła do aplikacji mobilnychWyłącz flagę po stronie serwera i wdróż poprawkęZainstalowanych aplikacji nie da się cofnąć

Przerwanie canary i kill switche flag należą do progressive delivery. Ta strona dotyczy rollbacku na poziomie release’u, który zostaje w odwodzie, gdy tamte mechanizmy nie wystarczą.

  1. Zapisz kontrakt rollbacku obok workflow wdrożenia. Zacommituj go jako deploy/rollback.yml i przeglądaj jak kod. Poniższy przykład jest ilustracyjny; zastąp polecenie i kontrole przetestowanym interfejsem swojej platformy.

    # deploy/rollback.yml — reviewed by the service owner
    service: checkout-api
    risk_class: standard # low | standard | high, as in progressive delivery
    target: previous-retained-release # an immutable, signed release ID, never a branch
    command: ./scripts/rollback.sh --release "$RELEASE_ID"
    dry_run: ./scripts/rollback.sh --release "$RELEASE_ID" --dry-run
    executor_identity: github-environment:production # the same gate as a deploy
    approver_role: incident-commander
    auto_trigger: # deterministic, never model-decided
    allowed: false # true only for low-risk, stateless services
    alert_rule: checkout-error-budget-burn-fast
    preconditions:
    - current release equals EXPECTED_RELEASE
    - target release artifact is retained and its signature verifies
    - no migration since target is marked "contract"
    abort_conditions:
    - target release has an active security block
    - a data migration since target is not backward compatible
    recovery_checks:
    - error-budget fast-burn alert clears and stays clear for 10 minutes
    - checkout synthetic passes from two regions
    - p95 latency within the pre-incident band
    last_rehearsal: 2026-09-18 # updated by the rehearsal job, not by hand
    evidence: incident record + deployment audit log

    Najwięcej pracy wykonują trzy pola. preconditions i abort_conditions pozwalają maszynowo sprawdzić ryzykowne przypadki z tabeli decyzji. recovery_checks definiuje „powrót do normy”, zanim ktokolwiek będzie pod presją. last_rehearsal pozwala CI odrzucić release, gdy ścieżka rollbacku się zestarzała.

  2. Niech skrypt odmawia, a nie zgaduje. scripts/rollback.sh sprawdza każdy warunek wstępny i warunek przerwania, zanim cokolwiek zmieni, i kończy się kodem niezerowym z podaniem powodu, gdy któryś nie jest spełniony. --dry-run wykonuje te same sprawdzenia i wypisuje plan. Skrypt nigdy nie wybiera celu sam: przyjmuje jeden identyfikator release’u i go weryfikuje.

  3. Uruchamiaj skrypt tylko w chronionym jobie. Dodaj workflow workflow_dispatch, który działa w tym samym środowisku production co deploy. Wtedy wymagany reviewer, polityka zaufania OIDC i ślad audytowy z akceptacji produkcji jako granicy systemu działają bez zmian.

    .github/workflows/rollback.yml
    name: rollback
    on:
    workflow_dispatch:
    inputs:
    release_id:
    description: Immutable release ID to restore
    required: true
    type: string
    target_env:
    description: Environment to roll back
    required: true
    type: choice
    options: [staging, production]
    default: production
    permissions:
    contents: read
    concurrency:
    group: ${{ inputs.target_env }}-deploy # the deploy workflow's group: never race a deploy
    cancel-in-progress: false
    jobs:
    dry-run:
    runs-on: ubuntu-latest
    permissions:
    contents: read
    id-token: write # read-only cloud credentials for the precondition checks
    steps:
    - uses: actions/checkout@v7
    with:
    persist-credentials: false
    # Add a read-only OIDC login here (a role that can list releases and read the registry,
    # nothing more), so the preconditions can check the current release and the target artifact.
    - name: Validate input and preconditions
    env:
    RELEASE_ID: ${{ inputs.release_id }} # passed as env, never interpolated into the script
    run: |
    [[ "$RELEASE_ID" =~ ^[a-z0-9._-]{1,64}$ ]] || { echo "invalid release id"; exit 1; }
    ./scripts/rollback.sh --release "$RELEASE_ID" --dry-run | tee -a "$GITHUB_STEP_SUMMARY"
    rollback:
    needs: dry-run
    runs-on: ubuntu-latest
    environment: ${{ inputs.target_env }} # waits for that environment's required reviewer
    permissions:
    contents: read
    id-token: write # short-lived cloud credentials after approval
    steps:
    - uses: actions/checkout@v7
    with:
    persist-credentials: false
    # Add your cloud's OIDC login step here; each role trusts only its own environment subject.
    - name: Roll back
    env:
    RELEASE_ID: ${{ inputs.release_id }}
    run: ./scripts/rollback.sh --release "$RELEASE_ID"

    Wejście target_env służy ćwiczeniom: ten sam plik działa na środowisku staging, które ma własnego wymaganego reviewera i własną rolę OIDC. Przebieg próbny (dry run) dostaje tylko poświadczenia do odczytu, a jego wynik trafia do podsumowania joba, więc osoba akceptująca widzi plan na tej samej stronie co przycisk Review deployments. W tym workflow nie działa żaden krok agenta.

    Wspólna grupa concurrency nie pozwala, żeby rollback działał równolegle z deployem, ale nie ustawia ich w kolejce: GitHub Actions trzyma w grupie najwyżej jedno oczekujące uruchomienie. Późniejsze uruchomienie w tej samej grupie anuluje oczekujące, więc najpierw wstrzymaj automatyczne wdrożenia (gh workflow disable deploy.yml) i sprawdź, że rollback czeka w kolejce, a nie został anulowany.

    Nadaj środowiskom production (i staging) tę samą regułę gałęzi wdrożeniowych, tylko gałąź domyślna, żeby zaakceptowany job zawsze uruchamiał przejrzany scripts/rollback.sh. Bez niej każdy z prawem zapisu może uruchomić rollback.yml z własnej gałęzi, a reviewer zaakceptuje skrypt, którego nikt nie przejrzał.

  4. Podłącz deterministyczny wyzwalacz tylko tam, gdzie pozwala na to kontrakt. Środowisko production zawsze czeka na wymaganego reviewera, więc alert, który uruchamia rollback.yml, tylko ustawia żądanie w kolejce: alert budzi dyżurnego, a ten akceptuje. To jest ustawienie domyślne i jedyna ścieżka dla usługi, której kontrakt mówi auto_trigger.allowed: false. Dla usługi z wartością true daj ścieżce automatycznej osobne drzwi, zamiast osłabiać wspólne:

    • Drugi workflow, .github/workflows/rollback-auto.yml, z tymi samymi krokami co rollback.yml, przypisany do drugiego środowiska, production-auto.
    • production-auto nie ma wymaganego reviewera. Chronią je reguła gałęzi wdrożeniowych, która dopuszcza tylko gałąź domyślną, oraz warunek zaufania OIDC w chmurze, który akceptuje wyłącznie subject environment:production-auto i tylko dla ról wcześniej zatwierdzonych usług.
    • Uruchamia go system alertów (nie agent) przez GitHub App, której tokenu nie ma żaden człowiek ani agent, i przekazuje identyfikator release’u z poprzedniego udanego wdrożenia. Job odrzuca każdego innego wywołującego i każdą usługę, której kontrakt na to nie pozwala.
    # .github/workflows/rollback-auto.yml: only the differences from rollback.yml
    concurrency:
    group: production-deploy # still never races a deploy
    jobs:
    rollback:
    if: github.actor == 'alert-bridge[bot]' # the alerting system's GitHub App
    environment: production-auto # no reviewer: branch rule + OIDC trust only
    steps:
    # checkout, read-only login and dry run as in rollback.yml, then:
    - name: Refuse unless the contract allows automatic rollback
    run: test "$(yq '.auto_trigger.allowed' deploy/rollback.yml)" = "true"

    Reguła gałęzi jest kluczowa: bez niej każdy, kto może wypchnąć gałąź, mógłby zmienić linię if: i dostać się do środowiska bez review. Deterministyczne wykrywanie anomalii pokazuje, jak wersjonować regułę alertu i testować ją na historycznych danych.

  5. Niech CI pilnuje świeżości ćwiczeń. Dodaj do workflow wdrożenia, przed jobem deployu, krok, który czyta last_rehearsal z kontraktu i kończy się błędem, gdy data jest starsza, niż pozwala polityka, na przykład 30 dni. yq jest preinstalowany na runnerach Ubuntu GitHuba.

    Bramka blokuje też poprawkę (roll forward), którą w czasie incydentu zaleca tabela decyzji, więc daj jej jedno udokumentowane wyjście: deploy uruchomiony z identyfikatorem incydentu pomija sprawdzenie, zapisuje ten identyfikator w podsumowaniu joba i automatycznie otwiera zgłoszenie na ćwiczenie rollbacku.

    .github/workflows/deploy.yml
    on:
    push:
    branches: [main]
    workflow_dispatch:
    inputs:
    incident_id:
    description: Incident ID for an emergency roll-forward (skips the freshness gate)
    required: false
    type: string
    # ...in the job that gates the deploy (it needs `issues: write` for the ticket):
    - name: Block the release when the rollback rehearsal is stale
    if: ${{ !inputs.incident_id }}
    run: |
    last=$(yq '.last_rehearsal' deploy/rollback.yml)
    if [[ $(date -d "$last" +%s) -lt $(date -d '-30 days' +%s) ]]; then
    echo "Rollback last rehearsed on $last; rehearse before shipping."; exit 1
    fi
    - name: Record the incident bypass and open a rehearsal ticket
    if: ${{ inputs.incident_id }}
    env:
    INCIDENT_ID: ${{ inputs.incident_id }}
    GH_TOKEN: ${{ github.token }}
    run: |
    echo "Freshness gate skipped for incident $INCIDENT_ID" >> "$GITHUB_STEP_SUMMARY"
    gh issue create --title "Rehearse rollback after incident $INCIDENT_ID" \
    --body "Deploy run $GITHUB_RUN_ID skipped the rehearsal-freshness gate."

    Przestarzała ścieżka rollbacku blokuje wtedy zwykłe wydania, zamiast zaskoczyć cię w środku incydentu, a każde obejście zostawia po sobie nazwany incydent i otwarte zgłoszenie. Bramka czyta datę z repozytorium, a przy push sam workflow też pochodzi z repozytorium, więc pull request (także agenta) może przesunąć last_rehearsal albo auto_trigger.allowed lub usunąć ten krok. Obejmij deploy/rollback.yml, scripts/rollback.sh i /.github/workflows/ wpisem w CODEOWNERS dla właściciela usługi z wymaganą akceptacją właściciela kodu i odrzucaj każdą zmianę last_rehearsal, która nie pochodzi z pull requesta joba próby.

Przy rollbacku inicjowanym przez człowieka inżynier dyżurny uruchamia jedno polecenie i akceptuje je na platformie:

Okno terminala
# terminal, as the on-call engineer
gh workflow run rollback.yml -f release_id=2026-09-26.3 -f target_env=production

Zadanie agenta to ta część, którą ludzie robią źle w piątek o 16:40: zebranie dowodów, sprawdzenie warunków wstępnych względem kontraktu i napisanie czytelnego rekordu decyzji. Daj mu dostęp tylko do odczytu do stanu wdrożeń, na przykład zestaw narzędzi Actions serwera GitHub MCP w trybie read-only (https://api.githubcopilot.com/mcp/x/actions/readonly, zgodnie z README github-mcp-server), oraz token tożsamości diagnostycznej, która nie może uruchamiać workflow. Konfiguracja różni się między narzędziami.

Podłącz zestaw narzędzi read-only z tokenem z magazynu sekretów, a potem uruchom prompt decyzji w trybie nieinteraktywnym (-p), z allowlistą. Powłoka podstawia wartość zmiennej, a Claude Code zapisuje go w twojej lokalnej konfiguracji; użyj krótkotrwałego tokenu tylko do odczytu i regularnie go rotuj. Tryb dontAsk odrzuca każde wywołanie narzędzia, które wymagałoby pytania, więc agent nie uruchomi gh workflow run ani gh api, dopóki na nie nie zezwolisz; mcp__github-actions-ro dopuszcza wszystkie narzędzia serwera read-only.

Okno terminala
# terminal, as the diagnostic identity
claude mcp add --transport http github-actions-ro \
https://api.githubcopilot.com/mcp/x/actions/readonly \
-H "Authorization: Bearer $GITHUB_READONLY_TOKEN"
claude -p --permission-mode dontAsk \
--allowedTools "Read,Grep,Glob,mcp__github-actions-ro,Bash(gh run view *),Bash(gh run list *),Bash(gh release view *)" \
--output-format json \
"$(cat prompts/rollback-decision.txt)" > rollback-decision.json

Flagi sprawdzone w claude --help, v2.1.283.

Trzymaj prompt w repozytorium (prompts/rollback-decision.txt), żeby każdy dyżurny uruchamiał ten sam, a każda jego zmiana przechodziła review.

Zastąp RUN_ID identyfikatorem, który wypisuje gh run list --workflow rollback.yml.

Ćwiczenie dowodzi czegokolwiek tylko wtedy, gdy używa prawdziwej ścieżki. Przeprowadzaj je regularnie, na stagingu albo w środowisku o kształcie produkcji, z tym samym workflow, tymi samymi tożsamościami i bramką środowiska skonfigurowaną tak jak na produkcji.

  1. Wdróż na staging znany release, a potem celowo zły, który łamie jedną z kontroli powrotu do normy, na przykład test syntetyczny zwracający błędy.
  2. Uruchom prompt decyzji i sprawdź, czy agent wskazuje właściwy cel i poprawnie ocenia każdy warunek wstępny.
  3. Uruchom rollback.yml z target_env=staging (gh workflow run rollback.yml -f release_id=<known-good> -f target_env=staging) i niech zaakceptuje go druga osoba. Środowisko staging też ma wymaganego reviewera, dokładnie tak jak produkcja.
  4. Uruchom prompt werdyktu o powrocie do normy i porównaj werdykt z dashboardami.
  5. Zapisz wynik: kto uruchamiał, kto akceptował, czas startu i końca, czas powrotu do normy, werdykt i to, co się zepsuło. Job ćwiczenia otwiera potem pull request, który aktualizuje last_rehearsal w kontrakcie.

Job ćwiczenia to workflow uruchamiany według harmonogramu (on: schedule, na przykład co tydzień), który sam wykonuje kroki 1, 3 i 5: wdraża oba release’y, uruchamia rollback, czeka na reviewera stagingu i otwiera pull request z zapisanym wynikiem. Prompty z kroków 2 i 4 uruchamia para dyżurnych.

Jak sprawdzić, że rollback zadziałał, bez czytania skryptu?

Dział zatytułowany „Jak sprawdzić, że rollback zadziałał, bez czytania skryptu?”

Weryfikujesz zachowanie, nie kod. Cztery dowody zastępują czytanie linijka po linijce:

  • Przebieg próbny wypisuje każdy warunek wstępny i jego wynik, zanim osoba akceptująca kliknie.
  • Kontrole powrotu do normy z kontraktu zwracają wartości, nie opinie, a prompt werdyktu raportuje je ze znacznikami czasu.
  • Zapis ćwiczenia pokazuje, że ten sam job, ta sama tożsamość i ta sama bramka niedawno zadziałały, ze zmierzonym czasem powrotu do normy.
  • Log audytowy wskazuje, kto uruchomił, kto zaakceptował i który release został wdrożony.

Powrót do normy ogłasza osoba dowodząca incydentem (incident commander), nie model. Potem luka, przez którą zmiana przeszła, staje się testem albo evalem, jak opisuje incydent spowodowany przez agenta, a incydent wraca do cyklu przez etap Maintain.

Co psuje się w pipeline rollbacku i jak to naprawić?

Dział zatytułowany „Co psuje się w pipeline rollbacku i jak to naprawić?”

Docelowy artefakt zniknął. Polityka retencji usunęła poprzedni obraz i skrypt nie ma czego przywrócić. Co zrobić: teraz wdróż poprawkę; potem zachowuj co najmniej kilka ostatnich release’ów produkcyjnych i niech ćwiczenie pobiera cel z produkcyjnego rejestru.

Migracja nie jest wstecznie kompatybilna. Stary release startuje i pada na nowym schemacie. Co zrobić: przerwij rollback i wdróż poprawkę. Zapobiegaj temu migracjami expand-and-contract i oznaczaj każdą migrację typu contract w release, żeby wyłapał ją warunek wstępny.

Ćwiczenie używało innych uprawnień. Staging działał z tokenem admina, a produkcyjne OIDC odrzuca job. Co zrobić: uruchom job ścieżką break-glass zdefiniowaną w procesie incydentowym, potem popraw ćwiczenie tak, by używało dokładnie tego samego środowiska i polityki zaufania, i ponownie uruchom prompt audytu ćwiczenia.

Deploy ścigał się z rollbackiem. Auto-merge wdrożył nowy release w trakcie rollbacku i produkcja skończyła na żadnym z nich. Co zrobić: wstrzymaj automatyczne wdrożenia (gh workflow disable deploy.yml), sprawdź, że żaden deploy nie czeka w kolejce, powtórz rollback i utrzymuj wspólną grupę concurrency w obu workflow, jak wyjaśnia krok 3.

Kontrole powrotu do normy przechodzą, a użytkownicy nadal mają błędy. Kontrole obserwowały zdrowie usługi, a nie ścieżkę użytkownika. Co zrobić: nie zamykaj incydentu, dodaj test syntetyczny dla zepsutej ścieżki do recovery_checks i traktuj niejednoznaczne sygnały jak brak powrotu do normy.

Agent dostał uprawnienia zapisu, „żeby było szybciej”. Fałszywy alarm cofnął zdrowy release w szczycie ruchu. Co zrobić: unieważnij token, podłącz z powrotem endpoint read-only i przenieś automatyczne wyzwalanie do wersjonowanej reguły alertu, na którą pozwala kontrakt.

  • deploy/rollback.yml istnieje dla usługi, wskazuje niezmienny cel i przeszedł review właściciela.
  • Job rollbacku używa bramki środowiska produkcyjnego i krótkotrwałych poświadczeń, a nie działa w nim żaden krok agenta.
  • Środowiska production i staging dopuszczają wdrożenia tylko z gałęzi domyślnej, więc akceptacja zawsze uruchamia przejrzany skrypt.
  • Warunki wstępne, warunki przerwania i kontrole powrotu do normy wykonują się automatycznie w przebiegu próbnym.
  • Agenci mają dostęp do wdrożeń tylko do odczytu i nie mogą uruchomić workflow.
  • Automatyczne wyzwalanie jest ograniczone do usług, których kontrakt na to pozwala, przez deterministyczną regułę alertu i osobne środowisko production-auto, do którego dociera tylko aplikacja alertów.
  • Ćwiczenie w oknie wymaganym przez politykę zapisało wykonawcę, osobę akceptującą, czasy, czas powrotu do normy i wnioski.
  • CI blokuje release, gdy ostatnie ćwiczenie jest przestarzałe, z wyjątkiem deployu z identyfikatorem incydentu, który otwiera zgłoszenie na ćwiczenie.
  • Powrót do normy ogłasza dowodzący incydentem.

Oficjalne źródła: środowiska wdrożeniowe GitHub, serwer GitHub MCP i etap Deploy w metodzie.

Najczęstsze pytania

Jak przećwiczony pipeline rollbacku zachowuje ludzką kontrolę nad produkcją?

Wersjonowany kontrakt rollbacku określa docelowy release, warunki wstępne i kontrole powrotu do normy, a wykonuje go chroniony job z krótkotrwałymi poświadczeniami uruchomiony przez wskazanego człowieka lub deterministyczną regułę alertu.

Jaką rolę pełnią agenci kodujący podczas rollbacku na produkcji?

Agenci pomagają przygotować zapis decyzji i zweryfikować powrót usługi do normy na podstawie danych tylko do odczytu, ale nie mają poświadczeń produkcyjnych i sami nie uruchamiają rollbacku.