Amazon Bedrock + GitHub Actions でClaude Codeを本格運用。複数リポジトリ対応の共通化も解説
フィッツプラスシステム開発部の高山です。
話題のClaude Codeを、GitHub Actions上で直接活用できる環境を構築しました。フィッツプラスではすでにAmazon BedrockでClaudeをAPI利用できる体制が整っているため、これを活かしたセットアップに挑戦してみました。
複数のリポジトリから共通のワークフローを呼び出せるようにする方法も含めて、手順をまとめています。同じようにAmazon Bedrockで課金を統一しつつ、GitHub ActionsでClaude Codeを使いたい方の参考になれば嬉しいです。
セットアップ手順
1. Bedrockでモデルを有効化
もしまだモデルの環境が整っていなければ、AWSコンソールからClaude Codeで使用するモデルを有効にします。モデルを選んでリクエストするだけなので簡単です。今回はClaude Sonnet 4を使う前提で設定を書いていますが、お好きなものをお使いください。ちなみにフィッツプラスではus-east-1
で動かしています。
2. IAMロールの作成
GitHub ActionsからBedrockのAPIを呼び出すため、OIDC(OpenID Connect)を利用してGitHubリポジトリとAWSアカウントを安全に連携させるIAMロールを作成します。
権限ポリシー:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": "*"
}
]
}
信頼ポリシー:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::xxxxxxxxxxxx:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com"
},
"StringLike": {
"token.actions.githubusercontent.com:sub": "repo:armg/*:*"
}
}
}
]
}
xxxxxxxxxxxx
はご自身のAWSアカウントID、armg/*
は対象とするOrganization/リポジトリ名に適宜変更してください。
フィッツプラスではTerraformを使ってIAMロールを作成しています。以下のコードスニペットは、上記の設定をTerraformで実装したものです。
resource "aws_iam_role" "claude" {
name = "claude-action"
assume_role_policy = data.aws_iam_policy_document.assume_claude.json
}
data "aws_iam_policy_document" "assume_claude" {
statement {
actions = ["sts:AssumeRoleWithWebIdentity"]
principals {
type = "Federated"
identifiers = [aws_iam_openid_connect_provider.github.arn]
}
condition {
test = "StringEquals"
variable = "token.actions.githubusercontent.com:aud"
values = [
"sts.amazonaws.com",
]
}
condition {
test = "StringLike"
variable = "token.actions.githubusercontent.com:sub"
values = [
"repo:armg/*:*",
]
}
}
}
resource "aws_iam_policy" "claude" {
name = "claude-action"
path = "/"
policy = data.aws_iam_policy_document.claude.json
}
resource "aws_iam_role_policy_attachment" "claude" {
role = aws_iam_role.claude.name
policy_arn = aws_iam_policy.claude.arn
}
# tfsec:ignore:aws-iam-no-policy-wildcards
data "aws_iam_policy_document" "claude" {
statement {
effect = "Allow"
actions = [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream",
]
resources = ["*"]
}
}
3. カスタムGitHub Appの作成
Anthropic公式のAppもありますが、組織内の権限をより細かく管理するため、カスタムGitHub Appを作成します。これはAnthropic自身も推奨している方法で、企業利用におけるセキュリティ統制の観点からも重要だと考えて設定しました。
主要な設定項目:
-
GitHub App name:
armg-claude-bot
など、お好きな名前 -
Webhook:
Active
のチェックを外す
Repository permissions:
- Contents: Read & Write
- Issues: Read & Write
- Pull requests: Read & Write
- Workflows: Read & write
作成後、「generate a private key」をクリックして秘密鍵を生成・ダウンロードしておきます。この秘密鍵はあとでGitHub ActionsのSecretsに登録するのに使います。
ちなみにGitHub App nameは、Issueのコメントやコミット履歴の名前として出現します。
4. GitHub Appのインストールと設定
作成したGitHub Appを対象のリポジトリまたはOrganization全体にインストールします。
その後、GitHubリポジトリの Settings > Secrets and variables > Actions
から、以下の3つのシークレットを登録します:
-
CLAUDE_APP_ID
: 作成したカスタムGitHub AppのID -
CLAUDE_APP_PRIVATE_KEY
: ダウンロードした秘密鍵 -
CLAUDE_AWS_ROLE_TO_ASSUME
: 作成したIAMロールのARN
ワークフローの作成
.github/workflows/claude-code.yml
として、以下のワークフローファイルを作成します:
name: Claude Code Action
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
jobs:
claude-response:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
runs-on: ubuntu-latest
env:
AWS_REGION: us-east-1
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
- name: Configure AWS Credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CLAUDE_AWS_ROLE_TO_ASSUME }}
aws-region: us-east-1
- uses: anthropics/claude-code-action@beta
with:
trigger_phrase: "@claude"
timeout_minutes: "60"
github_token: ${{ steps.app-token.outputs.token }}
use_bedrock: "true"
model: "us.anthropic.claude-sonnet-4-20250514-v1:0"
model
の指定は、利用したいモデルのIDに適宜変更してください。
設定がうまくいっていると、@claude
を付けて依頼すればPRのレビューやIssueを読んで開発作業をしてくれます。
ワークフローの共通化(応用編)
フィッツプラスはリポジトリがものすごく多いです。各リポジトリで設定をしてもいいのですが、モデルの変更やアクション自体のアップデートをそれぞれのリポジトリで管理するのはいささか面倒に感じました。
というわけなので、メンテナンス性を考慮してワークフローを共通化しました。GitHub Actionsのworkflow_call
を利用すると、メインの処理を1つのリポジトリに集約し、他のリポジトリから簡単に呼び出せるようになります。
共通ワークフローの作成
まず、共通ワークフローを配置するリポジトリを決めます。フィッツプラスでは専用の共通ワークフローリポジトリがあるので、そこに以下の修正を加えたファイルを配置しました。
元々のワークフローにworkflow_call
トリガーと、必要なinputsとsecretsを追加します:
@@ -13,13 +13,33 @@ on:
types: [created]
issues:
types: [opened, assigned]
+ workflow_call:
+ inputs:
+ trigger_phrase:
+ description: 'Phrase to trigger Claude action'
+ required: false
+ type: string
+ default: '@claude'
+ timeout_minutes:
+ description: 'Timeout in minutes'
+ required: false
+ type: string
+ default: '60'
+ secrets:
+ CLAUDE_APP_ID:
+ required: true
+ CLAUDE_APP_PRIVATE_KEY:
+ required: true
+ CLAUDE_AWS_ROLE_TO_ASSUME:
+ required: true
jobs:
claude-response:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
- (github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
+ (github.event_name == 'issues' && contains(github.event.issue.body, '@claude')) ||
+ (github.event_name == 'workflow_call')
runs-on: ubuntu-latest
env:
AWS_REGION: us-east-1
@@ -42,8 +62,8 @@ jobs:
- uses: anthropics/claude-code-action@beta
with:
- trigger_phrase: "@claude"
- timeout_minutes: "60"
+ trigger_phrase: ${{ inputs.trigger_phrase || '@claude' }}
+ timeout_minutes: ${{ inputs.timeout_minutes || '60' }}
github_token: ${{ steps.app-token.outputs.token }}
use_bedrock: "true"
model: "us.anthropic.claude-sonnet-4-20250514-v1:0"
共通ワークフロー(完全版)
name: Claude Code Action
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
workflow_call:
inputs:
trigger_phrase:
description: 'Phrase to trigger Claude action'
required: false
type: string
default: '@claude'
timeout_minutes:
description: 'Timeout in minutes'
required: false
type: string
default: '60'
secrets:
CLAUDE_APP_ID:
required: true
CLAUDE_APP_PRIVATE_KEY:
required: true
CLAUDE_AWS_ROLE_TO_ASSUME:
required: true
jobs:
claude-response:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude')) ||
(github.event_name == 'workflow_call')
runs-on: ubuntu-latest
env:
AWS_REGION: us-east-1
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.CLAUDE_APP_ID }}
private-key: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
- name: Configure AWS Credentials (OIDC)
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.CLAUDE_AWS_ROLE_TO_ASSUME }}
aws-region: us-east-1
- uses: anthropics/claude-code-action@beta
with:
trigger_phrase: ${{ inputs.trigger_phrase || '@claude' }}
timeout_minutes: ${{ inputs.timeout_minutes || '60' }}
github_token: ${{ steps.app-token.outputs.token }}
use_bedrock: "true"
model: "us.anthropic.claude-sonnet-4-20250514-v1:0"
各リポジトリでの利用
各リポジトリでは、この共通ワークフローを呼び出すシンプルなファイルを配置するだけで済みます:
name: Claude Code Action
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
jobs:
claude-response:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issues' && contains(github.event.issue.body, '@claude'))
uses: armg/common-workflows/.github/workflows/claude-code.yml@main
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
secrets:
CLAUDE_APP_ID: ${{ secrets.CLAUDE_APP_ID }}
CLAUDE_APP_PRIVATE_KEY: ${{ secrets.CLAUDE_APP_PRIVATE_KEY }}
CLAUDE_AWS_ROLE_TO_ASSUME: ${{ secrets.CLAUDE_AWS_ROLE_TO_ASSUME }}
uses
句のパス(armg/common-workflows/...
)は、共通ワークフローを置いたリポジトリに合わせて変更してください。
共通化のメリット
各リポジトリ側のコードも決して少ないとは言えませんが、メンテナンスは楽になりそうだと感じます。
また、リポジトリ固有の設定が必要な場合は、inputsパラメータを追加することで柔軟に対応できます。例えば、特定のリポジトリでは異なるモデルを使用するなども可能です。
まとめ
Amazon Bedrockを利用したClaude Code GitHub Actionsの環境を構築し、さらに共通化によってメンテナンス性を高める手順をご紹介しました。
まだベータ版という位置づけのようですが、Issueの内容に基づいたコードの自動修正提案など、開発の様々な場面で活躍してくれそうです。 共通化の仕組みを整えることで、複数のリポジトリでも運用しやすくなり、組織全体でのClaude Code活用が現実的になりました。
参考リンク
今回の設定をするにあたり参考にした記事です。ありがとうございました!
Discussion