Przejdź do głównej zawartości

Automatyzacja wdrożeń z Codex: kontenery, skrypty wdrożeniowe i rollback

Codex automatyzuje wdrożenia, pisząc i testując całą maszynerię wokół wydania: Dockerfile, test dymny obrazu w CI, skrypty wdrożenia i rollbacku, migracje expand/contract oraz notatkę o ryzyku dla zatwierdzającego. Samo wdrożenie uruchamia pipeline CI za chronionym środowiskiem. Codex nigdy nie dostaje produkcyjnych poświadczeń, a o wydaniu decydują dowody z CI, nie podsumowanie agenta.

Twój proces wdrożenia to strona w wiki z 23 ręcznymi krokami, w tym „zaloguj się przez SSH na serwer i uruchom te cztery polecenia”. Gdy ostatnio ktoś pominął krok 14, produkcja leżała 20 minut, a jedyna osoba, która wiedziała dlaczego, była na urlopie. Ta strona jest dla dewelopera, który odpowiada za ścieżkę wydań swojej usługi, i dla tech leada, który zatwierdza zmiany na produkcji. Zakładamy, że używasz Codex CLI albo aplikacji desktopowej i masz już GitHub Actions; jeśli nie, zacznij od uruchamiania Codex w CI/CD.

  • Podział obowiązków: co pisze Codex, która bramka to potwierdza i kto podpisuje.
  • Trzy prompty do skopiowania: konfiguracja kontenerów, skrypty wdrożenia i rollbacku, migracja bezpieczna dla rollbacku.
  • Job CI z testem dymnym, który dowodzi, że obraz się buduje, startuje zdrowy, działa jako nie-root, mieści się w budżecie rozmiaru i czysto się zamyka.
  • Workflow produkcyjny, w którym Codex pisze notatkę o ryzyku w trybie tylko do odczytu, a wdrożenie zatwierdza konkretna osoba.
  • Prompt cotygodniowej automatyzacji, która wyłapie psujący się pipeline przed dniem wydania.

Zasada, która utrzymuje to w ryzach: Codex wytwarza artefakty i dowody, a uruchamia je pipeline. Każdy wiersz ma kontrolę, która działa bez czytania wygenerowanego kodu linijka po linijce.

KrokCo robi CodexBramka, która to potwierdzaKto podpisuje
Konfiguracja kontenerówPisze Dockerfile, compose.yaml, compose.override.yamlJob CI z testem dymnym obrazu (krok 3)Recenzent PR
Skrypty wdrożenia i rollbackuPisze scripts/deploy.sh, scripts/rollback.shshellcheck, --dry-run w CI, próba rollbacku na staginguWłaściciel usługi
MigracjePisze migracje expand/contractTesty poprzedniego wydania przechodzą na nowym schemacieRecenzent PR
Notatki do wydaniaTworzy szkic z git logCzłowiek publikuje szkicRelease manager
Wdrożenie produkcyjnePisze notatkę o ryzyku tylko do odczytu, nic więcejŚrodowisko GitHub z wymaganymi recenzentamiWskazana osoba zatwierdzająca
Po wdrożeniuNic w czasie działaniaTest dymny w deploy.sh, automatyczny rollback przy błędzieDyżurny inżynier

Notatki do wydania mają już utwardzony workflow na stronie o Codex w CI/CD; tutaj go nie powtarzamy.

  1. Zapisz zasady wdrożeń w AGENTS.md. Codex czyta AGENTS.md, zanim zacznie pracę, więc poniższe ograniczenia trafiają do każdego wątku, zadania w chmurze i uruchomienia w CI. Traktuj je jako wskazówki dla agenta. Zamkami są środowisko i poświadczenia z kroku 6.

    ## Deployment
    - Production deploys run only from `.github/workflows/deploy.yml`. Never run
    `scripts/deploy.sh` without `--dry-run`.
    - Images are tagged with the full git SHA. Never deploy or push `:latest`.
    - Migrations follow expand/contract: a release may add tables and nullable
    columns; dropping or renaming waits for the release after next.
    - Before you call deployment work done, run `shellcheck scripts/*.sh`,
    `scripts/deploy.sh --dry-run "$(git rev-parse HEAD)"` and the test suite,
    and paste the exit codes.
    - Test database: `postgres://localhost:5432/app_test` (the `postgres` service
    in `compose.yaml`).
  2. Wygeneruj konfigurację kontenerów. Rozpocznij wątek w Codex CLI albo w aplikacji desktopowej (w worktree, jeśli masz inną pracę w toku) i wklej poniższy prompt. Nazywa ograniczenia, które liczą się na produkcji, więc dostajesz działającą konfigurację, a nie przykład z podręcznika.

  3. Udowodnij działanie obrazu w CI, nie w czacie. Podsumowanie wątku „kontener startuje poprawnie” to deklaracja. Dowodem jest poniższy job, uruchamiany przy każdym pull requeście, który dotyka kontenera. Zmienna COMPOSE_FILE trzyma override deweloperski z dala od CI.

    .github/workflows/image-smoke.yml
    name: Image smoke test
    on:
    pull_request:
    paths: ['Dockerfile', 'compose*.yaml', 'package*.json', 'src/**']
    permissions:
    contents: read
    jobs:
    smoke:
    runs-on: ubuntu-latest
    env:
    COMPOSE_FILE: compose.yaml
    APP_IMAGE: app:ci
    MAX_IMAGE_MB: 250
    steps:
    - uses: actions/checkout@v7
    with:
    persist-credentials: false
    - name: Build and start the stack
    run: docker compose up --build --wait --wait-timeout 90
    - name: Health endpoint answers
    run: curl -fsS http://localhost:3000/health
    - name: App does not run as root
    run: test "$(docker compose exec -T app id -u)" != "0"
    - name: Image fits the size budget
    run: |
    size_mb=$(( $(docker image inspect "$APP_IMAGE" --format '{{.Size}}') / 1000000 ))
    echo "Image size: ${size_mb} MB"
    test "$size_mb" -le "$MAX_IMAGE_MB"
    - name: Shuts down cleanly on SIGTERM
    run: |
    docker compose stop --timeout 10 app
    code=$(docker inspect --format '{{.State.ExitCode}}' "$(docker compose ps -aq app)")
    echo "Exit code: $code"
    test "$code" = "0"
    - name: Logs on failure
    if: failure()
    run: docker compose logs --no-color

    Każdy kod wyjścia inny niż 0 oznacza, że obsługa SIGTERM zawiodła; 137 oznacza konkretnie, że po upływie limitu czasu Docker musiał wysłać SIGKILL. Gdy job się wywróci, wklej jego log do wątku Codex i poproś o poprawkę; kolejny push uruchomi te same kontrole.

  4. Zastąp wiki skryptami wdrożenia i rollbacku. Prompt wymaga trybu dry-run, niezmiennych tagów SHA i automatycznego rollbacku, bo to te trzy cechy pozwalają przetestować skrypt, zanim dotknie produkcji.

    Polecenie restartu kroczącego zależy od platformy. Podaj je w prompcie (kubectl rollout, fly deploy, API load balancera), żeby Codex nie zgadywał. Przed pierwszym uruchomieniem na produkcji przećwicz rollback.sh na stagingu i zapisz wynik w docs/runbooks/rollback-rehearsals.md (data, SHA, rezultat); kontrakt przećwiczonego rollbacku opisuje, co musi oznaczać „przećwiczony”.

  5. Zadbaj, by migracje dało się wycofać. Skrypt rollbacku uruchamiający migracje w dół może zniszczyć dane zapisane przez nowe wydanie. Bezpieczniejszy jest wzorzec expand/contract: wydanie, które dodaje kolumnę, nigdy żadnej nie usuwa, więc poprzedni obraz dalej działa na nowym schemacie, a rollback sprowadza się do podmiany obrazu.

    Job schema-compat dowodzi, że rollback nadal działa: uruchamia kod, do którego byś wracał, na schemacie, który właśnie tworzysz. Więcej przepisów expand/contract znajdziesz w wzorcach migracji baz danych.

  6. Postaw bramkę produkcji poza modelem. Utwórz w GitHubie środowisko production z wymaganymi recenzentami i trzymaj DEPLOY_TOKEN oraz DATABASE_URL wyłącznie jako sekrety tego środowiska. Codex działa w osobnym jobie tylko do odczytu i zapisuje notatkę o ryzyku w podsumowaniu uruchomienia, więc zatwierdzający czyta jeden ekran zamiast całego diffa. Job wdrożeniowy nigdy nie uruchamia Codex.

    .github/workflows/deploy.yml
    name: Deploy
    on:
    push:
    branches: [main]
    permissions:
    contents: read
    concurrency:
    group: production
    cancel-in-progress: false
    jobs:
    risk-brief:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v7
    with:
    fetch-depth: 0
    persist-credentials: false
    - id: codex
    uses: openai/codex-action@v1
    with:
    openai-api-key: ${{ secrets.OPENAI_API_KEY }}
    permission-profile: ":read-only"
    prompt: |
    You are writing a deploy risk brief for a human approver.
    Compare ${{ github.event.before }}..${{ github.sha }} with git log and git diff.
    Output Markdown, at most 25 lines:
    1. Risk: low, medium or high, with one sentence why.
    2. Migrations in this range: file names, and whether each is expand-only.
    3. Changed config, environment variables or feature flags.
    4. What the approver should check in staging before approving.
    Do not speculate beyond what the diff shows.
    - name: Publish the brief to the run summary
    env:
    BRIEF: ${{ steps.codex.outputs.final-message }}
    run: printf '%s\n' "$BRIEF" >> "$GITHUB_STEP_SUMMARY"
    deploy:
    needs: risk-brief
    runs-on: ubuntu-latest
    environment: production
    steps:
    - uses: actions/checkout@v7
    with:
    persist-credentials: false
    # Obraz dla tego SHA zbudował i wypchnął Twój workflow budujący.
    - name: Deploy
    env:
    DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
    DATABASE_URL: ${{ secrets.DATABASE_URL }}
    run: scripts/deploy.sh "$GITHUB_SHA"

    Jeśli github.event.before to same zera (pierwszy push gałęzi) albo commit nieosiągalny po force-pushu, zakres jest nieprawidłowy; wskaż wtedy w prompcie git log -1 albo poprzedni tag wydania.

    Grupa concurrency nie pozwala dwóm pushom wdrażać jednocześnie, bo wtedy wygrywa ten upload, który wyląduje ostatni. Profil uprawnień :read-only (beta; sprawdzone z codex-action v1.12 i Codex CLI 0.157.1, 2026-09-26) to wejście, które openai/codex-action zaleca zamiast przestarzałego sandbox; domyślna strategia bezpieczeństwa akcji, drop-sudo, pozostaje włączona. Pozostałe opcje utwardzania akcji opisuje strona o Codex w CI/CD.

  7. Zaplanuj cotygodniową kontrolę gotowości wdrożeniowej. Narzędzia wdrożeniowe psują się między wydaniami: przesuwa się obraz bazowy, skrypt przestaje przechodzić shellcheck, migracja nie nakłada się już na pustą bazę. Utwórz automatyzację Codex w aplikacji desktopowej na worktree według przewodnika po automatyzacjach Codex i wklej ten prompt bez zmian, gdy raz uruchomisz go ręcznie.

    Jeśli sandbox automatyzacji nie sięga do demona Dockera albo do sieci, zostaw kontrole obrazu jobowi z testem dymnym w CI; ten prompt odczytuje jego wyniki przez gh zamiast budować obraz od nowa.

Skąd wiesz, że wydanie jest bezpieczne, bez czytania każdej linijki?

Dział zatytułowany „Skąd wiesz, że wydanie jest bezpieczne, bez czytania każdej linijki?”

Nikt w zespole nie musi czytać wygenerowanego Dockerfile’a ani deploy.sh linijka po linijce. Wydanie jest bezpieczne, gdy spełnione są poniższe warunki, a każdy z nich widać w CI albo w repozytorium:

  • Zielony test dymny obrazu: obraz się buduje, /health odpowiada, użytkownik nie jest rootem, rozmiar mieści się w budżecie, a SIGTERM kończy proces czysto.
  • Skrypty sprawdzone przed użyciem: shellcheck przechodzi, deploy.sh --dry-run wypisuje plan, a dziennik prób rollbacku ma wpis młodszy niż 30 dni.
  • Zielona zgodność schematu: testy poprzedniego wydania przechodzą na nowym schemacie, więc rollback to podmiana obrazu.
  • Wskazana osoba zatwierdzająca: wymagany recenzent środowiska production czyta notatkę o ryzyku, sprawdza staging i zatwierdza. Notatka jest pomocnicza; bramką jest zatwierdzenie.
  • Dowody po wdrożeniu: deploy.sh porównuje /api/version z SHA i sam wykonuje rollback, a .deploy/log.jsonl zapisuje każdą próbę.

Właściciel usługi podpisuje skrypty i próbę rollbacku; recenzent środowiska podpisuje każde wydanie. Wersję tej bramki dla wszystkich narzędzi opisuje strona o bramkowaniu produkcji na etapie wdrożenia. Kanarki i automatyczny rollback wyzwalany przez SLO opisuje progressive delivery dla zmian pisanych przez agentów.

Codex melduje „wszystkie kontrole przeszły”, a nic nie zostało uruchomione. Podsumowanie to nie dowód. Prompty na tej stronie wymagają poleceń i kodów wyjścia; jeśli wątek nie pokazuje ani jednego, ani drugiego, poproś Codex o ponowne uruchomienie kontroli i wklejenie wyniku. Źródłem prawdy i tak są joby CI.

Polecenia Dockera nie działają wewnątrz openai/codex-action. Na Linuksie domyślna strategia drop-sudo odbiera dostęp do należących do roota gniazd usług w /run, w tym do demona Dockera (README codex-action, odczyt 2026-09-26). Buduj i uruchamiaj obrazy w zwykłym kroku albo jobie, a Codex daj do przeczytania logi. Nie przełączaj się na safety-strategy: unsafe, żeby odzyskać Dockera.

Obraz buduje się lokalnie, ale nie w CI. Lokalna pamięć warstw ukrywa brakujący plik albo Twój laptop ma ARM, a runner x86. Zostaw --build w CI, ustaw platform: linux/amd64 w usłudze app w compose.yaml (albo przekaż --platform linux/amd64 do docker build), gdy serwery produkcyjne to x86, i poproś Codex o wyjaśnienie pierwszej nieudanej warstwy na podstawie logu.

/health jest zielony, ale usługa nie jest gotowa. Endpoint zdrowia, który od razu zwraca 200, przechodzi każdą kontrolę, a potem serwuje błędy. Prompt kontenerowy uzależnia /health od PostgreSQL i Redisa; jeśli odziedziczyłeś płytką kontrolę, poproś Codex o dodanie sprawdzeń gotowości i zwracanie 503, dopóki nie przejdą.

Rollback się nie udaje, bo schemat się zmienił. Nowe wydanie usunęło albo przemianowało kolumnę i stary obraz nie startuje. Napraw to, wdrażając nową wersję z poprawką (roll forward), albo przywróć usuniętą kolumnę nową migracją. Zapobiegaj temu promptem expand/contract i jobem schema-compat.

Agent ma dostęp do produkcji. Ktoś umieścił DEPLOY_TOKEN w środowisku chmurowym Codex albo w jobie, który uruchamia openai/codex-action. Usuń go, zrotuj i trzymaj wyłącznie jako sekret środowiska production, w którym Codex nigdy nie działa. Właśnie dlatego bramka stoi poza modelem. Gdy Financial Times podał (2026-02-20, źródło wtórne: Engadget), że agent Kiro Amazona postanowił „delete and recreate the environment” i spowodował 13-godzinną awarię AWS Cost Explorer, Amazon nazwał to błędem użytkownika, „specifically misconfigured access controls”. Niezależnie od winy to kontrola dostępu decyduje, co agent może zepsuć.