😎

GitHub ActionsからGitHub CopilotをIssueに自動アサインする

に公開

背景

  • GitHub CopilotのCoding Agent機能を使い、IssueをCopilotに投げて自動対応させたい。

  • 具体的には:

    • 特定の条件を満たすIssueが作成されたタイミング、あるいは手動でワークフローを実行したタイミングで、
    • @copilotをassigneeに追加し、Coding Agentを起動したい。

解法

  1. Copilotのライセンスを保持するユーザーのPATをGitHubのシークレットに保存する
  2. GitHub Actionsのワークフローでgh CLIを使い、Issueに@copilotをアサインする

実装手順

1. Fine-grained PATの発行

  1. GitHubにログイン
  2. Settings→Developer settings→Personal access tokens→Fine-grained tokensから新規トークンを作成
  3. 対象リポジトリを限定して選択する
  4. 権限(Permissions)は最低限:
    • Repository access:
      • Issues: Read and write
      • Metadata: Read
      • (必要に応じて)Copilotの実行に必要な他の権限を追加
  5. トークンを発行し、この文字列を安全な場所にコピーしておく(あとから再表示はできない)

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種類のトークンがある:

  1. インストールトークン(installation access token)

    • Appがインストールされているリポジトリに対して、Appとしてアクセスするトークン。
    • これはユーザーには紐づかない。
  2. ユーザーアクセストークン(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を使う場合、典型的な構成は以下のようなものになる:

  1. GitHub Appを作成し、Issue操作に必要な権限(issues: read/writeなど)を付与する。

  2. Copilotライセンスを持つユーザーで、AppのOAuthを一度だけ承認する。

  3. そのときに取得できるrefresh tokenを安全なストレージ(DB, Key Vaultなど)に保存する。

  4. Azure FunctionsやCloud Runなどの小さなバックエンドを用意し:

    • refresh tokenから最新のuser access token(ghu_...)を発行
    • GitHub Actionsからのリクエストに応じて一時トークンとして返す
  5. 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