• トップ
  • ブログ一覧
  • Sentryのアラートが自動PRになるまで ── GitHub App認証をちゃんと選んだ話
  • Sentryのアラートが自動PRになるまで ── GitHub App認証をちゃんと選んだ話

    はじめに

    先日、チームでこんな仕組みを作りました。

    「バグアプリのアラートを検知して、AIが自律的にPRを作成する」

    Sentryにアラートが飛んだら、自動で修正PRが届いている。
    そんな仕組みです。
    チーム内で役割分担をして、自分が担当したのはパイプラインの中の「GH Actionsを安全に起動する認証まわり」でした。

    地味といえば地味なテーマですが、ここの選択を雑にするとあとで運用コストとして返ってきます。この記事では、認証方式をどう選んで、どう実装したか、そしてどこでハマったかを書いていきます。

    作ったものの全体像

    まず全体のパイプラインをざっくり整理しておきます。

    1Sentry
    2↓ アラート発火
    3Cloud Run Functions(プロキシ)
    4GH Actionsをキック
    5GitHub Actions ワークフロー
    6Anthropic APIに連携
    7PR自動作成

    チーム内の役割分担は、「バグを仕込んだアプリを作る人」と「アラートからPR作成までのパイプラインを作る人」に分かれていました。自分は後者の担当で、特にCloud Run FunctionsからGH Actionsを起動するための認証まわりを受け持ちました。

    認証どうする問題:PATをやめてGitHub Appにした理由

    GH ActionsのAPIを叩くには認証トークンが必要です。選択肢として最初に浮かんだのはPAT(Personal Access Token)でした。

    最初はPATを考えていた

    PATは発行が簡単で、とりあえず動かすだけなら十分です。ただ、ちょっと立ち止まって考えると、チーム開発・CI/CD用途で使うには気になる点がいくつかありました。

    個人アカウントに紐づく問題
    PATは「誰かの」トークンです。発行した人が退職・異動したとき、そのトークンはどうするのか。失効させたら動かなくなるし、引き継ぎを忘れたら気づかずに本番が止まる、という未来が見えました。

    ローテーションの運用コスト
    PATには有効期限があり、定期的な更新が必要です。「更新してください」という通知が来るたびに手作業で対応するのは、地味に面倒だし見落とすリスクもあります。

    「動くかどうか」だけで考えるとPATで十分なのですが、「半年後も誰かがちゃんと運用できるか」まで考えると、まぁ無いよね、別の選択肢を探そ、となりました。

    GitHub Appに切り替えた

    GitHub Appは「人」ではなく「アプリ」として動きます。特定の個人アカウントに依存しないので、メンバーが変わっても影響を受けません。

    もう一つ気に入ったのがInstallation Tokenの仕組みです。PEMファイル(秘密鍵)からJWTを生成し、それを使って有効期限1時間のInstallation Tokenを動的に取得する、という流れになります。

    1Sentry(アラート発火)
    2Webhook
    3Cloud Run Functions(秘密鍵取得JWT生成)
    4JWTで認証
    5GitHub API(Installation Token発行・有効期限1時間)
    6Tokenで認証
    7GitHub Actions(workflow_dispatch をキック)

    ① GCP Secret ManagerにPEMとInstallation IDを保管しておき、Cloud Run Functionsが起動するたびに取得・JWT生成・Token交換という流れを都度実行します。

    毎回使い捨てのトークンを発行するので、万が一漏洩しても被害が限定的。ローテーションも自動化できます。

    設定の手間は正直PATよりかかります。GitHub Appの作成、GCP Secret Managerへの秘密鍵登録、Cloud Run FunctionsでのJWT生成処理……とステップは多い。ただ一度動けば運用がラクになると判断して採用しました。

    学んだこと

    「とりあえず動く」と「ちゃんと運用できる」は別の話だなと改めて感じました。PATは確かに手軽ですが、その手軽さのコストは後から運用するときに出てきます。認証方式の選定って地味なテーマですが、こういう判断の積み重ねが長く動き続けるシステムになるんだと思います。

    実装の流れ ── ハマったところも正直に

    GitHub Appの認証方式は決まった。あとは実装するだけ……と思っていたら、細かいところでいくつかハマりました。

    Cloud Run FunctionsはClaude Codeに任せた

    今回、Cloud Run Functionsのコード(動作確認用ですが)はClaude Codeに書いてもらいました。Ruby 3.4で、JWT生成からInstallation Token取得、GH Actionsのキックまでの一連の流れをざっくり指示したら、骨格はほぼ作ってくれました。

    コードの品質自体はかなりよかったです、多分(あまりRubyは得意ではない)。ただ、「動くコードを書く」ことと「その環境でちゃんと動く」ことは少し別の話で、そこの詰めは自分でやる必要がありました。

    ハマり① grpc関連のgemバージョン

    GCP Secret ManagerからPEMやInstallation IDを取得するために GoogleCloud SecretManager を使ったのですが、その依存として入ってくるgrpc系のgemのバージョンが曲者でした。

    Ruby 3.4との組み合わせで、バージョンによってはビルドがこけたり、実行時にエラーが出たり、おかげで汗べったり。
    原因はClaude Codeが生成したGemfileの特定のgemのバージョン指定がCloud Run Functions 上で対応しているバージョンに対応していない(指定してたのが新しかった)ためでしたが、動く組み合わせを探すのに時間がかかりました。

    gemのバージョンを明示的に固定して、bundle update で依存関係を整理し直すことで落ち着きました。新しめのRubyバージョンを使うときは、GCP系のgemがCloud Run Functionsのプラットフォーム上追いついているかを最初に確認しておくのが良さそうです、トライアンドエラーを繰り返したくなければね。

    ちなみに追加したgemとそのバージョンは以下となります。

    1gem "google-protobuf", "4.28.1"
    2gem "grpc", "1.73.0"

    何か昔dockerのビルドでもprotobuf/grpcでハマった記憶、デジャブ。

    ハマり② GH ActionsデプロイのSA権限不足

    Cloud Run FunctionsのデプロイをGH Actionsで回していたのですが、デプロイ用のService Account(SA)の権限が足りなくてデプロイが失敗しました。

    こちらもClaude Codeが生成したワークフローを使っていたのですが、SAに付与すべき権限の洗い出しまでは完全にはカバーされていませんでした。エラーログを見ながら「このAPIへのアクセス権がない」→「ロールを追加」を数回繰り返して解決した感じです。

    必要だったのは大まかに以下のようなロールです(環境によって変わります):

    1// Cloud Shell
    2$ gcloud projects get-iam-policy ${PROJECT_ID} \
    3--flatten="bindings[].members" \
    4--filter="bindings.members:serviceAccount:${デプロイ用のSAアカウント}" \
    5--format="table(bindings.role)"
    6
    7ROLE: roles/artifactregistry.writer // ビルドコンテナイメージ格納
    8ROLE: roles/cloudfunctions.admin // CloudRunFunctions管理者(過剰だったかも?)
    9ROLE: roles/iam.serviceAccountUser // CloudRunFunctionsに特定の権限の紐づけ
    10ROLE: roles/run.developer // CloudRunFunctionsの作成/デプロイ/更新/削除できる権限
    11ROLE: roles/storage.objectAdmin // 一時退避先(バケット)への権限

    Claude Codeについて一言

    誤解してほしくないのですが、Claude Codeはめちゃくちゃ便利でした。コードの骨格を一気に作ってくれるし、構成の相談にも乗ってくれるし、おすし。

    ただ、「GCPのIAM権限まわり」とか「特定バージョン組み合わせの相性」みたいな、環境依存で細かいところは、まだ完全には拾いきれない印象でした。そこを自分で詰める必要があるという前提で使うと、期待値がちょうどよくなると思います。

    「ほぼ完璧、あとは環境依存の詰めだけ」という状態を作ってくれるツールとして、かなり頼りになりました。

    まとめ

    今回の担当範囲を通じて、学んだことを整理しておきます。

    認証方式は「運用できるか」で選ぶ
    PATは手軽だけど、チームで長く使うには向いていない場面がある。GitHub Appは初期コストが高めだが、運用が属人化しない設計になっている。最初の選択でここをちゃんと考えられたのはよかったと思っています。

    Claude Codeは「骨格を作るツール」として使う
    コードの生成はとても優秀。ただし、インフラ権限や依存gemのバージョンといった「環境の文脈」は自分で確認する必要がある。その前提で使うと非常に強力なツールです。

    自分のスコープを明確に持つ
    チーム開発で役割分担をするとき、担当範囲を明確に持つと迷わず進められます。「自分はここを責任もってやりきる」という意識が、結果的に全体のスピードにもつながると感じました。

    ライトコードでは、エンジニアを積極採用中!

    ライトコードでは、エンジニアを積極採用しています!カジュアル面談等もございますので、くわしくは採用情報をご確認ください。

    採用情報へ

    おすすめ記事

    エンジニア大募集中!

    ライトコードでは、エンジニアを積極採用中です。

    特に、WEBエンジニアとモバイルエンジニアは是非ご応募お待ちしております!

    また、フリーランスエンジニア様も大募集中です。

    background