GitHub 連携
GitHub App を一度連携すれば、ブランチ・タイトル・本文にイシュー識別子を含む PR が該当イシューに自動で紐づきます。そして PR をマージするとイシューが Done に移動します。
設定 → GitHub で GitHub アカウントまたは組織を一度だけ連携してください。その後は、ブランチ名・タイトル・本文にイシュー識別子(例: MUL-123)を含むあらゆる pull request が該当するイシューに自動で紐づき、イシューサイドバーの Pull requests に表示され、PR がマージされるとイシューが Done に移動します。
イシューごとの設定はありません。フロー全体が識別子で駆動されます。
連携が行うこと
| 場所 | 動作 |
|---|---|
| 設定 → GitHub | ワークスペースの admin には、マスタートグル、Connect GitHub ボタン、機能スイッチ(PR サイドバー、Co-authored-by、自動紐づけ)を備えた GitHub タブが表示されます。インストール後は GitHub タブに戻ります。 |
| イシューサイドバー → Pull requests | このイシューに自動で紐づいたすべての PR が、タイトル、リポジトリ、状態(Open / Draft / Merged / Closed)、作成者とともに表示されます。行をクリックすると GitHub の該当 PR に移動します。 |
| Webhook(バックグラウンド) | すべての pull_request イベントで、Multica は PR 行を upsert し、PR からイシュー識別子をスキャンして、紐づけ行を(再)構築します。冪等性があり、同じ delivery を再送しても変化はありません。 |
| マージ時のステータス自動変更 | PR が merged に遷移すると、まだ Done でも Cancelled でもない、紐づいたすべてのイシューが Done に移動します。ステータス変更は source github_pr_merged でタイムラインに記録されます。 |
ミラーリングされるのは PR 自体のみです。コミット、オープンな PR のないブランチ ref、CI チェックの状態はモデル化されません。この連携は意図的に狭く設計されています。
識別子のマッチング方法
Webhook は次の順序で 3 つのフィールドから識別子を抽出します: PR head ブランチ、PR タイトル、PR 本文。マッチャーは次のとおりです。
- 大文字小文字を区別しません —
mul-123、MUL-123、Mul-123はすべてマッチします。 - 境界があります — 左側の
\bと右側の数字アンカーにより、v1.2-3のようなバージョン番号やメール形式の文字列を誤って拾わないようにしています。 - ワークスペーススコープに限定されます — そのワークスペース固有のイシュー prefixにのみマッチします。prefix が
MULのワークスペースでは、整数が別のイシューと一致してもFOO-1は無視されます。 - 重複が除去されます — 本文に
MUL-1, MUL-1と並べても、イシューは一度だけ紐づきます。
1 つの PR で複数のイシューを参照できます。Closes MUL-1, MUL-2 は PR を両方のイシューに紐づけ、マージすると両方が Done に進みます。
マージ時の Done 自動変更ルール
PR の merged フィールドが true に切り替わると、紐づいたすべてのイシューが評価されます。
| イシューの現在のステータス | 結果 |
|---|---|
done | 変化なし(すでに終了状態)。 |
cancelled | 変化なし — cancelled はユーザーが作業を明示的に放棄したことを意味するため、連携はこのシグナルを上書きしません。 |
それ以外すべて(todo、in_progress、in_review、blocked、backlog) | done に移動。 |
PR をマージせずにクローズした場合は、PR カードの状態が Closed に更新されるだけです。紐づいたイシューはそのまま維持されます — マージせずにクローズすることが何を意味するかはユーザーが決めるからです。
この動作はタイムライン上で system アクターに帰属します。イシューの購読者は、人がステータスを移動したときと同じように、ステータス変更に関するインボックス通知を受け取ります。
自動で紐づかないもの
- コミットメッセージ内の識別子 — ブランチ / タイトル / 本文のみがスキャンされます。
MUL-123: fix loginというタイトルのコミットは、同じ文字列が PR タイトルや本文にも現れない限り自動では紐づきません。 - PR コメント内の識別子 — PR 自体のメタデータのみがスキャンされ、後から付いた GitHub コメントは無視されます。
- App がインストールされていないリポジトリの PR — App がなければ、Multica は webhook をまったく受け取りません。
- PR をイシューに手動で紐づける — まだこのための UI はありません。チームの慣習で識別子を Multica が読まない場所に置いている場合は、PR タイトルや本文に追加してください。
連携解除
設定 → GitHub にはインストール一覧はありません — 既存のインストールは GitHub から直接管理します。
- GitHub から —
https://github.com/settings/installations(個人)またはhttps://github.com/organizations/<org>/settings/installations(組織)で Multica GitHub App をアンインストールします。Multica はinstallation.deletedwebhook を受け取ってリアルタイムで行を削除し、開いている Settings タブはリロードなしで更新されます。 - Multica 内部からの連携解除は admin 専用です — GitHub タブの連携解除コントロールは、admin 以外のユーザーには非表示です。マスター GitHub スイッチがオフでも利用可能なままなので、admin はワンクリックで機能を無効化した後でも、古いインストールを取り消せます。
連携解除後も、ミラーリングされた PR 行はデータベースに残り、過去のイシューサイドバーで何が紐づいていたかを引き続き表示しますが、そのインストールから新たに入ってくる webhook イベントは受理されなくなります。
権限と可視性
- 連携 / 連携解除にはワークスペースの owner または admin が必要です。member にはカードの説明は見えますが、Connect ボタンは見えません。
- イシューの Pull requests サイドバーは、そのイシューを閲覧できる誰にでも表示されます — イシュー詳細の他の部分と同じ権限です。
- GitHub App は pull request とメタデータへの読み取り専用アクセスを要求します。Multica はコミット、コメント、ステータスチェックを GitHub に書き戻すことはありません。
セルフホストのセットアップ
Multica Cloud で Multica を実行している場合、連携はすでに構成済みです — このセクションは飛ばしてください。
セルフホストの場合は、GitHub App を 1 つ作成し、サーバーを指すように設定し、環境変数を 2 つ設定します。フロー全体は以下のとおりです。
1. GitHub App を作成する
次のいずれかにアクセスしてください。
- 個人アカウント →
https://github.com/settings/apps/new - 組織 →
https://github.com/organizations/<org>/settings/apps/new
次を入力します。
| フィールド | 値 |
|---|---|
| GitHub App name | 見分けやすい名前、例: Multica または Multica (staging)。 |
| Homepage URL | Multica フロントエンド、例: https://multica.example.com。 |
| Callback URL | 空欄のままにしてください — Multica は OAuth ユーザー ID を使用しません。 |
| Setup URL | https://<api-host>/api/github/setup。「Redirect on update」をチェックしてください。 |
| Webhook → Active | 有効。 |
| Webhook URL | https://<api-host>/api/webhooks/github。 |
| Webhook secret | 長いランダム文字列を生成してください(例: openssl rand -hex 32)。手順 2 で同じ値を Multica の env に貼り付けます。 |
| Permissions → Repository → Pull requests | Read-only。 |
| Permissions → Repository → Metadata | Read-only(必須)。 |
| Subscribe to events | Pull request をチェックしてください。 |
| Where can this GitHub App be installed? | お好みで。単一組織のセットアップなら Only on this account で十分です。 |
Create GitHub App の後、App の詳細ページから 2 つのことを控えておいてください。
- 上部の public link — その末尾が slug です。
https://github.com/apps/multica-acme→ slug =multica-acme。 - 先ほど生成した webhook secret(後で GitHub から読み戻すことはできません — 今すぐ保存してください)。
Webhook secret ≠ Client secret。 App 設定ページには両方のフィールドが並んで配置されています。Webhook secret は pull_request の payload に署名する値で、Multica が必要とするものです。Client secret は OAuth 用で、この連携では使用しません。この 2 つを混同すると、すべての webhook delivery で紛らわしい 401 invalid signature が発生します。
2. 環境変数を設定する
API サーバーで:
GITHUB_APP_SLUG=multica-acme
GITHUB_WEBHOOK_SECRET=<the webhook secret you generated>両方の変数が必須です。どちらかが欠けていると:
- Settings の
Connect GitHubが無効になり、「not configured」のヒントが表示されます。 /api/webhooks/githubエンドポイントが503 github webhooks not configuredを返します — Multica は secret なしでイベントを処理することを拒否し、すべての署名を黙って有効として扱うことはありません。
FRONTEND_ORIGIN も設定されている必要があります(どのプロダクションのセルフホストでもすでに設定されています)。インストール後、setup コールバックがユーザーを <FRONTEND_ORIGIN>/settings?tab=github に戻します。
env 変数を設定した後は API を再起動してください。
3. マイグレーションを実行する
この連携はテーブルをマイグレーション 079_github_integration で提供します。古いデプロイをアップグレードする場合:
make migrate-up3 つのテーブルが作成されます: github_installation、github_pull_request、issue_pull_request。これらはワークスペースとともに cascade-delete されるため、ワークスペースを削除すると自動的にクリーンアップされます。
4. UI から連携する
Multica で:
- owner または admin 権限で 設定 → GitHub を開きます。
- Connect GitHub をクリックします。GitHub が新しいタブで開きます。
- アクセスを付与するリポジトリを選び、Install します。
- GitHub が
<api-host>/api/github/setupにリダイレクトしてインストールを記録し、<FRONTEND_ORIGIN>/settings?tab=github&github_connected=1に戻します。
その後、ブランチ / タイトル / 本文にイシュー識別子を含む PR を開いてみてください — 数秒以内に、そのイシューの詳細ページに Pull requests ブロックが表示されます。
5. curl プローブで検証する
インストール後に GitHub の Recent Deliveries ページで 401 invalid signature が報告される場合、両側の secret が異なっています。どちらが間違っているかを最も速く突き止める方法は、GitHub を迂回することです。
SECRET="<the value you put in GITHUB_WEBHOOK_SECRET>"
BODY='{"zen":"test"}'
SIG=$(printf '%s' "$BODY" | openssl dgst -sha256 -hmac "$SECRET" -hex | awk '{print $NF}')
curl -i -X POST https://<api-host>/api/webhooks/github \
-H "X-Hub-Signature-256: sha256=$SIG" \
-H "X-GitHub-Event: ping" \
-H "Content-Type: application/json" \
-d "$BODY"| HTTP ステータス | 意味 | 解決方法 |
|---|---|---|
200 {"ok":"pong"} | サーバーがロードした secret が $SECRET と一致します。不一致は GitHub 側にあります。 | App → Webhook secret を編集 → 同じ値を貼り付け → Save changes(保存せずにフィールドの外をクリックすると古い secret が維持されます)。再送してください。 |
401 invalid signature | サーバーがロードした secret が思っている値でありません。 | env 変数が実行中のプロセスに反映されたか確認してください(例: kubectl exec → echo -n "$GITHUB_WEBHOOK_SECRET" | wc -c)。再デプロイしてください。 |
503 github webhooks not configured | プロセスで GITHUB_WEBHOOK_SECRET が空です。 | env 変数を設定し、API を再起動してください。 |
制限事項
現時点で知っておくべき、いくつかの粗い部分があります。
- まだ手動の紐づけ UI はありません — PR を紐づける唯一の方法は、ブランチ、タイトル、本文に識別子を置くことです。
- CI / チェック状態はありません — PR 自体のみがミラーリングされます。ビルド状態、レビューコメント、レビュアーは Multica には表示されません。
- マージ → Done ルールに対するワークスペースレベルの設定はありません — 固定のデフォルトです(
cancelledでない限りmerged → done)。ワークスペースでカスタマイズできるマッピングは将来の追加予定です。 - 1 つのイシューに複数の PR が紐づく場合、マージは保守的です — 2 つの PR がどちらも
MUL-123を参照していて最初の 1 つがマージされると、イシューはただちにDoneに移動します。進める前に紐づいたすべての PR が解決されるのを待つ後続の変更が進行中です。