GitHub Actionsを使用してbundle update自動実行→PRを自動作成

# 概要
- CircleCIを使用して週1で自動実行していたbundle updateを、GitHub Actionsに移行した際に行ったことのメモ
- CircleCIを使用していたときは[circleci-bundle-update-pr](https://github.com/masutaka/circleci-bundle-update-pr)というGemを使用させていただき、bundle update自動実行→プルリクエスト自動作成を実現していた
- [circleci-bundle-update-pr](https://github.com/masutaka/circleci-bundle-update-pr)は、名前の通りCircleCIでの使用を目的に作成されているように見受けられたGemだが、READMEを見ていたらGitHub Actionsで動かすためのexampleも記載されていた
    - https://github.com/masutaka/circleci-bundle-update-pr?tab=readme-ov-file#run-on-github-actions
- Dependabot等の別ツールへの移行コストや運用コストを考えたときに、こちらを使用し続けるほうが良いという判断に至ったため、GitHub ActionsでもこちらのGemを引き続き使用させていただくことにした

作成した結果、以下のようなbundle updateを行ったプルリクエストを毎週決まった日時に自動作成できるようになっている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/990312/5a272215-9178-f5b1-be7e-66dbdd01fdfa.png)


以下詳細を記載

# 作成したワークフロー
- exampleでも十分動くので大した変更はしていないが、幾つか変更した箇所はあるので以下に記載
```bundle-update-pr.yaml
name: bundle-update-pr

on:
  schedule:
    - cron: "00 22 * * 3" # JST 07:00 (Thu)

jobs:
  create_bundle_update_pr:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: libgsl-dev Install
        run: |
          if ! dpkg -l | grep -q "libgsl-dev"; then
            echo "Package not found. Installing..."
            sudo dpkg -i vendor/packages/gsl_2.3-1_amd64.deb
          else
            echo "Package already installed. Skipping installation."
          fi

      - name: Get Ruby Version
        id: ruby
        run: echo "ruby-version=$(cat .ruby-version)" >> $GITHUB_OUTPUT

      - name: Set up Ruby
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ steps.ruby.outputs.ruby-version }}

      - name: Install dependencies
        run: |
          set -x
          gem install -N bundler circleci-bundle-update-pr

      - name: Set timezone to Asia/Tokyo
        run: |
          set -x
          cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

      - name: Create GitHub Apps Token
        id: github_apps
        uses: actions/create-github-app-token@v1
        with:
          app-id: ${{ secrets.APP_ID }}
          private-key: ${{ secrets.PRIVATE_KEY }}

      - name: run circleci-bundle-update-pr
        run: |
          set -x

          export CIRCLE_BRANCH=$(echo $GITHUB_REF | sed -e 's!refs/heads/!!g')
          export CIRCLE_PROJECT_USERNAME=$(echo $GITHUB_REPOSITORY | cut -d "/" -f 1)
          export CIRCLE_PROJECT_REPONAME=$(echo $GITHUB_REPOSITORY | cut -d "/" -f 2)

          circleci-bundle-update-pr "${GIT_USER_NAME}" "${GIT_USER_EMAIL}"
        env:
          GITHUB_ACCESS_TOKEN: ${{ steps.github_apps.outputs.token }}
          GIT_USER_NAME:       "YOUR USER NAME"
          GIT_USER_EMAIL:      "YOUR USER EMAIL"
```

## Get Ruby Version
```yaml
- name: Get Ruby Version
  id: ruby
  run: echo "ruby-version=$(cat .ruby-version)" >> $GITHUB_OUTPUT
```
- `ruby/setup-ruby@v1`で使用するruby-versionは固定ではなく、アプリケーションの`.ruby-version`のバージョンに準拠するようにしたかったため、バージョンを取得するステップを追加

※追記→コメント欄で@takaram様にご指摘いただきましたが、`ruby/setup-ruby`はバージョン指定しなければ自動で`.ruby- version`ファイルを読んでくれるとのこと
https://github.com/ruby/setup-ruby#supported-version-syntax

ご指摘いただありがとうございます！

## Create GitHub Apps Token

```yaml
- name: Create GitHub Apps Token
  id: github_apps
  uses: actions/create-github-app-token@v1
  with:
    app-id: ${{ secrets.APP_ID }}
    private-key: ${{ secrets.PRIVATE_KEY }}
```
- このワークフローが適用されるアプリケーションは、ブランチにpushが発生した場合にRspecや静的解析が回るという別のワークフローが実装されており、このワークフローを通過しないとブランチをマージできない仕様になっている
- ただ、デフォルトのままこのGemを使用して作成されるプルリクエストは、作成者が`github-actions`というbotになり、botの場合、別のCIをキックしないという仕様があったため、このテストワークフローを回すことができず、bundle updateのプルリクエストをマージすることもできなかった
    - 参考: [botにpushされてもGithub Actionsが動かない件 | UMIHICO BLOG](https://umihi.co/blog/20221019-run-gh-as-actual-user-instead-of-github-actions-bot-in-actions)
- そのためGitHub Appsトークンを作成して、そのトークンをアクセストークンとして渡すことで、作成者をbotではなく開発者自身としてプルリクエスト作成を実行できるようにした
    - [actions/create-github-app-token: GitHub Action for creating a GitHub App Installation Access Token](https://github.com/actions/create-github-app-token)というアクションを使用することで簡単に作成できる
    - 詳しいGitHub Appsトークンの作成方法は割愛
    - Personal Access Tokenはセキュリティ的に非推奨っぽいので使用しなかった
- GitHub Appsトークンを渡した結果、作成者が`github-actions`という名前から渡したトークン名(ここではnitta-test-2)に変化していた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/990312/89364aee-86cf-b5d7-a375-50ae46d18622.png)

## libgsl-dev
```yaml
- name: libgsl-dev Install
  run: |
    if ! dpkg -l | grep -q "libgsl-dev"; then
      echo "Package not found. Installing..."
      sudo dpkg -i vendor/packages/gsl_2.3-1_amd64.deb
    else
      echo "Package already installed. Skipping installation."
    fi
```
- 動かしている環境では特定のDebianパッケージファイルがないとbundle installが動かないため追加