Wzorce pipeline'ów CI/CD
ENReceptury pipeline’ów CI/CD dla agentów AI to gotowe prompty i przejrzany YAML, dzięki którym Claude Code, Codex lub Cursor generują pipeline’y GitHub Actions, GitLab CI albo Jenkins z bramkami, które potrafią zablokować zmianę: testy z prawdziwych skryptów repozytorium, skan obrazu przed pushem, akcje przypięte do commitów i deploy czekający na zatwierdzenie przez człowieka.
Twój deploy przeszedł wszystkie checki w CI, a mimo to wypuścił krytyczne CVE. Testy były zielone, obraz się zbudował, ale krok skanowania tylko wgrywał raport, więc nic w pipeline’ie nie mogło powiedzieć „nie”. Agent, który napisał workflow, zrobił dokładnie to, o co go poproszono. Nikt nie poprosił go o bramkę, która potrafi zatrzymać zmianę.
Ta strona jest dla developera albo tech leada, który odpowiada za pipeline serwisu i chce, żeby pisał go agent. Receptury poniżej generują YAML, a potem udowadniają, że każda bramka potrafi zrobić się czerwona, więc ufasz pipeline’owi bez ponownego czytania 200 linii.
Co wyniesiesz z tych receptur CI/CD
Dział zatytułowany „Co wyniesiesz z tych receptur CI/CD”- Prompt, który z
package.jsoniDockerfilerobi workflow GitHub Actions z matrycą wersji Node, skanem Trivy uruchamianym przed pushem i jobem wdrożeniowym za GitHub Environment. - Ćwiczenie bramek:
actionlint,zizmori jednorazowe pull requesty, które muszą zrobić się czerwone, więc wiesz, że każda bramka blokuje, zamiast to zakładać. - Prompt, który zamienia log nieudanego uruchomienia w jedną przyczynę źródłową i jedną poprawkę.
- Krok AI review dla pull requestów zmieniających pipeline w Claude Code, Codex albo Cursorze, skonfigurowany z najmniejszymi uprawnieniami.
- Tryby awarii, na które wygenerowane pipeline’y trafiają najpierw, razem ze sposobem wyjścia z każdego.
Szersze techniki pipeline’owe (buildy świadome zmian, kwarantanna niestabilnych testów, progresywne rollouty) opisuje automatyzacja pipeline’ów z AI. Ta strona zajmuje się wyłącznie generowaniem i utwardzaniem samego pliku pipeline’u.
Jak sprawić, żeby agent wygenerował pipeline pasujący do twojego repozytorium?
Dział zatytułowany „Jak sprawić, żeby agent wygenerował pipeline pasujący do twojego repozytorium?”Goły prompt „stwórz pipeline CI/CD” daje wiarygodnie wyglądający workflow dla projektu, którego nie masz: zły menedżer pakietów, wymyślony npm run test:ci, wersja Node, której nigdy nie używałeś. Zakotwicz agenta w plikach, które już istnieją, i opisz bramki przez to, co ma je wywrócić.
W katalogu głównym repozytorium uruchom claude. Claude Code sam czyta package.json, Dockerfile i istniejące .github/workflows/*, więc niczego nie wklejasz. Żeby przejrzeć plan, zanim zmieni się jakikolwiek plik, zacznij w trybie planowania:
claude --permission-mode planWklej prompt poniżej. Gdy plan wymieni skrypty znalezione w package.json, zatwierdź go i pozwól Claude Code zapisać plik.
W katalogu głównym repozytorium uruchom Codex z profilem uprawnień :workspace (beta w Codex CLI 0.157.1), który pozwala pisać w repozytorium i nigdzie indziej:
codex -c default_permissions=":workspace"Wklej prompt poniżej. Profil :workspace nie daje dostępu do sieci, więc Codex zapyta, zanim uruchomi git ls-remote, żeby sprawdzić SHA akcji. Zatwierdź tę jedną prośbę.
Otwórz repozytorium w Cursorze, przełącz agenta w Plan Mode i dodaj do kontekstu @package.json, @Dockerfile oraz istniejące pliki workflow. Wklej prompt poniżej, przejrzyj plan, a potem pozwól agentowi zapisać .github/workflows/ci.yml i przejrzyj diff w edytorze, zanim go zachowasz.
Dobry wynik ma taki kształt. Fragment pokazuje tagi dla czytelności; wynik agenta zawiera SHA:
# .github/workflows/ci.yml (excerpt)name: CIon: push: { branches: [main] } pull_request: release: { types: [published] }
permissions: contents: read
jobs: test: runs-on: ubuntu-latest strategy: matrix: { node: [22, 24] } steps: - uses: actions/checkout@v7 with: { persist-credentials: false } - uses: actions/setup-node@v7 with: node-version: ${{ matrix.node }} cache: npm - run: npm ci - run: npm test # the script that exists in package.json
image: needs: test runs-on: ubuntu-latest permissions: contents: read packages: write env: IMAGE: ghcr.io/acme/billing-api:${{ github.sha }} # GHCR names must be lowercase steps: - uses: actions/checkout@v7 with: { persist-credentials: false } - uses: docker/setup-buildx-action@v4 - name: Build (loaded locally, not pushed) uses: docker/build-push-action@v7 with: load: true tags: ${{ env.IMAGE }} cache-from: type=gha cache-to: type=gha,mode=max - name: Scan - fails the job on fixable CRITICAL/HIGH uses: aquasecurity/trivy-action@v0.36.0 with: image-ref: ${{ env.IMAGE }} severity: CRITICAL,HIGH ignore-unfixed: true exit-code: '1' - if: github.event_name != 'pull_request' uses: docker/login-action@v4 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Push only what passed the scan if: github.event_name != 'pull_request' run: docker push "$IMAGE"
deploy-prod: needs: image if: github.event_name == 'release' runs-on: ubuntu-latest environment: production # required reviewers on this environment = the human sign-off permissions: contents: read id-token: write # OIDC to the cloud, no stored cloud keys steps: - uses: actions/checkout@v7 with: { persist-credentials: false } # TODO: cloud login via OIDC, then the rolloutBezpieczeństwo trzymają trzy linie, więc to je sprawdzasz najpierw:
exit-code: '1'zamienia skan z raportu w bramkę. Bez tego Trivy wypisuje znaleziska, a job zostaje zielony.load: trueprzed skanem idocker pushpo nim sprawiają, że podatny obraz nigdy nie trafia do rejestru. Skan popush: trueblokuje deploy, ale zły obraz jest już opublikowany.environment: productionnic nie robi, dopóki nie dodasz do tego środowiska wymaganych recenzentów w ustawieniach repozytorium. YAML nazywa bramkę, ustawienie ją egzekwuje.
O Dockerfile, który buduje pipeline, piszemy we wzorcach Docker i kontenerów. Rollout, który uruchamia job wdrożeniowy, opisują wzorce orkiestracji Kubernetes oraz progressive delivery zmian pisanych przez agentów.
Jak udowodnić, że bramki pipeline’u naprawdę blokują?
Dział zatytułowany „Jak udowodnić, że bramki pipeline’u naprawdę blokują?”Wygenerowany pipeline, który nigdy nie był czerwony, jest pipeline’em nieprzetestowanym. Zamiast czytać każdą linię, uruchom dwa statyczne checkery i jedno ćwiczenie, które celowo wywraca każdą bramkę. Z testami jest tak samo: bramka, która nie potrafi zawieść, jest gorsza niż brak bramki, bo daje zielony check bez żadnego bezpieczeństwa.
-
Sprawdź składnię i wyrażenia workflow.
actionlintwyłapuje nieprawidłowe klucze, zepsute wyrażenia${{ }}i błędy powłoki w blokachrun:. Zainstaluj go przezbrew install actionlintalbogo install github.com/rhysd/actionlint/cmd/actionlint@latesti uruchomactionlintw katalogu głównym repozytorium. -
Przeprowadź audyt bezpieczeństwa workflow.
zizmor(PyPIzizmor1.30.1, sprawdzone 2026-09-26) zgłaszatemplate-injection,excessive-permissions,unpinned-uses,cache-poisoningiartipacked(poświadczenia checkoutu zostawione na dysku). Uruchomuvx zizmor .github/workflows/. Od wersji 1.20.0 domyślna polityka wymaga przypięcia każdej akcji przez SHA, takżeactions/*, więc workflow przypięty tagami nie przejdzie tego kroku, dopóki agent nie rozwiąże SHA. -
Przeprowadź ćwiczenie bramek. Niech agent otworzy szkicowe pull requesty z jednorazowych gałęzi, z których każda niesie dokładnie jedną celową awarię (prompt poniżej). Trzymaj awarie na osobnych gałęziach:
imagezależy odtest, więc padający test na tej samej gałęzi pominąłby skan i niczego by o nim nie udowodnił. Każda bramka musi zrobić się czerwona na swojej gałęzi, adeploy-prodnie może wystartować. -
Spraw, żeby bramki były wiążące. W ochronie gałęzi albo w zestawie reguł (
ruleset) dlamainoznacztestiimagejako wymagane status checki i dodaj wymaganych recenzentów do środowiskaproduction. Do tego czasu czerwony check jest tylko radą: każdy z prawem merge’a może go obejść. Wymagane checki nadal uruchamiają plik workflow z samego pull requesta, więc pull request może usunąć krok skanowania i pozostać zielony; obejmij/.github/regułąCODEOWNERSi włącz w tym samym zestawie reguł wymaganą recenzję właścicieli kodu. -
Zapisz, kto zatwierdza. Wymagani recenzenci środowiska
productionto osoby z uprawnieniami produkcyjnymi. Agent pisze i naprawia pipeline, a każdy deploy produkcyjny zatwierdza wskazany z nazwiska człowiek. Zobacz akceptację produkcji jako granicę systemu.
Gdy ćwiczenie się skończy, porównaj faktycznie czerwone checki z listą agenta. Bramka, która została zielona na swojej gałęzi, to znalezisko, a nie przypadkowa, niestabilna awaria. Zamknij szkicowe pull requesty i usuń gałęzie, gdy każda bramka zawiodła tam, gdzie powinna.
Jak zdiagnozować czerwone uruchomienie bez przewijania logu?
Dział zatytułowany „Jak zdiagnozować czerwone uruchomienie bez przewijania logu?”Najdroższa część CI to uruchomienie, które pada 400 linii w głąb logu, bo npm ci zwróciło 1. Pobierz przez GitHub CLI tylko nieudane kroki i daj agentowi log razem z definicją joba:
gh run view RUN_ID --log-failed > failed.logRUN_ID to numer z adresu URL uruchomienia. Workflow jest identyczny we wszystkich trzech narzędziach: w Claude Code i Codex podajesz w prompcie ścieżkę failed.log, w Cursorze dołączasz plik przez @failed.log.
Żeby agent sam czytał uruchomienia, zarejestruj zestaw narzędzi Actions serwera GitHub MCP w trybie tylko do odczytu, z drobnoziarnistym tokenem dostępu tylko do odczytu w zmiennej GITHUB_PAT:
claude mcp add --transport http github-actions \ https://api.githubcopilot.com/mcp/x/actions/readonly \ -H "Authorization: Bearer $GITHUB_PAT"Powłoka rozwija $GITHUB_PAT jednorazowo, a Claude Code zapisuje otrzymaną wartość w swojej konfiguracji, więc użyj tokenu ograniczonego do odczytu Actions.
codex mcp add github-actions \ --url https://api.githubcopilot.com/mcp/x/actions/readonly \ --bearer-token-env-var GITHUB_PATCodex czyta zmienną przy nawiązywaniu połączenia i nigdy nie zapisuje tokenu w config.toml.
W ~/.cursor/mcp.json, globalnym pliku użytkownika, którego nigdy się nie commituje:
{ "mcpServers": { "github-actions": { "url": "https://api.githubcopilot.com/mcp/x/actions/readonly", "headers": { "Authorization": "Bearer ${env:GITHUB_PAT}" } } }}To kształt z przewodnika GitHuba dla Cursora; interpolacja ${env:NAZWA} pochodzi z dokumentacji MCP Cursora cytowanej w naszym researchu i nie była testowana w binarce Cursora. Sprawdź w Settings > MCP, że github-actions pokazuje narzędzia, a pełną konfigurację znajdziesz w zakładce Cursor sekcji Zainstaluj serwer GitHub MCP.
Więcej o zestawach narzędzi serwera i trybie lockdown znajdziesz na stronie serwera GitHub MCP.
Pytanie „dlaczego w CI tak, a lokalnie nie” kieruje model ku przyczynom środowiskowym: kluczowi cache, który przywraca zależności zbudowane dla innej wersji Node, lockfile’owi rozjechanemu z package.json, brakującemu kontenerowi usługi albo tokenowi bez uprawnienia, którego potrzebuje krok. Punkt 4 to weryfikacja: poprawka jest skończona, gdy ten check zrobi się zielony, a nie gdy wyjaśnienie brzmi przekonująco.
Co się zmienia w GitLab CI i Jenkinsie?
Dział zatytułowany „Co się zmienia w GitLab CI i Jenkinsie?”Pętla „wygeneruj, potem przećwicz” jest ta sama; zmienia się tylko plik docelowy i składnia bramek. W promptach zamień .github/workflows/ci.yml na .gitlab-ci.yml albo deklaratywny Jenkinsfile i dopisz uwagi dla platformy:
- GitLab CI: poproś o utrzymywane przez GitLab szablony
include: - template: Jobs/SAST.gitlab-ci.ymliJobs/Container-Scanning.gitlab-ci.ymlzamiast ręcznie pisanych jobów skanera. Starsze ścieżkiSecurity/to już tylko przekierowania (Container Scanning przeniesiono w GitLab 15.6), a wygenerowane pipeline’y często wciąż je emitują. Przypinaj obrazy jobów do prawdziwego tagu, np.node:22-alpine, i kluczuj cache lockfile’em przezcache: key: files: [package-lock.json]. - Jenkins: poproś o deklaratywny
Jenkinsfilez agentami Docker i równoległymi (parallel) etapami jakości oraz etap SonarQube, który wywołujewithSonarQubeEnv, a po nimwaitForQualityGate abortPipeline: true. BezabortPipeline: truenieudany quality gate zostaje tylko zaraportowany, a pipeline jedzie dalej.
Jak dodać krok AI review do pull requestów zmieniających pipeline?
Dział zatytułowany „Jak dodać krok AI review do pull requestów zmieniających pipeline?”Recenzent AI przy zmianach pipeline’u łapie to, czego nie złapią checkery: zbyt szeroki warunek wdrożenia, uprawnienie poszerzone „tymczasowo”, skan przeniesiony za push. Jego głos jest doradczy. Bramkami pozostają wymagane checki i zatwierdzenie środowiska, a komentarz z review nigdy ich nie zastępuje.
Uruchom /install-github-app w claude, żeby zainstalować aplikację Claude GitHub i zapisać ANTHROPIC_API_KEY jako sekret repozytorium, a potem dodaj workflow review ograniczony do plików pipeline’u:
name: Claude pipeline reviewon: pull_request: types: [opened, synchronize] paths: ['.github/workflows/**', 'Dockerfile', '.gitlab-ci.yml', 'Jenkinsfile']permissions: contents: read pull-requests: write id-token: write # the action swaps an OIDC token for the Claude GitHub App tokenjobs: review: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 with: { persist-credentials: false, fetch-depth: 1 } - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: | REPO: ${{ github.repository }} PR NUMBER: ${{ github.event.pull_request.number }} Review only the CI/CD changes in this pull request. Flag: gates that can no longer fail, widened permissions, unpinned actions, event data used inside run: scripts, secrets exposed to pull request code, and deploy conditions broader than releases. Comment inline on the exact line. Do not suggest style changes. claude_args: '--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr diff:*),Bash(gh pr view:*)"'id-token: write jest wymagane przy domyślnym uwierzytelnianiu przez aplikację GitHub: bez niego akcja nie dostanie tokenu OIDC, który wymienia na token aplikacji, i job kończy się błędem, zanim cokolwiek zrecenzuje. Jeśli nie chcesz używać aplikacji, przekaż zamiast tego github_token: ${{ secrets.GITHUB_TOKEN }}, a komentarze będą wtedy pochodzić od github-actions[bot]. --allowedTools ogranicza recenzenta do czytania diffu i dodawania komentarzy inline. Przy pull requestach akcja przywraca .claude/, .mcp.json i CLAUDE.md z gałęzi bazowej, zanim wystartuje Claude, więc pull request nie podmieni własnych hooków ani serwerów MCP. Akcja konfiguruje własne poświadczenia gita przed tym pobraniem, więc persist-credentials: false w checkoucie nie psuje przywracania (kod źródłowy claude-code-action, sprawdzone 2026-09-26). To przywracanie chroni konfigurację agenta, nie sam workflow: przy pull_request GitHub uruchamia YAML z pull requesta, a filtr paths obejmuje .github/workflows/**, więc każdy, kto może wypchnąć gałąź do tego repozytorium, może poszerzyć --allowedTools we własnej kopii joba, a ta kopia uruchomi się z ANTHROPIC_API_KEY, zanim ktokolwiek ją przejrzy. CODEOWNERS na /.github/ z wymaganą recenzją blokuje scalenie takiej zmiany, a nie jej uruchomienie, więc prawo push dawaj tylko zaufanym osobom, a recenzję AI traktuj jako doradczą.
openai/codex-action@v1 instaluje Codex CLI i uruchamia codex exec. Uruchamiaj Codex w jobie, który może tylko czytać, a jego odpowiedź publikuj z drugiego joba, który ma uprawnienie do zapisu:
name: Codex pipeline reviewon: pull_request: types: [opened, synchronize, reopened] paths: ['.github/workflows/**', 'Dockerfile', '.gitlab-ci.yml', 'Jenkinsfile']jobs: codex: runs-on: ubuntu-latest permissions: contents: read outputs: final_message: ${{ steps.run_codex.outputs.final-message }} steps: - uses: actions/checkout@v7 with: ref: refs/pull/${{ github.event.pull_request.number }}/merge fetch-depth: 0 # base and head SHAs reachable for the diff persist-credentials: false - id: run_codex uses: openai/codex-action@v1 with: openai-api-key: ${{ secrets.OPENAI_API_KEY }} permission-profile: ':read-only' prompt: | Review only the CI/CD changes between ${{ github.event.pull_request.base.sha }} and ${{ github.event.pull_request.head.sha }}. Flag gates that can no longer fail, widened permissions, unpinned actions, event data used inside run: scripts, and deploy conditions broader than releases. Cite file and line for each finding. No style comments. post: needs: codex if: needs.codex.outputs.final_message != '' runs-on: ubuntu-latest permissions: pull-requests: write steps: - env: GH_TOKEN: ${{ github.token }} BODY: ${{ needs.codex.outputs.final_message }} PR_NUMBER: ${{ github.event.pull_request.number }} run: gh pr comment "$PR_NUMBER" --repo "$GITHUB_REPOSITORY" --body "$BODY"Zostaw domyślne safety-strategy: drop-sudo, które odbiera sudo przed uruchomieniem Codex. README akcji OpenAI zaleca w nowych workflow profil uprawnień zamiast starszego wejścia sandbox, a obu wejść nie da się połączyć. Zostaw model puste, żeby użyć domyślnego modelu Codex; aktualny opisuje przegląd modeli. Job codex czyta pliki samego pull requesta, w tym dodany przez niego AGENTS.md albo .codex/, mając dostęp do OPENAI_API_KEY, więc to :read-only i brak uprawnień do zapisu sprawiają, że wrogi pull request nic nie zepsuje: nigdy nie dawaj temu jobowi uprawnień ani narzędzi do zapisu. Tak jak w przypadku joba Claude Code, każdy, kto może wypchnąć gałąź, może zmienić ten workflow przed jego uruchomieniem, więc recenzja pozostaje doradcza.
Recenzentem pull requestów w Cursorze jest Bugbot, który po włączeniu dla repozytorium przegląda pull requesty pod kątem błędów, problemów bezpieczeństwa i jakości kodu (dokumentacja Cursora, sprawdzone 2026-08-28; konfiguracja na stronie Bugbot). Tę samą listę kontrolną co w prompcie dla Claude Code umieść w .cursor/BUGBOT.md, pliku reguł projektu, który czyta Bugbot: bramki, które już nie mogą zawieść, poszerzone uprawnienia, nieprzypięte akcje i szerokie warunki wdrożenia. Jeśli chcesz skryptowego kroku w samym workflow, Cursor dokumentuje uruchamianie swojego CLI w GitHub Actions (dokumentacja Cursora, sprawdzone 2026-08-28). Częsty podział pracy: piszesz pipeline w edytorze, a w CI recenzuje go Bugbot albo jedna z dwóch pozostałych akcji.
Kiedy wygenerowane pipeline’y CI/CD się psują
Dział zatytułowany „Kiedy wygenerowane pipeline’y CI/CD się psują”-
Cache się przywraca, a build i tak się psuje albo kompiluje wszystko od nowa. Klucz nie zawiera hasha lockfile’a albo wersji Node, więc
node_moduleszbudowane dla jednej wersji Node wraca pod inną. Użyjactions/setup-nodezcache: npm, które cache’uje pobrane paczki npm, a nienode_modules. Jeśli potrzebujeszactions/cache, kluczuj go przez${{ runner.os }}-node${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}. -
Push do GHCR pada z „repository name must be lowercase”.
${{ github.repository }}zachowuje wielkość liter nazwy właściciela. Zamień nazwę na małe litery we wcześniejszym kroku albo wpisz ją małymi literami, jak w szkielecie powyżej, i uruchom ponownie. -
Deploy przez OIDC pada z „Not authorized to perform sts:AssumeRoleWithWebIdentity”. YAML zwykle jest w porządku; to polityka zaufania w chmurze nie pasuje do tokenu. Job z
environment: productionwysyła subjectrepo:ORG/REPO:environment:production, a nie referencję gałęzi. Poproś agenta o wygenerowanie polityki zaufania z wyzwalacza i środowiska workflow, a potem porównaj jej waruneksubz claimem z nieudanego uruchomienia. -
Trivy wywraca build na CVE, które nie ma jeszcze poprawki. Nie usuwaj ani nie osłabiaj kroku skanowania; skan, który nie może zawieść, to powtórka incydentu z początku strony.
ignore-unfixed: truepomija podatności bez wersji z poprawką. Resztę dopisz do.trivyignorez datą wygaśnięcia, na przykładCVE-2026-12345 exp:2026-12-31, i komentarzem wskazującym recenzenta. Trivy zgłosi ją ponownie, gdy data minie. -
Agent przypina akcje do tagów,
@mainalbo do nieistniejących wersji. Agenci odtwarzają wersje z danych treningowych i zgadują SHA. Złośliwe wydania LiteLLM 1.82.7/1.82.8 na PyPI (2026-03-24) powiązano ze skompromitowanym krokiem Trivy w CI LiteLLM (doniesienia wtórne; zgłoszenie BerriAI/litellm#24518). Przypięcie przez SHA sprawia, że przesunięty albo przejęty tag nie zmieni tego, co uruchamia twój pipeline. Ponów prompt z „resolve every action to its full commit SHA withgit ls-remote, tag as a comment” i pozwól audytowiunpinned-useswzizmorto potwierdzić. -
Job AI review nigdy nie komentuje. Sprawdź po kolei trzy rzeczy: pull request przyszedł z forka (brak sekretów, celowo), filtr
pathswykluczył zmieniony plik albo job nie mapull-requests: write. Popraw filtr albo uprawnienie. Nie poszerzaj wyzwalacza.
Dokąd dalej z pipeline’ami CI/CD
Dział zatytułowany „Dokąd dalej z pipeline’ami CI/CD”Czy ten artykuł Ci pomógł?
Jedno kliknięcie, bez logowania.
Co z tym zrobisz?
Jak się czytało?
Co przeszkadzało? Możesz zaznaczyć kilka
Twoja rola?
Dzięki. Czytam każdą odpowiedź. Michał Jaskólski
Pomógł Ci ten artykuł?
Każde to jedno kliknięcie. Zamknij, kiedy chcesz.
bez logowania