GitHub ActionsからGitHub CopilotをIssueに自動アサインする
背景
-
GitHub CopilotのCoding Agent機能を使い、IssueをCopilotに投げて自動対応させたい。
-
具体的には:
- 特定の条件を満たすIssueが作成されたタイミング、あるいは手動でワークフローを実行したタイミングで、
-
@copilotをassigneeに追加し、Coding Agentを起動したい。
解法
- Copilotのライセンスを保持するユーザーのPATをGitHubのシークレットに保存する
- GitHub Actionsのワークフローで
ghCLIを使い、Issueに@copilotをアサインする
実装手順
1. Fine-grained PATの発行
- GitHubにログイン
-
Settings→Developer settings→Personal access tokens→Fine-grained tokensから新規トークンを作成 - 対象リポジトリを限定して選択する
- 権限(Permissions)は最低限:
-
Repository access:- Issues: Read and write
- Metadata: Read
- (必要に応じて)Copilotの実行に必要な他の権限を追加
-
- トークンを発行し、この文字列を安全な場所にコピーしておく(あとから再表示はできない)
2. PATをSecretsに登録
対象リポジトリ(あるいはOrganization)のSecretsに、このトークンを登録する:
- 名前例:
COPILOT_ASSIGN_PAT - 値:先ほど発行したFine-grained PAT
3. GitHub Actionsワークフローの例
-
workflow_dispatchで手動実行 - 入力としてIssue番号を指定
- 指定されたIssueに
@copilotをassigneeとして追加
するシンプルな例である。
name: Assign Copilot to Issue (manual)
on:
workflow_dispatch:
inputs:
issue_number:
description: 'Copilot にアサインしたい Issue 番号'
required: true
type: number
jobs:
assign-copilot:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- name: Checkout (optional)
uses: actions/checkout@v4
- name: Assign Copilot to issue
env:
GH_TOKEN: ${{ secrets.COPILOT_ASSIGN_PAT }} # サービスアカウントの Fine-grained PAT
ISSUE_NUMBER: ${{ inputs.issue_number }}
run: |
echo "Assigning Copilot to issue #${ISSUE_NUMBER} in ${GITHUB_REPOSITORY}"
gh --version
gh issue edit "${ISSUE_NUMBER}" \
--repo "${GITHUB_REPOSITORY}" \
--add-assignee "@copilot"
補足:調査の詳細
ここからは、上記の結論に至るまでの調査内容を詳しく記載する。
調査結果①:GITHUB_TOKENではCopilotをアサインできない
まずは素直に、GitHub Actions標準のGITHUB_TOKENを使ってgh CLIからCopilotをアサインしようとした。
gh issue edit <number> --add-assignee "@copilot"
しかし、実際にはCopilotをアサインすることができない。
これはCopilotの割当てにCopilotのライセンスが必要になるため。
そのためIssueテンプレートのassignees欄に@copilotを指定しても、現在はcopilotを自動アサインすることはできないが、将来的にもCopilotのライセンスを保持していないユーザーがIssueを作成したときには、@copilotをアサインすることはできないと考えられる。
調査結果②:GitHub App+user-to-server token案
「個人のPATを使いたくない」という観点から、次に検討したのがGitHub Appを使う案だった。
GitHub Appでできること
GitHub Appには大きく2種類のトークンがある:
-
インストールトークン(installation access token)
- Appがインストールされているリポジトリに対して、Appとしてアクセスするトークン。
- これはユーザーには紐づかない。
-
ユーザーアクセストークン(user access token / user-to-server token)
- Appが「特定ユーザーの代理」としてAPIを叩くためのトークン。
- OAuthフローを通してユーザーがAppを承認する必要がある。
CopilotのAPI利用では、この2番目のuser access tokenが「ユーザートークン」として利用できる。
GitHub App+user-to-server tokenの構成
Copilotを扱うためにGitHub Appを使う場合、典型的な構成は以下のようなものになる:
-
GitHub Appを作成し、Issue操作に必要な権限(issues: read/writeなど)を付与する。
-
Copilotライセンスを持つユーザーで、AppのOAuthを一度だけ承認する。
-
そのときに取得できるrefresh tokenを安全なストレージ(DB, Key Vaultなど)に保存する。
-
Azure FunctionsやCloud Runなどの小さなバックエンドを用意し:
- refresh tokenから最新のuser access token(
ghu_...)を発行 - GitHub Actionsからのリクエストに応じて一時トークンとして返す
- refresh tokenから最新のuser access token(
-
GitHub Actionsのワークフローでは、バックエンドから受け取ったuser access tokenを
GH_TOKENに流し込んでgh issue edit --add-assignee "@copilot"を実行する。
この案の課題
機能的には成立するが、問題は以下:
- バックエンドを運用する必要がある
- GitHub AppのOAuth / refresh token / access tokenまわりを自前で正しく実装・監査しなければならない
- 「Copilotをアサインするだけ」の用途に対しては、ややオーバーエンジニアリング感が強い
このため、今回はGitHub App方式は見送り、よりシンプルなPAT方式を採用することにした。
Discussion