【Unity】GitHubで保護されたブランチにコミットする

GitHubで保護されたブランチにコミットしたい事ってありませんか？そのやり方を解説します。

## ブランチの保護とは？

特定のブランチに直接コミットできないように[ブランチの保護ルール](https://docs.github.com/ja/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches)というものを設定することが可能です。例えば、自分も含めてすべてのユーザーに`main`ブランチへのコミットやマージができないように設定して、プルリエクエストのレビューを必須にします。そうする事で誤ってコミットしたりマージする可能性を半減させる事ができます。

## 参考リポジトリ

下記、リポジトリで実際に運用してます。

**紹介** 
GitHubアクションを使ったUnityパッケージのリリース自動化

- [パッケージマニフェスト](https://docs.unity3d.com/2022.3/Documentation/Manual/upm-manifestPkg.html)のバージョンを更新する
- リリースを生成する
- タグを作成する
- [Unity Test Framework (旧 Test Runner)](https://docs.unity3d.com/2022.3/Documentation/Manual/testing-editortestsrunner.html)でテストする
- パッケージの生成をする
- 生成したパッケージをリリースページにアップロードする

https://github.com/IShix-g/Unity-GitHubActions

## GitHub Appを使う

ブランチの保護には、Bypass listというものがあります。このBypass listに追加したアカウントは保護ルールをパスできます。ここにGitHub Appを設定し、GitHub Appからコミットする事で、ブランチの保護を回避し安全にリリースをおこなう事ができます。

- Repository admin (Allow for pull requests only): 自分は、プルリクエストのみパス
- App (Always allow): AppのPermissionの範囲内はパス

![rule.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/1d512c34-80e4-9bef-751c-7e4a5da4f796.jpeg)

## GitHub Appの生成

#### 生成ページを開く
1. 右上のアイコンをクリック
2. Settingsをクリック
3. Developer settingsをクリック

![github_app1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/a9a8a405-ee35-0dab-e34b-1baa90198149.jpeg)

#### 生成

New GiHub Appをクリック

![github_app2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/2bb7258a-bb8a-38ec-f86c-ba992ba5195e.jpeg)

GitHub Appを作成します。

- GitHub App nameに適当に入力、ユニークである必要があります
- Homepage URLに`http://localhost`と入力
- WebfookのActiveを選択解除する

Permissionsを下記のように指定。指定後保存してください。

| Permissions  |  Read and write |
|---|---|
| Administration  |  Read and write |
| Contents  | Read and write  |
| Metadata  | Read-only  |
| Pull requests  |  Read-only |

![github_app3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/c36fff86-d1a8-ed8f-dad9-de31baa37e94.jpeg)

## App情報を取得

生成したAppから必要情報を取得します。

### App IDを控える

App IDは、Repository secretsのBOT_APP_IDに設定します。

![github_app4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/aa54b02d-7f87-66ee-7643-6e60b4e6bc67.jpeg)

### Private keyの生成

`Generate a private key`から設定。ファイルがPCにダウンロードされます。
このキーは、Repository secretsのBOT_PRIVATE_KEYに設定します。

![github_app5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/9b2d2062-224d-200a-b7fc-fdaeeff8ddba.jpeg)


## Appのインストール

アカウントにAppをインストールします。

![github_app6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/63e65641-3289-ede2-e2d4-c302496b96b4.jpeg)


All repositoriesを選択してインストール実行 (対象リポジトリを選択する事も可)

![github_app7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/74ef5fd6-c517-bca6-d059-656d77badaa1.jpeg)

## リポジトリに設定する

### ルールの設定

設定したいリポジトリのブランチ保護ルールを開き、Bypass listにAppを設定してください。

`リポジトリ > Settings > Rules > Rulesets`  
![github_app8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/6b35deed-1c07-da1c-9727-85ff7b380ed2.jpeg)

### シークレットの設定

上記で取得したデータを`New repository secret`から設定します。

#### BOT_APP_ID

アプリのIDを設定  
**例)** 1130092

#### BOT_PRIVATE_KEY

PCにダウンロードしたアプリのシークレットの中身をコピペ  
**例)**
```
-----BEGIN RSA PRIVATE KEY-----
省略
-----END RSA PRIVATE KEY-----
```

`リポジトリ > Settings > Secrets and variables > Actions`  

![github_app9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/e6b28c37-04cd-7559-821b-2be4f40396ba.jpeg)

## コード

あとは、Appからコミットなどをおこなうように設定します。やり方は簡単で、Appトークンを生成して、そのトークンを`secrets.GITHUB_TOKEN`の代わりに渡します。

参考: [.github/workflows/reusable-update-packagejson.yaml](https://github.com/IShix-g/Unity-GitHubActions/blob/main/.github/workflows/reusable-update-packagejson.yaml)

```yaml
# Appトークンの生成
- name: Generate Token
id: app-token
uses: actions/create-github-app-token@v1
with:
  app-id: ${{ secrets.BOT_APP_ID }}
  private-key: ${{ secrets.BOT_PRIVATE_KEY }}

- uses: actions/checkout@v4
with:
  ref: ${{ inputs.ref }}
  persist-credentials: false #チェックアウトする時は指定する

- name: Push changes
uses: ad-m/github-push-action@master
with:
  # 生成したtokenを渡す
  github_token: ${{ steps.app-token.outputs.token }}
  branch: ${{ inputs.ref }}
  tags: false
```

場合によって、Git認証情報を設定する必要があります。
エラーが出る場合は、設定してください。(生成したトークンが必要です。)

参考: [.github/workflows/reusable-create-release.yaml](https://github.com/IShix-g/Unity-GitHubActions/blob/5ed54ca7b4ea36a05d8c17c102b5546647e17bda/.github/workflows/reusable-create-release.yaml#L83-L86)

```yaml
- name: Configure Git Authentication with Custom Token
run: |
  git config --global url."https://x-access-token:${{ steps.app-token.outputs.token }}@github.com/".insteadOf "https://github.com/"
```

## ブランチの保護をしていないのにエラーが出る場合

保護を設定していないのにPermissionエラーが出る場合、以下の設定を確認してみてください。

- リポジトリの`Settings > Actions > General > Workflow permissions`を開く
- Workflow permissionsをRead and write permissionsに設定

![settings_action.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389614/04a303b2-ff4c-aabc-5c86-31420ec56245.jpeg)