Claude Code w CI/CD z GitHub Actions i trybem headless
Claude Code działa w CI/CD przez akcję GitHuba anthropics/claude-code-action@v1, a w każdym innym pipelinie przez tryb headless (claude -p). Akcja odpowiada na wzmianki @claude albo wykonuje stały prompt przy dowolnym zdarzeniu GitHuba, na przykład etykiecie lub nieudanym buildzie. Każdy przebieg ograniczają allowlista narzędzi, limit tur i te same wymagane testy, które przechodzi kod ludzi.
Twój zespół otwiera 30 pull requestów tygodniowo, każdy czeka pół dnia na pierwsze spojrzenie człowieka, a build pada dwa razy w tygodniu na zapomnianej regule lintera. Chcesz agenta w pipelinie, który nie „naprawi” builda usuniętym testem ani nie odda sekretu w cudzym pull requeście. Ta strona jest dla programisty, który konfiguruje workflowy, i dla tech leada, który decyduje, co wolno im robić.
Co daje działająca konfiguracja Claude Code w CI
Dział zatytułowany „Co daje działająca konfiguracja Claude Code w CI”- Workflow
@claude, który odpowiada na prośby w komentarzach do zgłoszeń i pull requestów - Automatyczne code review każdego pull requesta z komentarzami przy liniach, plus własny prompt nastawiony na bezpieczeństwo
- Zadanie zamieniające oznaczone etykietą zgłoszenie w pull request, z bramką specyfikacji przed startem
- Workflow auto-fix dla CI, który nie może usunąć ani pominąć testu i nigdy nie uruchamia kodu gałęzi obok twojego klucza API, bo osobny job bez sekretów ponownie uruchamia bramkę, zanim cokolwiek zostanie wypchnięte
- Przepis na headless
claude -pdla GitLaba, Jenkinsa lub dowolnego runnera, ze strukturalnym JSON-em, na którym skrypt może oprzeć decyzję - Konfiguracje dla Bedrocka, Google Cloud i Foundry, limity kosztów oraz awarie, których możesz się spodziewać w pierwszym tygodniu
Który punkt wejścia Claude Code do CI wybrać?
Dział zatytułowany „Który punkt wejścia Claude Code do CI wybrać?”| Chcesz | Użyj | Wynik trafia do |
|---|---|---|
| Doraźnych próśb od ludzi w zgłoszeniach i PR-ach | Akcji bez wejścia prompt (tryb interaktywny) | Komentarza, który Claude aktualizuje w trakcie |
| Stałego zadania na zdarzenie (nowy PR, etykieta, cron) | Akcji z wejściem prompt (tryb automatyzacji) | Logu przebiegu albo komentarza, jeśli prompt o to prosi |
| Code review każdego PR-a bez utrzymywania workflowu | Zarządzanego Code Review (Team i Enterprise, research preview) | Komentarzy przy liniach PR-a |
| Claude’a w GitLabie, Jenkinsie, Buildkite lub na maszynie z cronem | Headless claude -p w skrypcie | stdout, JSON-a, którego parsujesz |
| Cyklicznego zadania bez zdarzenia w repozytorium | Rutyn (Routines) | Sesji w chmurze |
Akcja sama wybiera tryb na podstawie konfiguracji: bez prompt czeka na frazę wyzwalającą (domyślnie @claude), z prompt startuje od razu. Sam YAML pipeline’u (cache, macierze, filtry ścieżek) opisuje konfiguracja pipeline za pomocą Claude Code. Ta strona dotyczy agenta działającego wewnątrz tego pipeline’u.
Zainstaluj aplikację Claude GitHub App i workflow @claude
Dział zatytułowany „Zainstaluj aplikację Claude GitHub App i workflow @claude”-
Uruchom instalator z lokalnej sesji. Zainstaluj GitHub CLI i wykonaj
gh auth login. Otwórzclaudew repozytorium i wpisz/install-github-app. Potrzebujesz uprawnień administratora repozytorium, a komenda działa tylko dla remote’ów na github.com. Instaluje aplikację Claude GitHub App i zapisuje sekret repozytorium:ANTHROPIC_API_KEYdla klucza API alboCLAUDE_CODE_OAUTH_TOKENdla tokenu subskrypcji (wygenerujesz go przezclaude setup-token). -
Scal pull request z workflowem, który otworzy instalator. Instalator wypycha gałąź z
claude.yml(i zclaude-code-review.yml, jeśli wybierzesz workflow code review) i otwiera GitHuba na gotowym pull requeście. Scalenie go włącza@claude. -
Albo dodaj workflow ręcznie. Ręczna konfiguracja jest potrzebna dla Bedrocka, Google Cloud i Foundry albo gdy chcesz panować nad plikiem. Zainstaluj Claude GitHub App, dodaj sekret i zacommituj ten plik:
.github/workflows/claude.yml name: Claude Codeon:issue_comment:types: [created]pull_request_review_comment:types: [created]jobs:claude:if: contains(github.event.comment.body, '@claude')runs-on: ubuntu-latesttimeout-minutes: 30permissions:contents: writepull-requests: writeissues: writeid-token: write # the action's GitHub App authenticationactions: read # lets Claude read CI results on the PRsteps:- uses: actions/checkout@v7with:fetch-depth: 1persist-credentials: false- uses: anthropics/claude-code-action@v1with:anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}claude_args: '--max-turns 30' -
Przetestuj. Skomentuj zgłoszenie:
@claude fix the TypeError in the dashboard component. Claude odpowiada komentarzem, aktualizuje go w trakcie pracy i commituje na nową gałąź. Nie otwiera pull requesta sam: jego komentarz linkuje do strony tworzenia PR-a na GitHubie, więc to człowiek decyduje, co zostanie zaproponowane.
Przy pull requeście akcja, zanim Claude ruszy, przywraca z gałęzi bazowej ścieżki konfiguracji samego Claude’a: .claude/, .mcp.json, .claude.json, CLAUDE.md, CLAUDE.local.md, .husky/ i kilka innych. Pull request nie wniesie więc własnych hooków ani serwerów MCP. Cała reszta zostaje w wersji z pull requesta, łącznie z package.json, więc hook z gałęzi bazowej, który wywołuje npm run format, uruchamia skrypt napisany w pull requeście. Wywołuj narzędzia bezpośrednio, z przypiętą wersją (docs/security.md akcji, odczyt 2026-09-26).
Które wejścia akcji istnieją, a które są po cichu ignorowane?
Dział zatytułowany „Które wejścia akcji istnieją, a które są po cichu ignorowane?”Najczęstsze wejścia to prompt, claude_args, anthropic_api_key lub claude_code_oauth_token, github_token, settings, plugins, plugin_marketplaces, trigger_phrase, track_progress, allowed_bots oraz use_bedrock, use_vertex lub use_foundry (pełna lista w action.yml). Wejść z czasów bety, czyli model, max_turns, timeout_minutes, direct_prompt i custom_instructions, w v1 nie ma (action.yml na gałęzi main, 2026-09-26): GitHub wypisuje ostrzeżenie „Unexpected input”, a przebieg idzie dalej na ustawieniach domyślnych. Opcje CLI przenieś do claude_args:
--model claude-sonnet-5przypina model. Bez tego akcja używa domyślnego modelu Claude Code, więc koszt przebiegu zmienia się razem ze zmianą domyślnego modelu. Zanim wybierzesz, zajrzyj do przeglądu modeli.--max-turns 10kończy przebieg błędem, gdy Claude dojdzie do limitu.--allowedTools "..."przyznaje narzędzia. W trybie automatyzacji Claude nie ma powłoki ani dostępu do API GitHuba poza tym, co mu przyznasz.--append-system-prompt "..."zastępuje dawnecustom_instructions.
Zegar zadania to GitHubowe timeout-minutes: na poziomie joba, a nie wejście akcji.
Jeśli nie chcesz przechowywać żadnego długowiecznego poświadczenia Claude’a, akcja może wymienić token OIDC workflowu GitHuba na dostęp do API przez konto serwisowe w Claude Console. Ustaw anthropic_federation_rule_id i anthropic_organization_id (plus anthropic_service_account_id albo anthropic_workspace_id, gdy reguła ich wymaga) i zostaw id-token: write. Jeśli jeden sekret ma obsługiwać całą organizację, niech to będzie klucz API z Console: CLAUDE_CODE_OAUTH_TOKEN jest związany z subskrypcją osoby, która uruchomiła claude setup-token.
Code review każdego pull requesta z Claude Code
Dział zatytułowany „Code review każdego pull requesta z Claude Code”Workflow code review z szybkiej instalacji uruchamia plugin code-review z marketplace’u claude-code Anthropic. Oto ten sam workflow rozpisany, żebyś panował nad wyzwalaczami, modelem i uprawnieniami:
name: Code Reviewon: pull_request: types: [opened, synchronize, ready_for_review, reopened]jobs: review: if: github.event.pull_request.draft == false runs-on: ubuntu-latest timeout-minutes: 20 concurrency: group: claude-review-${{ github.event.pull_request.number }} cancel-in-progress: true permissions: contents: read pull-requests: read issues: read id-token: write steps: - uses: actions/checkout@v7 with: fetch-depth: 1 persist-credentials: false - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} plugin_marketplaces: 'https://github.com/anthropics/claude-code.git' plugins: 'code-review@claude-code-plugins' prompt: '/code-review:code-review --comment ${{ github.repository }}/pull/${{ github.event.pull_request.number }}' claude_args: '--allowedTools "mcp__github_inline_comment__create_inline_comment"'Dwie linie decydują, czy ktokolwiek zobaczy code review. --comment sprawia, że Claude publikuje komentarze przy liniach albo jeden komentarz podsumowujący, gdy nic nie znajdzie; bez tej flagi wyniki zostają w logu przebiegu. Akcja uruchamia serwer MCP do komentarzy przy liniach tylko wtedy, gdy przyznaje go --allowedTools. W publicznych repozytoriach GitHub nie udostępnia sekretów pull requestom z forków, więc to zadanie obejmuje tylko gałęzie z tego samego repozytorium.
Żeby code review trzymało się reguł zespołu, zapisz je w CLAUDE.md albo w skillu w .claude/skills/ i wywołaj go jako prompt (/security-pass). Krok checkout musi wykonać się wcześniej, żeby pliki skilla były na runnerze. Własne komendy slash są teraz skillami; zobacz własne komendy.
Wstaw go jako prompt: w workflowie powyżej zamiast wywołania pluginu i dopisz do --allowedTools narzędzia Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr comment:*), żeby Claude mógł przeczytać diff i opublikować komentarz podsumowujący. Linia z confirmed: true w prompcie też ma znaczenie: narzędzie akcji do komentarzy przy liniach wstrzymuje niepotwierdzone komentarze i klasyfikuje je po zakończeniu sesji, więc bez niej komentarze mogą się opóźnić albo zostać odfiltrowane. Etykiety ważności mają znaczenie: code review, które zgłasza wszystko z tą samą głośnością, w drugim tygodniu przestaje być czytane, a „nic HIGH, sprawdziłem to i to” samo w sobie jest dowodem, z którego może skorzystać recenzent.
Traktuj to code review jako jeden z czujników, a nie jako zatwierdzenie. Co człowiek czyta zamiast całego diffu, opisuje code review PR-a agenta bez czytania każdej linii. Lokalne code review przed pushem opisuje automatyzacja code review.
Zamień oznaczone zgłoszenie w pull request
Dział zatytułowany „Zamień oznaczone zgłoszenie w pull request”Etykieta jest bramką specyfikacji: nic nie rusza, dopóki człowiek nie uzna, że zgłoszenie ma kryteria akceptacji, które agent może spełnić.
name: Issue to PRon: issues: types: [labeled]permissions: {}jobs: implement: # Holds the API key and a read-only token. Claude edits and tests; it cannot push. if: >- github.event.label.name == 'claude-implement' && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.issue.author_association) runs-on: ubuntu-latest timeout-minutes: 45 permissions: contents: read issues: read steps: - uses: actions/checkout@v7 with: persist-credentials: false - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} github_token: ${{ github.token }} # scoped to this job's read-only permissions prompt: | Implement issue #${{ github.event.issue.number }} in ${{ github.repository }}. Read it with `gh issue view ${{ github.event.issue.number }}` and ignore its comments. Follow the instructions in .github/claude/implement.md. Write the pull request body to ${{ runner.temp }}/pr-body.md. claude_args: >- --max-turns 40 --add-dir ${{ runner.temp }} --allowedTools "Read,Edit,Write,Glob,Grep,Bash(gh issue view:*),Bash(npm ci),Bash(npm test:*),Bash(npm run lint:*),Bash(npm run typecheck:*)" - name: Export Claude's change as a patch run: | git add -A && git diff --cached --binary > "$RUNNER_TEMP/change.patch" [ -s "$RUNNER_TEMP/pr-body.md" ] || echo "Claude wrote no PR body." > "$RUNNER_TEMP/pr-body.md" - uses: actions/upload-artifact@v7 with: name: claude-implement path: | ${{ runner.temp }}/change.patch ${{ runner.temp }}/pr-body.md
open-pr: # Holds the write token, never sees the API key, runs nothing Claude wrote. needs: implement runs-on: ubuntu-latest timeout-minutes: 10 permissions: contents: write pull-requests: write issues: write steps: - uses: actions/checkout@v7 with: persist-credentials: false - uses: actions/download-artifact@v8 with: name: claude-implement path: ${{ runner.temp }} - name: Push claude/issue-N and open a PR, or post Claude's questions env: GH_TOKEN: ${{ github.token }} ISSUE: ${{ github.event.issue.number }} run: | if [ ! -s "$RUNNER_TEMP/change.patch" ]; then gh issue comment "$ISSUE" --body-file "$RUNNER_TEMP/pr-body.md"; exit 0; fi BR="claude/issue-$ISSUE" git apply --index "$RUNNER_TEMP/change.patch" if git diff --cached --name-only | grep '^\.github/'; then echo "Refusing: the change touches .github/"; exit 1; fi git config user.name "claude[bot]" git config user.email "claude[bot]@users.noreply.github.com" git switch -c "$BR" git commit -m "Implement #$ISSUE" git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "HEAD:refs/heads/$BR" gh pr create --head "$BR" --title "Implement #$ISSUE" --body-file "$RUNNER_TEMP/pr-body.md"Prompt przekazuje numer zgłoszenia, a nie ${{ github.event.issue.body }}. Wklejenie treści sprawia, że tekst autora zgłoszenia staje się częścią twoich instrukcji; przekazanie numeru zostawia instrukcje po twojej stronie, a zgłoszenie jako dane, które Claude czyta. To zmniejsza ryzyko prompt injection, ale go nie usuwa, dlatego workflow otacza je czterema kontrolami:
- Kto napisał tekst i kto nadał etykietę. Etykietę może nadać także osoba z rolą Triage, ale
claude-code-actionodmawia startu każdemu aktorowi bez prawa zapisu lub administratora, chyba że ustawiszallowed_non_write_users, więc przebieg uruchomi tylko nadający etykietę z prawem zapisu. Tę bramkę daje sama akcja (checkWritePermissions, sprawdzone namainw commicie 97c5347, 2026-10-01): zamień akcję na zwykły krokclaude -p, a ją stracisz. Warunek naauthor_associationpomija zgłoszenia, których autorem nie jest właściciel, członek organizacji ani współpracownik, przy czymCOLLABORATORobejmuje też współpracowników z prawem odczytu i rolą Triage. Claude czyta zgłoszenie bez komentarzy, bo komentarz może dopisać każdy, także już po nadaniu etykiety. - Claude nie dostaje gita. Wpis w rodzaju
Bash(git:*)to dowolna powłoka:git -c alias.x='!sh -c …' xuruchamia dowolną komendę, a sama akcja dostarcza własny wrapperscripts/git-push.shwłaśnie dlatego, żegit push --receive-pack=…robi to samo. Tutaj Claude nie ma gita, a jego token ma tylkocontents: read. - Token z prawem zapisu żyje w osobnym jobie.
open-prnigdy nie widzi klucza API i nie uruchamia niczego, co napisał Claude: nakłada patch, odrzuca każdą zmianę w.github/, wypychaclaude/issue-<numer>i otwiera pull request, a gdy zmiany nie ma, publikuje pytania Claude’a w zgłoszeniu. - Każdy checkout ma
persist-credentials: false, więc żaden krok nie zostawia tokenu w.git/configdla kolejnego.
npm test to nadal wykonywanie kodu obok klucza API, bo testy, które Claude uruchamia, sam pisze. Tutaj jest to do przyjęcia tylko dlatego, że zaufany jest zarówno kod (gałąź domyślna), jak i instrukcje (zgłoszenie od zaufanego autora). Przy zgłoszeniach od zewnętrznych kontrybutorów użyj kształtu workflowu naprawy CI opisanego niżej: Claude dostaje tylko narzędzia plikowe, a bramkę uruchamia job bez sekretów. Pull request otwarty GITHUB_TOKEN-em workflowu nie uruchamia innych workflowów, więc jeśli CI ma na nim ruszyć, użyj w open-pr tokenu GitHub App.
To ryzyko nie jest teoretyczne. W łańcuchu, który badacz bezpieczeństwa Adnan Khan nazwał „Clinejection”, jak streścił go Simon Willison 2026-03-06 (relacja z drugiej ręki), prompt wstrzyknięty przez tytuł zgłoszenia do workflowu AI do triażu, zbudowanego na claude-code-action z narzędziami Bash, Write i Edit, doprowadził do zatrucia cache GitHub Actions i kradzieży tokenów publikacji.
Pull request otwarty w ten sposób niesie własne dowody: kryteria przypisane do testów, uruchomione komendy, otwarte pytania. Taki kształt definiuje pakiet dowodów i to on pozwala recenzentowi zatwierdzić zmianę na podstawie dowodów, a nie czytania linia po linii.
Napraw nieudany przebieg CI bez osłabiania testów
Dział zatytułowany „Napraw nieudany przebieg CI bez osłabiania testów”Niebezpieczna wersja tego zadania robi checkout padającej gałęzi, daje Claude’owi klucz API i powłokę, a potem wypycha to, co wyprodukuje. Prędzej czy później usuwa niestabilny test, który się sypał. Do tego skrypty z package.json, pliki testów i konfigurację builda z tej gałęzi uruchamia w tym samym jobie co twój sekret, więc każdy, kto może wypchnąć gałąź, może odczytać klucz.
Wersja poniżej dzieli pracę na trzy joby o różnych uprawnieniach:
| Job | Ma dostęp do | Uruchamia kod gałęzi? | Co robi |
|---|---|---|---|
patch | Klucz API, token tylko do odczytu | Nie | Claude czyta logi i edytuje kopię commita |
verify | Niczego: bez sekretów, token tylko do odczytu | Tak | Nakłada łatkę, odrzuca osłabione testy, ponownie uruchamia bramkę |
open-pr | Token z prawem zapisu | Nie | Commituje zweryfikowaną łatkę na nową gałąź i otwiera PR |
name: Claude fixes CIon: workflow_run: workflows: ['CI'] types: [completed]permissions: {}jobs: patch: # Holds the API key. Reads and edits the failing commit, never executes it. if: >- github.event.workflow_run.conclusion == 'failure' && github.event.workflow_run.pull_requests[0] && !startsWith(github.event.workflow_run.head_branch, 'claude-fix/') runs-on: ubuntu-latest timeout-minutes: 20 permissions: contents: read actions: read id-token: write steps: - uses: actions/checkout@v7 # trusted default branch at the workspace root with: persist-credentials: false - uses: actions/checkout@v7 # the failing commit, in a subdirectory with: ref: ${{ github.event.workflow_run.head_sha }} path: pr-head persist-credentials: false - name: Save the failing jobs' logs env: GH_TOKEN: ${{ github.token }} RUN_ID: ${{ github.event.workflow_run.id }} run: gh run view "$RUN_ID" --repo "$GITHUB_REPOSITORY" --log-failed | tail -c 60000 > "$RUNNER_TEMP/ci-failure.log" - uses: anthropics/claude-code-action@v1 with: anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} prompt: | CI failed on the commit checked out in pr-head/. The failing jobs' logs are in ${{ runner.temp }}/ci-failure.log. Edit files under pr-head/ only. Follow the CI-fix rules in .github/claude/fix-ci.md. claude_args: >- --max-turns 25 --add-dir pr-head ${{ runner.temp }} --allowedTools "Read,Edit,Write,Glob,Grep" - name: Export Claude's change as a patch run: git -C pr-head add -A && git -C pr-head diff --cached --binary > fix.patch - uses: actions/upload-artifact@v7 with: name: claude-fix path: fix.patch
verify: # Executes the branch's code, so it gets no secrets and a read-only token. needs: patch runs-on: ubuntu-latest timeout-minutes: 20 permissions: contents: read steps: - uses: actions/checkout@v7 with: ref: ${{ github.event.workflow_run.head_sha }} persist-credentials: false - uses: actions/download-artifact@v8 with: name: claude-fix path: ${{ runner.temp }} - name: Apply the patch and re-run the gate outside Claude run: | [ -s "$RUNNER_TEMP/fix.patch" ] || { echo "Claude changed nothing"; exit 1; } git apply --index "$RUNNER_TEMP/fix.patch" if git diff --cached --name-only --diff-filter=D | grep -E '\.(test|spec)\.'; then echo "Refusing: a test file was deleted"; exit 1; fi if git diff --cached -U0 | grep -E '^\+.*\.(skip|only)\(|^\+.*\bxit\('; then echo "Refusing: a test was skipped or focused"; exit 1; fi if git diff --cached --name-only | grep -E '^\.github/|(^|/)package(-lock)?\.json$|(jest|vitest|playwright|karma)\.config\.'; then echo "Refusing: the patch edits CI, package scripts or test config"; exit 1; fi npm ci && npm run lint && npm run typecheck && npm test
open-pr: # Can write to the repository, but runs no code from the branch. needs: verify runs-on: ubuntu-latest timeout-minutes: 10 permissions: contents: write pull-requests: write steps: - uses: actions/checkout@v7 with: ref: ${{ github.event.workflow_run.head_sha }} persist-credentials: false - uses: actions/download-artifact@v8 with: name: claude-fix path: ${{ runner.temp }} - name: Push to a fix branch and open a PR env: GH_TOKEN: ${{ github.token }} HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} RUN_ID: ${{ github.run_id }} run: | SAFE=$(printf '%s' "$HEAD_BRANCH" | tr -cd 'a-zA-Z0-9/_.-') BR="claude-fix/$SAFE-$RUN_ID" git apply --index "$RUNNER_TEMP/fix.patch" git config user.name "claude[bot]" git config user.email "claude[bot]@users.noreply.github.com" git switch -c "$BR" git commit -m "fix: repair CI failure from run $RUN_ID" git push "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" "HEAD:refs/heads/$BR" gh pr create --head "$BR" --base "$HEAD_BRANCH" --fillBezpieczeństwo opiera się na czterech decyzjach. Claude dostaje narzędzia plikowe i żadnej powłoki, więc kod gałęzi nigdy nie działa obok klucza. Ten kod działa tylko w verify, który nie ma żadnego sekretu i odrzuca patch dotykający .github/, package.json albo konfiguracji testów, więc Claude nie przepisze bramki, która go sprawdza. Sprawdzenie prefiksu claude-fix/ nie pozwala workflowowi wyzwalać samego siebie. A pull request celuje w gałąź programisty, więc to autor przyjmuje albo odrzuca poprawkę.
verify nie jest jednak piaskownicą. Job wyzwolony przez workflow_run działa w kontekście gałęzi domyślnej i dzieli z nią zakres cache GitHub Actions, więc niezaufany kod może tam zatruć cache bez żadnego sekretu, a to jest właśnie wektor Clinejection opisany wyżej. Nie używaj actions/cache ani cache w setup-node w verify i nigdy nie przywracaj cache w workflowach wydania i publikacji.
Ceną jest to, że Claude nie uruchomi testów, więc nieudany verify oznacza brak pull requesta, a nie ponowną próbę; artefakt claude-fix przechowuje łatkę i diagnozę. Pull request otwarty tokenem GITHUB_TOKEN workflowu nie wyzwala innych workflowów; verify już uruchomił bramkę, a token aplikacji GitHub (actions/create-github-app-token) w open-pr sprawi, że CI ruszy także na nim.
Plik z promptem leży na gałęzi domyślnej, więc pull request nie przepisze reguł, których Claude przestrzega. CLAUDE_FIX_NOTES.md trafia do commita dla recenzenta; przed scaleniem usuń go albo przenieś jego treść do opisu PR-a.
Uruchom Claude Code headless w GitLabie, Jenkinsie lub dowolnym runnerze
Dział zatytułowany „Uruchom Claude Code headless w GitLabie, Jenkinsie lub dowolnym runnerze”Poza GitHub Actions wywołuj CLI bezpośrednio. W CI nie ładuj niczego z checkoutu. --bare pomija hooki, synchronizację pluginów, auto memory, LSP i automatyczne wyszukiwanie CLAUDE.md. --setting-sources "" pomija pliki ustawień użytkownika, projektu i lokalne. --strict-mcp-config ignoruje każdy serwer MCP, którego nie przekazałeś przez --mcp-config. Tryb bare uwierzytelnia się wyłącznie przez ANTHROPIC_API_KEY, apiKeyHelper przekazany przez --settings albo poświadczenia dostawcy chmury, nigdy logowaniem z subskrypcji ani przez pęk kluczy (wszystko sprawdzone w claude --help, 2.1.283).
# In the CI job; ANTHROPIC_API_KEY comes from the CI secret store.CI_TMP=$(mktemp -d)git diff "origin/$TARGET_BRANCH...HEAD" > "$CI_TMP/change.diff"
claude --bare -p "Classify the risk of the change in $CI_TMP/change.diff for release. Read the files it touches. Answer in the schema." \ --setting-sources "" --strict-mcp-config \ --add-dir "$CI_TMP" \ --allowedTools "Read,Grep,Glob" \ --permission-mode dontAsk \ --max-turns 15 --max-budget-usd 3 \ --output-format json \ --json-schema '{"type":"object","properties":{"risk":{"enum":["low","medium","high"]},"reasons":{"type":"array","items":{"type":"string"}}},"required":["risk","reasons"]}' \ > risk.json
jq -e '.is_error == false and (.structured_output.risk == "low" or .structured_output.risk == "medium")' risk.json || { jq '.structured_output.reasons // .result' risk.json; exit 1; }--permission-mode dontAsk odrzuca wszystko spoza allowlisty, zamiast czekać na pytanie, na które nikt nie odpowie. --max-budget-usd zatrzymuje przebieg na limicie w dolarach i działa tylko z -p. --json-schema umieszcza zwalidowany obiekt w polu structured_output, więc pipeline rozgałęzia się na wartości, a nie na wolnym tekście. Przebieg, który kończy się błędem, wyczerpuje budżet albo limit tur, nie ma structured_output, więc bramka musi traktować brak werdyktu jako porażkę; dlatego linia jq sprawdza is_error i przepuszcza tylko dwie znane bezpieczne wartości. --max-turns nie pojawia się w wyjściu claude --help, ale jest opisane w dokumentacji CLI i działa z -p (sprawdzone na 2.1.283). W zadaniu, które ma wyłącznie czytać, --restricted dodatkowo usuwa Bash i pozostałe narzędzia uruchamiające kod oraz ogranicza narzędzia plikowe do katalogów roboczych i --add-dir.
Dla GitLaba istnieje też utrzymywana przez GitLab integracja Claude Code z GitLab CI/CD, w wersji beta. Do sterowania programowego wykraczającego poza wywołanie z powłoki użyj Claude Agent SDK. Dłuższe, wieloetapowe skrypty opisuje automatyzacja z Claude Code.
Uruchom akcję na Bedrocku, Google Cloud lub Foundry
Dział zatytułowany „Uruchom akcję na Bedrocku, Google Cloud lub Foundry”Z dostawcą chmury akcja uwierzytelnia się przez federację OIDC, więc repozytorium nie przechowuje statycznych poświadczeń chmurowych. Ustaw jedno wejście (use_bedrock, use_vertex albo use_foundry), nadaj id-token: write i dodaj krok logowania do dostawcy przed akcją.
permissions: contents: write pull-requests: write issues: write id-token: write steps: - uses: actions/checkout@v7 with: persist-credentials: false - uses: aws-actions/configure-aws-credentials@v6 with: role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} aws-region: us-west-2 # exported as AWS_REGION for the rest of the job - uses: anthropics/claude-code-action@v1 with: use_bedrock: 'true' claude_args: '--model us.anthropic.claude-opus-5-5 --max-turns 10'Użyj ID profilu inferencji, które konsola Bedrocka pokazuje dla grupy regionów, w której nadałeś dostęp do modelu, na przykład us. plus ID modelu w Bedrocku anthropic.claude-opus-5-5. Rola IAM potrzebuje zawężonej polityki wywołań od Anthropic, która obejmuje bedrock:InvokeModel.
permissions: contents: write pull-requests: write issues: write id-token: write steps: - uses: actions/checkout@v7 with: persist-credentials: false - id: auth uses: google-github-actions/auth@v3 with: workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }} service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }} - uses: anthropics/claude-code-action@v1 with: use_vertex: 'true' claude_args: '--model claude-sonnet-5 --max-turns 10' env: ANTHROPIC_VERTEX_PROJECT_ID: ${{ steps.auth.outputs.project_id }} CLOUD_ML_REGION: us-east5Wejście nadal nazywa się use_vertex, a region i projekt pochodzą ze zmiennych środowiskowych CLOUD_ML_REGION i ANTHROPIC_VERTEX_PROJECT_ID, nie z wejść akcji.
permissions: contents: write pull-requests: write issues: write id-token: write steps: - uses: actions/checkout@v7 with: persist-credentials: false - uses: azure/login@v3 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - uses: anthropics/claude-code-action@v1 with: use_foundry: 'true' claude_args: '--model claude-sonnet-5 --max-turns 10' env: ANTHROPIC_FOUNDRY_RESOURCE: your-foundry-resourceUżyj ID modelu, który odpowiada wdrożeniu Claude’a w twoim zasobie Foundry.
W publicznym repozytorium każdy komentarz z frazą wyzwalającą uruchamia te zadania, a logowanie do chmury wykonuje się, zanim akcja sprawdzi prawo zapisu komentującego. Dodaj pierwszy krok, który sprawdza uprawnienia komentującego przez gh api i kończy zadanie wcześniej. Pełną konfigurację dostawców, łącznie z własną aplikacją GitHub z uprawnieniami tylko do Contents, Issues i Pull requests, opisuje przewodnik Anthropic po dostawcach chmury oraz nasza strona o integracji korporacyjnej.
Utrzymaj koszty Claude Code w CI w ryzach
Dział zatytułowany „Utrzymaj koszty Claude Code w CI w ryzach”Każdy przebieg zużywa minuty GitHub Actions i tokeny modelu; CLAUDE_CODE_OAUTH_TOKEN obciąża subskrypcję zamiast API. Większość pracy wykonuje pięć mechanizmów:
- Nie uruchamiaj wcale dla draftów, zmian wyłącznie w dokumentacji i PR-ów od botów:
if: github.event.pull_request.draft == falseplus filtrpaths:w wyzwalaczu. - Przypnij model w
claude_args, żeby zmiana domyślnego modelu nie zmieniała rachunku. Ceny są w przeglądzie modeli. - Ogranicz pracę:
--max-turnsw akcji,--max-turnsi--max-budget-usdw przebiegach headless. - Ogranicz czas przez
timeout-minutes:joba. - Anuluj nieaktualne przebiegi grupą
concurrency:na pull request, jak w workflowie code review powyżej.
Zarządzane Code Review jest rozliczane osobno: dokumentacja Anthropic podaje, że każde review „averages $15-25” i rośnie z rozmiarem PR-a (dokumentacja Code Review, sprawdzone 2026-09-26). Wydatki CI śledź obok użycia interaktywnego według strony kontrola kosztów Claude Code.
Skąd wiesz, że automatyczny wynik jest poprawny?
Dział zatytułowany „Skąd wiesz, że automatyczny wynik jest poprawny?”Dowód pochodzi z bramek, których Claude nie może edytować:
- Wymagane status checki. Ochrona gałęzi wymaga na PR-ach Claude’a tych samych testów, sprawdzania typów i lintera co na PR-ach wszystkich innych. Workflow auto-fix uruchamia je ponownie w jobie, którego Claude nie dotyka.
- Chronione testy. Reguła CODEOWNERS na katalogach testów i konfiguracji CI sprawia, że zmiana wyroczni wymaga zatwierdzenia przez wskazaną osobę. Workflow auto-fix przed pushem odrzuca usunięte, pominięte i zawężone (
.only) testy. - Dowody w opisie PR-a. Kryteria akceptacji przypisane do testów, uruchomione komendy i otwarte pytania, zgodnie z pakietem dowodów.
- Strukturalne werdykty. Zadania headless zwracają wynik
--json-schema, a pipeline pada na wartości, a nie na tym, że człowiek przeczyta prozę. - Człowiek zatwierdzający dla każdej klasy ryzyka. Komentarze Claude’a to dane wejściowe. Decyzja o scaleniu zostaje przy osobie wskazanej w CODEOWNERS, a przy ścieżkach wysokiego ryzyka ta osoba czyta wybrane punkty zapalne opisane w code review PR-a agenta.
Kolejność wdrażania dla tech leada: najpierw workflow code review (tylko odczyt, niskie ryzyko), potem @claude, potem zgłoszenie w PR za etykietą, a auto-fix dopiero wtedy, gdy job verify i CODEOWNERS na testach są na miejscu.
Kiedy Claude Code w GitHub Actions zawodzi
Dział zatytułowany „Kiedy Claude Code w GitHub Actions zawodzi”Claude nie odpowiada na @claude. Sprawdź, czy aplikacja Claude GitHub App jest zainstalowana w tym repozytorium, czy Actions są włączone, czy nazwa sekretu zgadza się z workflowem, czy komentarz zawiera @claude jako całe słowo i czy komentujący ma prawo zapisu. Log przebiegu pokazuje, która kontrola odrzuciła zdarzenie.
CI nie rusza na commitach Claude’a. GitHub nie wyzwala workflowów na pushach wykonanych domyślnym GITHUB_TOKEN. Usuń github_token: ${{ secrets.GITHUB_TOKEN }} z akcji, żeby uwierzytelniała się jako Claude GitHub App, albo przekaż token własnej aplikacji GitHub.
Code review się wykonuje, ale nic nie publikuje. Prompt nie ma --comment albo claude_args nie dopuszcza mcp__github_inline_comment__create_inline_comment. Plugin code-review pomija też drafty, zamknięte pull requesty i te, które Claude już skomentował.
Workflow ignoruje twój model albo limit tur. Ustawiłeś model: lub max_turns: jako wejścia akcji. Poszukaj w przebiegu adnotacji z ostrzeżeniem „Unexpected input” i przenieś wartości do claude_args.
Zadanie z harmonogramu nie przechodzi kontroli aktora. GitHub przypisuje przebiegi z harmonogramu użytkownikowi, który ostatnio zmienił linię cron. Jeśli to bot, dodaj go do allowed_bots. W publicznych repozytoriach GitHub wyłącza też harmonogram po 60 dniach bez aktywności.
Zadanie kończy się błędem max-turns. Zadanie jest za duże na jeden przebieg. Podziel je (jedno zgłoszenie na przebieg, jeden padający job na naprawę), zanim podniesiesz limit.
Workflow auto-fix nigdy nie otwiera pull requesta. verify padł albo Claude zatrzymał się zgodnie z regułami i zapisał tylko diagnozę. Przeczytaj CLAUDE_FIX_NOTES.md z artefaktu claude-fix i dokończ ręcznie. Jeśli verify pada w większości przebiegów, zostaw te awarie człowiekowi, zamiast dawać powłokę jobowi, który ma klucz.
open-pr pada z komunikatem „GitHub Actions is not permitted to create or approve pull requests”. Gałąź z poprawką jest już wypchnięta, ale repozytorium lub organizacja nie pozwala tokenowi GITHUB_TOKEN workflowu otwierać pull requestów. Włącz „Allow GitHub Actions to create and approve pull requests” w Settings → Actions → General albo użyj tokenu aplikacji GitHub w open-pr.
Auto-fix otwiera pull request, który osłabia test. Wzorce w verify tego nie wyłapały, na przykład obniżonego progu pokrycia. Zamknij PR, dopisz ten wzorzec do verify i obejmij plik konfiguracji regułą CODEOWNERS.
Job wydania lub publikacji uruchamia kod, którego nikt nie scalił. Job wykonujący kod gałęzi, na przykład verify, zapisał coś do cache Actions gałęzi domyślnej, a późniejszy zaufany workflow ten cache przywrócił. Usuń cache ze wszystkich jobów uruchamiających niezaufany kod, przestań przywracać cache w workflowach wydania i publikacji i wyczyść cache repozytorium w Actions → Caches.
Bedrock lub Google Cloud zwraca 401 albo 403. Polityka zaufania OIDC nie pasuje do tego repozytorium lub gałęzi, rola nie ma uprawnienia do wywołania modelu albo brakuje dostępu do modelu w jednym z regionów profilu inferencji.
Co dalej z Claude Code w CI
Dział zatytułowany „Co dalej z Claude Code w CI”- Automatyzacja pipeline’u z AI: przekrojowe spojrzenie na agentów w pipelinie dostarczania, niezależne od narzędzia
- Konfiguracja pipeline za pomocą Claude Code: wygeneruj i przyspiesz pipeline, w którym działają te zadania
- Code review PR-a agenta bez czytania każdej linii: co człowiek czyta po code review Claude’a
- Pakiet dowodów: kontrakt PR-a, który wypełnia prompt „zgłoszenie w PR”
- Uprawnienia i sandboxing: allowlisty narzędzi i piaskownice (sandboksy) dla agentów działających bez nadzoru
- Hooki i automatyzacja: egzekwuj te same reguły lokalnie, zanim kod dotrze do CI
- Agenci bez interfejsu w CI:
claude -p,codex execi Agent SDK porównane jako klocki pipeline’u - Te same zadania w innych narzędziach: Codex w CI/CD i Cursor w CI/CD