ブログ一覧

.github リポジトリの PR テンプレートに「ハマったこと」欄を置く理由

GitHub の組織で複数のリポジトリを運用していて、PR のテンプレートがリポジトリごとにばらばらになっていました。しかも、AI エージェント(Claude Code)に PR を作らせると、テンプレートはそもそも使われていませんでした。この記事は、組織の .github リポジトリに 1 つのテンプレートを置いて全リポジトリの既定にした話と、そのテンプレートに「ハマったこと・試行錯誤」の欄を置いて、あとから機械的に拾える資産にした話です。

症状: テンプレートが「適用されるはず」なのに、PR の本文に出てこない

私は Claude Code に Issue から PR までを作らせています。PR を作るコマンドは `gh pr create` で、エージェントは本文を --body で渡します。このとき、リポジトリに置いた PR テンプレートは使われません。テンプレートが本文欄に差し込まれるのは、GitHub の Web UI で PR を開いたときと、gh pr create を本文なしで対話的に使ったときで、本文を明示して渡せば素通りします。私は「適用されるはず」だと思い込んでいて、エージェントの作った PR にテンプレートの見出しが 1 つも無いことに、しばらく気づきませんでした。

もう 1 つ、リポジトリが増えるにつれて、テンプレートの中身がずれていきました。片方には「ハマったこと」の欄があり、片方には無い。エージェントが PR に何を書くかは、そのリポジトリのテンプレートで決まるので、書き残される物語の質がリポジトリごとに違っていました。

直し方: 組織の .github リポジトリに 1 つ置く

shinobiworks/.github            # 公開リポジトリ
  .github/
    ISSUE_TEMPLATE/
      bug_report.yml            # Issue Forms(概要 / 再現手順 / 期待 / 実際 / 環境 / ログ)
      feature_request.yml       # Issue Forms(解決したい課題 / 提案 / 代替案)
      config.yml
    PULL_REQUEST_TEMPLATE.md    # Summary / 関連 Issue / 変更内容 / 動作確認方法 / 🔥 ハマったこと・試行錯誤
  README.md

GitHub には、組織(または個人アカウント)に .github という名前の公開リポジトリを置くと、そこに入れた Issue や PR のテンプレートが、個別にテンプレートを持たないリポジトリの既定になる仕組みがあります。各リポジトリからテンプレートを消して、ここ(shinobiworks/.github)に 1 つだけ残しました。以後、テンプレートを直すのは 1 か所です。

エージェント側の対処: テンプレートは取りに行く

--body で素通りする問題は、テンプレートの側では直せません。エージェントの作業手順に「PR を作る前に .github リポジトリのテンプレートを取得し、その見出しの構成に沿って本文を組み立てる」と書きました。Issue Forms(yml)も gh issue create --body では適用されないので、同じようにフィールドの label を見出しに読み替えて本文を組みます。

gh api repos/shinobiworks/.github/contents/.github/PULL_REQUEST_TEMPLATE.md --jq '.content' | base64 -d

テンプレートを「自動で差し込まれる物」ではなく「作業の前に読む仕様」として扱う、という置き直しです。

「🔥 ハマったこと・試行錯誤」の欄

テンプレートの最後にこの欄を置いています。書くのは、詰まった点、調査の過程、捨てた実装とその理由。「未来の自分とレビュワーへの申し送り」と説明を付けてあります。無ければ空欄でよい。

この欄を置いた理由は、commit のメッセージには「何をしたか」しか残らないからです。「何に詰まって、どう抜けたか」は、作業の直後に書かないと消えます。エージェントに作業させていると特にそうで、セッションが終わればその文脈はどこにも残りません。PR の本文は、作業の文脈がいちばん濃い時点で書かれ、リポジトリに永久に残る、唯一の場所です。

そして、この欄は機械的に拾えます。私は別の bot に、毎朝、指定したリポジトリの直近 24 時間の commit・PR・Issue を集めさせていて、PR の本文はそのまま素材に入ります。「ハマったこと」の欄があれば、そこを優先して引用するように指示してあります。この bot の設計は 自動投稿 bot の設計を「ネタ→投稿」から「背景→投稿」に変えた に書きました。

拾う側で失敗したこと

bot が PR の本文を素材に含める上限を、最初は 300 文字にしていました。テンプレートの欄は本文の一番下にあるので、冒頭から 300 文字で切ると、まさに欲しい欄が落ちます。上限を 2,000 文字に上げて直しました。欄を置いた PR 自身の「ハマったこと」には、こう書いてあります。

特になし(この欄自体が本 PR の成果物)

残す場所(テンプレートの欄)と拾う側(本文の上限)は、揃えて初めて動きます。片方だけ作っても資産にはなりません。

境界: テンプレートに置く物と、置かない物

  • 置く: 見出しの構成(Summary、関連 Issue、変更内容、動作確認方法、ハマったこと)。これは全リポジトリで同じでよい
  • 置かない: リポジトリ固有の手順(デプロイの注意、テストのコマンド)。それは各リポジトリの CLAUDE.md や README に置く。テンプレートに書くと、他のリポジトリで嘘になる
  • 欄は用意するが、埋めることは強制しない。「特になし」と書ける欄にしておかないと、埋めるために作り話が書かれる

どこで止まるか

  • .github リポジトリの既定は、そのリポジトリ自身にテンプレートが無いときだけ効きます。個別のテンプレートが残っていると、そちらが勝ちます。統一するなら各リポジトリから消す作業が要ります
  • 組織の既定として効かせるには、.github リポジトリを公開にする必要があります。テンプレートの中身は公開情報になります
  • 欄があっても、書く人(エージェントを含む)が書かなければ空です。私の場合、エージェントの手順書に「この欄は空にしない。調査で判明した非自明な点を書く」と明記して埋まるようになりました

この構成で気をつけること

  • gh pr create --body はテンプレートを使わない。エージェントに作らせるなら、テンプレートを「差し込まれる物」ではなく「先に読む仕様」にする
  • テンプレートは組織の .github リポジトリに 1 つ。リポジトリごとに持たない
  • 「ハマったこと」の欄は、作業の文脈が消える前に物語を残す唯一の場所。commit には残らない
  • 残す場所と拾う側の両方を作る。拾う側の上限や順序で、欄ごと落ちることがある

参考リンク

関連

この記事をシェア