PRを出したらformatterを実行させるようにしよう[GithubActions]

# actions-diff-pr-managementとは？

PRに対して、formatterを実行した結果をPRにするGithub Actionsです。

https://github.com/dev-hato/actions-diff-pr-management

# actions-diff-pr-managementを使うメリット
VSCode等のエディタやIDEで保存時にformatterを実行することはできると思います。
しかし、エディタによってそれを行えなかったり、設定がしっかりできていなかったりしてformatterが意味をなさない時があります。

その際にGithubActionsでformatterを回すことができるのですが、もしかしたらformatterがおかしな結果を出してきてそれを上書きしてくるかもしれません。

それを防ぐためにPRを作成して`changes file`で見えるようにすることで、安全にformatterを機能させるために`actions-diff-pr-management`を使用します。


# やり方
今回は`tbls`というデータベース生成ツールを使った結果をPRとして出してみようと思います。

tblsに関する記事はこちらです。

https://qiita.com/maooz4426/items/44a71129ce2f0a463817

## actionsに権限を与えよう
actionsでPRを作成するためにGithubの設定を行う必要があります。

リポジトリの`setting/actions/general`の下の方に権限を与える項目があるので下のように設定しましょう。

![スクリーンショット 2024-11-23 20.50.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/a5c935a8-7b0d-bfe9-66b6-481431eec906.png)


## Github Actionsのworkflowを準備する

`./.github/workflows/`に下のようなymlファイルを書きます。

```tbls.yml
name: tbls-gen

on:
  pull_request:
    types:
      - opened
      - synchronize
      - reopened
      - closed # 元のPRを閉じた際に本Actionsが出したPRを自動的に閉じるために必要 (このtypeの場合は本Actionsのstepのみ実行する)

jobs:
  gen:
    name: tbls-gen
    permissions:
      contents: write
      pull-requests: write
    runs-on: ubuntu-latest
    timeout-minutes: 10
    services:
      mysql:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: root
    steps:
      - name: checkout
        uses: actions/checkout@v4.2.2
      - name: Set up Go
        uses: actions/setup-go@v5.1.0
        with:
            go-version-file: 'go.mod'
            cache: false
            check-latest: true
        id: go
      - name: Ensure go.mod is tidied
        run: go mod tidy
      - name: install sql-migrate
        run: go install -v github.com/rubenv/sql-migrate/sql-migrate@latest
      - name: mysql wakeup
        run: |
          until (echo 'SELECT 1' | mysql -h 127.0.0.1 -P 3306 -uroot --silent &> /dev/null); do echo "waiting for mysql to be connectable" && sleep 2; done
      - name: mysql migrate for tbls
        run: |
          mysql -h 127.0.0.1 -P 3306 -u root -e "CREATE DATABASE IF NOT EXISTS db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin"
          sql-migrate up -env="ci"
      - name: install tbls
        uses: k1low/setup-tbls@v1
      - name: run tbls
        run: |
          TBLS_DSN=mysql://root:@localhost:3306/db tbls doc --rm-dist --config .tbls.yml
      - name: fix tbls
        uses: dev-hato/actions-diff-pr-management@v1
        with:
            github-token: ${{ secrets.GITHUB_TOKEN }}
            branch-name-prefix: fix-tbls

```

## ymlについての説明

onの配下にactionsのトリガーを書いています。
今回はPRを出した時をトリガーにしています。
```yml
on:
  pull_request:
    types:
      - opened
      - synchronize
      - reopened
      - closed 
```

jobsでactionsのjobを設定しています。
genというjobを設定しています。
```yml
jobs:
  gen:
```

permissionsは、`GITHUB_TOKEN`を使用するアクションに対して何を許可するかを設定しています。
今回はコードを書く、PRを作成する許可を与えています。
```yml
permissions:
      contents: write
      pull-requests: write
```

jobを動かすOSを設定しています。

```yml
runs-on: ubuntu-latest
```

タイムアウトの時間を設定しています。
```yml
timeout-minutes: 10
```

mysqlのコンテナをactions内で立ち上げています。
```yml
services:
      mysql:
        image: mysql:8.0
        ports:
          - 3306:3306
        env:
          MYSQL_ALLOW_EMPTY_PASSWORD: yes
          MYSQL_DATABASE: root
```

steps配下からは、jobで実行する各処理を記述できます。

checkoutを使って、actions内にリポジトリの内容をクローンします。
```yml
- name: checkout
  uses: actions/checkout@v4.2.2
```

goの環境をセットアップしています。
```yml
- name: Set up Go
  uses: actions/setup-go@v5.1.0
  with:
    go-version-file: 'go.mod'
    cache: false
    check-latest: true
  id: go
```

goのモジュールの依存関係を整理します。
```yml
- name: Ensure go.mod is tidied
  run: go mod tidy
```

データベースにテーブルを作成するためにマイグレーションを行うためのツールをインストールしています。
```yml
- name: install sql-migrate
  run: go install -v github.com/rubenv/sql-migrate/sql-migrate@latest
```

mysqlを起動させる処理を書いています。

mysqlをsilentモードでかつ標準出力が出ないように起動し、起動してるかの確認を'SELECT 1'で行っています。起動した場合0となるので、そうなるまでの間untilコマンドによる繰り返し処理で起動するまで待つようにしています。

```yml
- name: mysql wakeup
  run: |
    until (echo 'SELECT 1' | mysql -h 127.0.0.1 -P 3306 -uroot --silent &> /dev/null); do echo "waiting for mysql to be connectable" && sleep 2; done
```

データベース作成とマイグレーションを行っています。
```yml
- name: mysql migrate for tbls
  run: |
    mysql -h 127.0.0.1 -P 3306 -u root -e "CREATE DATABASE IF NOT EXISTS db DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin"
    sql-migrate up -env="ci"
```

action用のtblsをインストールしています。

```yml
- name: install tbls
  uses: k1low/setup-tbls@v1
```

tblsを走らせています。
```yml
- name: run tbls
  run: |
    TBLS_DSN=mysql://root:@localhost:3306/db tbls doc --rm-dist --config .tbls.yml
```

`actions-diff-pr-management`を使ってフォーマッタの結果をPRとして作成するようにしています。
```yml
- name: fix tbls
  uses: dev-hato/actions-diff-pr-management@v1
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}
    branch-name-prefix: fix-tbls
```

:::note
### GITHUB_TOKENとは
GithubのAPIにリクエストを行い、リポジトリの操作を行えるようにするためのトークンです。
:::

## 実行結果
実際にこれが成功すると下のようにPRが作成されます。
![スクリーンショット 2024-11-17 17.48.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/ba81ce25-1f0d-fdf4-cce0-b92ec80afd28.png)


PRをマージした際にフォーマッタの実行結果が保管されているブランチが残ってしまうので`settings`の`General`にある下の欄にチェックをつけておくのおすすめです
![スクリーンショット 2024-11-17 19.01.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3766230/00caa644-7986-dcfd-dbf4-38d7bdac2950.png)

ぜひ共同開発で使ってみてください!