actionsでprivateなパッケージを取得する[actions/create-github-app-token]

go mod vendorについて調べてみた記事の中で`Personal Access Token(PAT)`を使用して一時的にprivateリポジトリの中を閲覧するができるようにしました。

https://qiita.com/maooz4426/items/67a738f060b8452c1a08

今回、そのような一時的なPATの発行で利用した`actions/create-github-app-token`について調べてみようと思います。

# actions/create-github-app-tokenとは

Github Appに`access token`をインストールさせることのできるactionです。

https://github.com/actions/create-github-app-token

Github Appとは、Githubの機能を操作することで、特別なユースケースでも対応できるように機能を拡張させることのできるツールです。
特定のニーズやワークフローに合わせて、GitHubの動作や表示をカスタマイズしたり、自動化したり、他のツールと連携させたりすることができます。

先述したactionを使うことで、Github Appにリポジトリの閲覧権限などを付与することができ、安全にGithub Appに権限を一時的に付与することができます。

# actions/create-github-app-tokenを使うメリット

## 1.一時的にaccess tokenを発行できる
まず、PATを発行してGithub Appに登録することがなぜ良くないのか説明します。

PATは、複数の権限を設定できるのと同時にExpireDateとして有効期限を設定できます。
ここでExpireDateに有効期限を設定した場合と無期限にした場合で2つ考えてみようと思います。

- 有効期限を設定した場合
有効期限を設定した場合、有効期限が切れた場合に手動でPATを発行し直す必要が出てきます。

- 無期限にした場合
無期限にした場合、有効期限を設定した場合と違い、メンテナンスの必要はなくなりますが、万が一PATが漏れた場合に悪用される可能性があります。
これに関してはもちろん有効期限内であった場合も同様です。

このように、PATの手動発行は、メンテナンスの難しさとセキュリティリスクという点で課題を抱えています。

`actions/create-github-app-token`を使用することで、有効期限が1時間の`access token`がworkflowの実行時に適宜自動発行されることになるので、再発行といったメンテナンスや有効期限を設定しなくてもよくなるので、手動発行よりも安全に発行することができます。

## 2.公式のactionとして利用することができる
`actions/create-github-app-token`が登場するよりも前にサードパーティー製のactionが登場していました。

https://github.com/getsentry/action-github-app-token

しかし、サードパーティ製だと公式のactionと比較して、セキュリティ的な面での信頼が低くなります。

なので、公式のアクションを使用することで信頼性が高く行うことができます。

# 使ってみる

## 1.Github Appの準備

`Developers settings`から`Github App`を選択し、`New Github App`からAppを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/feb50892-a8a6-4631-91b2-2a583ee22f2b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/eedfa4f8-6695-4fa2-a1ee-6bbe347a2bbb.png)


下のように該当Appを作ってみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/2d2ce775-7a2b-417c-9e6e-8aafad140c75.png)

Webhookはオンになっていますが、最初はいらないのでチェックは外します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/c3620edb-ca1c-4430-97b4-3e80b4de4802.png)

権限を設定します。
`contents`を`read-only`にします。
こうすることでrepositoryの中身を`GithubApp`が閲覧することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/27aa6c40-75b2-42d6-8e0c-493d3876160c.png)

ここまでできたら、`Create Github App`を選択します。
今回は個人用のアカウントでしか使わないので`Only on this account`を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/61399859-31c9-4d2c-83a1-5ddef7a6c7d5.png)

## 2.GithubAppのインストール
上でAppを作成した後、下のように作成したAppを該当リポジトリにインストールします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/14dd4805-1573-4972-b402-df721b950433.png)

>ダウンロードするモジュールが存在するリポジトリも追加しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/6540f2e6-4e78-4648-8796-a1dc8e13d522.png)


## 3.repositoryの設定
Github AppのIDをvariablesとして登録します。

IDは該当GithubAppの下の部分に書かれています。
![スクリーンショット 2025-06-15 22.43.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/f4c063f1-5303-47d1-a7d2-02fda1621420.png)

これをvariablesに設定します。
![スクリーンショット 2025-06-15 22.44.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/e7be754a-afa4-434c-883e-a659620cbd96.png)

次に秘密鍵を生成します。
これは`Developer Settings`から該当のGithub Appの`Edit`を選択し、下の方にスクロールすることで見つけることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/2cd27d27-1119-4cdd-9ac5-f508d8f82427.png)

秘密鍵は生成するとローカルにダウンロードされます。
catコマンドで秘密鍵が下の形式で表示されるのでそれをコピーします。
```
-----BEGIN RSA PRIVATE KEY-----

-----END RSA PRIVATE KEY-----
```

これをrepositoryのsecretsに保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/2e34be5a-099f-4f16-8ba2-2b8251f90769.png)

## 4.workflowを組む
実際にworkflowを組んでみます。

```yml:.github/workflows/build.yml
name: build
on:
  pull_request:
    types: [opened, synchronize, reopened]
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
      - uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e #v2.0.6
        id: generate-token
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.PRIVATE_KEY }}
      - name: Configure Git for private modules
        run: |
          git config --global url."https://x-access-token:${{ steps.generate-token.outputs.token }}@github.com".insteadOf "https://github.com"
        env:
          GOPRIVATE: github.com/maooz4426/*
      - name: Set up Go
        uses: actions/setup-go@d35c59abb061a4a6fb18e82ac0862c26744d6ab5
        with:
          go-version-file: "go.mod"
      - name: Install dependencies
        run: go mod vendor
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb
      - name: Build and push
        uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83
        with:
          context: .
          push: false  # PRなのでpushしない場合
          tags: |
            myapp:latest
            myapp:pr-${{ github.event.number }}
          cache-from: type=gha
          cache-to: type=gha,mode=max
```

今回紹介しているactionは下部になります。

```yml
      - uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e #v2.0.6
        id: generate-token
        with:
          app-id: ${{ vars.APP_ID }}
          private-key: ${{ secrets.PRIVATE_KEY }}
```

idの部分はこれを設定することでactionで作成されたaccess tokenを参照することができます。
```yml
steps.generate-token.outputs.token
```
withには、先ほど準備していた`APP_ID`と`PRIVATE_KEY`を参照させています。

そして下の部分でgoがprivateリポジトリを見れるように設定しています。
これは生成したaccess tokenをURLに含めることでみることのできるURLを`https://github.com`というエイリアスにあてています。
こうすることで`https://github.com`にアクセスしようとすると暗黙的に`https://x-access-token:${{ steps.generate-token.outputs.token }}@github.com`に置き換えて、goのモジュールをダウンロードできるようにしています。

```yml
      - name: Configure Git for private modules
        run: |
          git config --global url."https://x-access-token:${{ steps.generate-token.outputs.token }}@github.com".insteadOf "https://github.com"
```

こうすることで発行したAccess Tokenを使用してprivateリポジトリを閲覧することができます。

# まとめ
`actions/create-github-app-token` を活用することで、GitHub Actionsのワークフロー内でプライベートリポジトリへ安全にアクセスするためのアクセストークンを自動的かつ一時的に発行できます。

従来の`GITHUB_TOKEN` (リポジトリのスコープに限定される) ではなく、GitHub Appのアクセストークンを利用するケースは、プライベートリポジトリへの参照が必要なGitHub Actionsワークフローで特に有効な選択肢になると思いました。