GitHub Issueにメモするだけでdraft PRができる仕組みを作った話(Claude Code + GitHub Actions)

概要

今回はGitHub Issueにタスクをメモしておくだけで、実装済みのdraft PRが自動でできあがる仕組みを作ったので紹介していきます。

個人で家計簿アプリを作っているのですが、「カテゴリ別の支出グラフが欲しいな」と思いついても、本業がある平日はなかなか手が回らないんですよね。
そこでスマホからGitHub Issueにメモしておいたら、帰宅する頃には実装されたdraft PRができていたという仕組みを作りたくて、Claude Code + GitHub Actionsで無人実装パイプラインを組みました。

正直、動かすまでに何回もハマったので、その辺りも含めて共有していきます(^^b

それではやっていきましょう!

生成されたdraft PRは必ず人間がレビュー・マージする運用です。
自動マージは行っていません。
個人開発の実験的な仕組みなので、そのまま業務利用する場合は各社のセキュリティ方針に沿って十分に検証してください。

目次

全体構成

まずは全体像から。
Issueにメモを書いてからdraft PRができるまでの流れをまとめると、こんな感じです。

Issueメモからdraft PRまでの無人実装パイプライン(GitHub Actions → claude-code-action → draft PR)
Issueメモからdraft PRまでの無人パイプライン構成図。特定ラベルでActions起動、claude-code-actionが実装、ブランチ作成とコミット、draft PR発行の4ステップ

Issue Formsをメモ欄1本にまとめた話

依頼の受け口にはGitHub Issue Forms(フォーム形式のIssueテンプレート)を使っています。

最初は「テーマ」「カテゴリ」「参考URL」「その他要望」と項目を分けていたのですが、結局「自由記述のメモ欄1つ」にまとめた方が書く手間が減って良かったという発見がありました。

  • 項目を分けるほど入力のハードルが上がる
    • スマホで思いついた瞬間にメモしたいのに、項目ごとに迷って手が止まってしまう
  • 自由記述でもClaude側で十分に解釈できる
    • テーマ・要望・参考URLが1つの文章に混ざっていても、実装内容の解釈には困らなかった

入力側のUXを削って、解釈は全部AI側に任せるという判断は、個人開発の無人パイプラインだとかなり相性が良いと感じました。

ラベル駆動でGitHub Actionsを起動

Issue Formsで受け取った依頼に特定ラベル(例: ai-taskが付いたことをトリガーに、anthropics/claude-code-actionをGitHub Actions上で実行しています。

Claude CodeにBash/Read/Write/Edit等のフルツールセットを与え、リポジトリをcheckoutした状態で、実装からブランチ作成・コミット・draft PR発行までを一気にやらせる実装です。

.github/workflows/ai-task.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
on:
issues:
types: [labeled]

jobs:
implement:
if: contains(github.event.issue.labels.*.name, 'ai-task')
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}

認証はサブスクのOAuthトークンで

API従量課金ではなく、個人のサブスクリプション(Claude Pro/Max)からOAuthトークンを発行してSecretsに登録する形にしています。

コマンド

1
claude setup-token

発行したトークンをCLAUDE_CODE_OAUTH_TOKENとしてリポジトリのSecretsに登録しておけば、サブスク枠内で無人実行が回ります。
API従量課金だと指示を失敗した時に、とんでもない金額が請求される可能性があり費用も読みにくいので、この構成はかなりお勧めです(^^

draft PRで人間のレビューを待つ運用

生成後は必ずdraft PRとして開き、人間が最終レビュー・マージするまで自動マージはしないようにしています。

無人実行とはいえ、実装内容を無条件に信用するのは怖いですよね。
draft PRなら「できあがってはいるけど、まだ確認していない」という状態が一目で分かるので、運用としてかなり安心感があります。

@claudeコメントでの修正フロー

draft PRができたあとに、グラフの配色が気に入らなかったり、ちょっとした直しが欲しくなることもよくあります。
そこでPRやIssueへの「@claude ◯◯を直して」というコメントで修正依頼を出すと、該当ブランチを自動でcheckoutして修正コミットをpushする仕組みも追加しました。

例えば、draft PRのグラフの配色が気に入らなかったので@claude 配色をもう少し落ち着いた色にしてとコメントしたら、そのまま直ってpushされてきた、というような使い方です。

@claudeコメントでの修正フロー(対象がPRかIssueかでブランチの特定方法を変える)
claudeコメントでの修正フロー図。PRへのコメントならgh pr viewでheadRefNameを取得し、Issueへのコメントなら命名規則からブランチ名を導出して共通のcheckoutと修正コミットに合流する

ここで一つ注意点があって、対象がPRかIssueかでブランチの特定方法を変える必要があるんですよね。

  • PRへのコメントの場合
    • gh pr view --json headRefNameで正確なブランチ名をAPIから直接取得できる
  • Issueへのコメントの場合
    • PRがまだ存在しないので、article/issue-<番号>のような命名規則からブランチ名を導出する

この分岐を作っておくと、draft PRができた後の「ちょっとここ直して」がコメント1本で完結するようになって、かなり快適です(^^b

ハマったポイント

ここが今回一番書きたかったところです。
同じところで何度も詰まったので、順番にまとめます。

1. labels:の自動付与は既存ラベルが無いと無視される

GitHub Issue Formsのlabels:(作成時の自動ラベル付与設定)は、そのラベルがリポジトリに既に存在する場合のみ機能するという仕様でした。

.github/ISSUE_TEMPLATE/article-request.yml

1
2
3
name: 記事リクエスト
labels:
- ai-task

存在しないラベルを指定していても、テンプレートを提出した瞬間に黙って無視され、ラベルが付かないので自動化が発火しません。
エラーも出ないので気付きにくく、最初はここでけっこう時間を溶かしました。。。

リポジトリの「Issues → Labels」で先にラベルを作成しておくだけで解決します。
やっかいですよね。

2. opened+labeledで同じIssueに2回ジョブが走る

on: issues: types: [opened, labeled]にすると、ラベル付きIssueをフォームで作成した瞬間にopenedlabeledの2つの別イベントが発火し、同じIssueに対してジョブが2回走ってしまいました。

フォーム作成時にlabels:で自動付与されると、GitHubの内部的には「Issue作成」と「ラベル付与」が同時に起きるため、両方のイベントが飛んでくる、という仕組みのようです。

.github/workflows/ai-task.yml

1
2
3
4
5
6
7
8
9
10
11
12
# 修正前(2回発火する)
on:
issues:
types: [opened, labeled]

# 修正後(labeledだけに絞る)
on:
issues:
types: [labeled]
jobs:
implement:
if: contains(github.event.issue.labels.*.name, 'ai-task')

labeledだけに絞り、条件も「そのイベントで実際に付与されたラベルそのもの」を見るように直したら解決しました
2回実行されると同じ内容のdraft PRが2つできてしまうので、トークンの無駄かつ混乱します(- -;

3. Workflow permissionsだけではPRが作れない

GitHub Actionsの「Workflow permissions」を書き込み可(Read and write permissions)にしただけでは、gh pr createが次のエラーで失敗しました。

エラー

1
GitHub Actions is not permitted to create or approve pull requests

別途「Allow GitHub Actions to create and approve pull requests」というチェックボックスを有効にする必要がありました。
設定場所はSettings → Actions → General → Workflow permissionsの一番下です。

このチェックボックスはリポジトリ単位(もしくはOrganization単位)の設定なので、workflowファイル側の`permissions:`をいくら調整しても解決しません。
「権限は足りているはずなのに」でかなり苦労しました。

4. ghが無いときはcompare URLで手動作成できる

ローカルにgh CLIが入っていない環境でも、compare URL(.../compare/main...<branch>)からワンクリックでdraft PRを手動作成できることも分かりました。

Claude Code側にブランチ作成・コミットまでやらせておいて、PR発行だけ手動で行いたい場合には便利な方法です。
自動化が思うように動かなかったときの検証手段としても使えます。

使ってみた所感

メリット

  • 思いついた瞬間にメモするだけで着手できる
    • スマホからIssueを書いた数分後にはActionsが動き出している
  • サブスク枠内で完結するので費用が読みやすい
    • API従量課金ではなくclaude setup-tokenのOAuthトークンで実行できる
  • draft PRを挟むので安心感がある
    • 実装内容を無条件に信用せず、必ず人間が最終確認できる
  • @claudeコメントで軽い直しがコメント1本で終わる
    • 配色調整のような細かい要望をもう一度Issueを書かずに依頼できる

デメリット

  • 同じところで何度もハマる仕組みなので、初回セットアップに時間がかかる
    • ラベル・イベント・権限のどれか一つ抜けても発火しない
  • ラベル付与を忘れると気付きにくい
    • エラーが出ずに単に発火しないだけなので、しばらく気付かないことがある
  • 無人実行なので、実装の妥当性は結局人間が見る必要がある
    • draft PRができても、レビューの手間自体はゼロにはならない

デメリット面は基本的にセットアップ周りだけなので、そこさえ出来ちゃえばあとは楽しい開発作業が待ってます!

まとめ

今回はGitHub Issueにタスクをメモするだけで、実装済みのdraft PRができあがる無人実装パイプラインを紹介しました。

ポイントをおさらいすると以下のとおりです。

  • Issue Formsはメモ欄1本にまとめた方が書く手間が減る
  • ラベル駆動でActionsを起動する際はlabeled単体イベントに絞る
  • 認証はclaude setup-tokenサブスク枠内に収める
  • 生成物は必ずdraft PRとして人間のレビューを待つ
  • @claudeコメントでPR/Issueを判別しつつ軽い修正を依頼できる

思いついたタスクを忘れないようにメモしておいても、結局手が空くまで着手できない、というのは個人開発だとよくある悩みだと思います。
「Issueに書く→気づいたらdraft PRができている」という体験は作ってみるとかなり気持ちいいので、似たような悩みを持っている方の参考になったらうれしいです。

以上となります。
issuesを書くだけで実装まで完了するっていい時代ですよね(^^
それではお疲れさまでした。