Github Actionsでリリース作業を自動化してみた

# はじめに
ラクスパートナーズの寺澤 歩希と申します。
普段は主にデータ分析基盤の構築を行なっています。

この記事は、[ラクスパートナーズ AdventCalendar 2023](https://qiita.com/advent-calendar/2023/rakus-partners)の11日目の記事となります。

# この記事の背景
この記事では、最近職場で業務改善した内容について、整理も兼ねて書いていこうと思います。

現在の業務では、Githubを使ってソースコードを管理しています。
2日に1回程度、本番環境に新機能をリリースするのですが、以下のような手作業が発生していました。
- 承認者に分かりやすいように、マージ済みのPullRequest(以下、PR)のリンクやタイトルを書く
- リリース用PRが開いている時に、マージ元のブランチに新しいPRがマージされた時、追記する必要がある


そこで、Github Actionsを使ってこの面倒だったリリース作業を自動化する機能を、業務の隙間時間に実装してみました。

# Github Actionsとは
Github Actionsについて、超ざっくりと説明すると、
『github上の何かしらのイベントをトリガーとして、何かしらのActionを作用させることができる』、Githubが提供する機能です。
いわゆる、CI/CDツールです。
[公式ドキュメント](https://docs.github.com/ja/actions/learn-github-actions/understanding-github-actions)

よくあるユースケースとしては、
- プッシュした時に、コードにLintをかける・ユニットテストを走らせる
- 本番ブランチにマージ後、自動デプロイ

などでしょうか。

今回は、
『mainブランチ宛てのPRの作成・更新』をトリガーとし、
『PRのタイトル・本文を自動作成・更新』するGithub Actionsを作りました。

# ブランチモデルと要件
以下のような単純なブランチモデルを想定しています。
![IMG_2222.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969543/3dc70872-1d79-85ca-5e9c-1277fc0489cc.jpeg)

- mainブランチ：本番環境のブランチ
- developブランチ：開発の主軸ブランチ
- featブランチ：開発者作業用のブランチ

開発作業の流れは以下です。
1. mainブランチからdevelopブランチを切る
2. developブランチから、実装する機能ごとにfeatureブランチを切る
3. 実装が完了したら、developブランチにマージ
4. リリースのタイミングで、develop -> mainのPRを作成


上記のような開発環境において、以下の要件を満たすような機能を実装しました。
- mainブランチへのPRを作成したとき、自動でタイトル・本文を更新する
- 本文には、developブランチにマージ済のPRのタイトル、リンクが記載されている
- developブランチにPRが新しくマージされた時、リリース用PRの本文にも追記する

# 成果物
実装の内容より先に、まずは成果物の紹介です。

タイトルや本文は特に触らずにmain宛てのpull requestを作成すると...
![IMG_3159.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969543/6fd206df-5074-71fe-610f-184d8304d066.jpeg)

アクションが起動し、タイトルが『Release <<実行日>>』に更新され、本文にマージ済のPRが表示されます。
またマージ元のブランチに新しいPRがマージされた時にも起動し、本文に自動で追加されます。

![IMG_3158.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2969543/3be0784b-6e89-37d1-6067-235ce66e3e68.jpeg)

# 実装したYAML
```.github/workflows/auto_pull_request.yml

name: Auto Release PR Body

on:
  pull_requests:
    - main
  types: [opened, synchronize, reopened]

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
  auto_update_pull_requests:
    runs_on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth:0

      - name: Set current datetime as env variable
        env: 'Asia/Tokyo'
        run: |
          echo "current_date=$(date + '%Y-%m-%d')" >> $GITHUB_ENV
 
      - name: Update Pull Request Title
        run: |
          gh pr edit ${{ github.event.pull_requests.number }} \
          --title "Release ${current_date}"

      - name: Update Pull Request Body
        uses: technote-space/pr-commit-body-action@v1.7.3
        with:
          MAX_COMMITS: '10'
          TITLE: "### Changes"
```

次セクションで、ステップごとに整理していきます。





# 各ブロックの解説
### トリガー部分
```.github/workflows/auto_pull_request.yml
name: Auto Edit Release PR

on:
  pull_requests:
    - main
  types: [opened, synchronize, reopened]
```
- `on`では、何をトリガーとするかを指定できます。
今回は、main宛てのPRが作成された時、更新された時（、再度openした時）としています。

[その他のトリガーについて](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#on)

### GITHUB_TOKENの設定
```.github/workflows/auto_pull_request.yml
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
- アクションがGithub APPにアクセスするためのトークン情報です。記述しておけば、アクションごとに自動生成してくれます。
後半で、ghコマンド（github cli）を使用するため、明記しておきます。


### jobの基本オプション
```.github/workflows/auto_pull_request.yml
jobs:
  auto_update_pull_requests:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
```
- `runs-on`では、アクションを実行するマシンを指定できます。
Githubが用意しているマシンの他に、自分で作成したランナー（[セルフホステッドランナー](https://docs.github.com/ja/actions/hosting-your-own-runners/managing-self-hosted-runners/about-self-hosted-runners)）を使用することもできます。
今回はシンプルなアクションなので、ubuntu-latestとしています。

- `permissions`は、アクションの権限をコントロールするために記述します。こちらは、リポジトリのSettingsからデフォルトで権限を付与することができますが、アクションごとに必要な権限を記載する方がセキュアな気がしています。
今回はアクションに、リポジトリの読み取り、プルリクエストの更新をさせるので、`contents: read`, `pull-requests: write`を付与しています。

### リポジトリのチェックアウト
```.github/workflows/auto_pull_request.yml
    steps:
      - name: Checkout
        uses: actions/checkout@v3
        with:
          fetch-depth:0
```
Github actionsのワーキングディレクトリに、リポジトリのソースコードをcloneする記述です。
Github actionsのお約束みたいな記述です。


### タイトル更新部分
```.github/workflows/auto_pull_request.yml
      - name: Set current datetime as env variable
        env: 'Asia/Tokyo'
        run: |
          echo "current_date=$(date + '%Y-%m-%d')" >> $GITHUB_ENV
 
      - name: Update Pull Request Title
        run: |
          gh pr edit ${{ github.event.pull_requests.number }} \
          --title "Release ${current_date}"
```
- 1つ目のstepで、アクションが動く日を『YYYY-mm-dd』の形でcurrent_dateという変数に格納しています。
後半の`>> $GITHUB_ENV`の記述は、github環境変数ファイルに書き込む処理です。こうすることで、後続のstepで変数を呼び出すことができます。

- 2つ目のstepでは、ghコマンドを使用し、PRのタイトルを変更しています。また、1つ目のstepでGITHUB_ENVに格納した変数を呼び出しています

### 本文更新部分
```.github/workflows/auto_pull_request.yml
      - name: Update Pull Request Body
        uses: technote-space/pr-commit-body-action@v1.7.3
        with:
          MAX_COMMITS: '10'
          TITLE: "### Changes"
```
肝心の本文更新部分は、[既存のアクション](https://github.com/technote-space/pr-commit-body-action)を利用させてもらいました。
このアクションは、本文に下記の記載がある場合に働き、STARTとENDで囲まれた部分に、マージ済のPR・コミットが表示されます。
```
<!-- START pr-commits -->
<!-- END pr-commits -->
```
本文作成の度に、上記の記載をしているようでは自動化の恩恵が薄いため、GithubのPRテンプレートを活用することにしました。

Githubでは、`PULL_REQUEST_TEMPLATE.md`という名前のmarkdown形式のファイルを用意しておくことで、PR作成時にデフォルトで本文を記載してくれます。（[参考](https://docs.github.com/ja/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository)）

```PULL_REQUEST_TEMPLATE.md
# Release Request
<!-- START pr-commits -->
<!-- END pr-commits -->

### リリースタイプ
...
..
.
```
このテンプレートの中に、先述の`<!-- START pr-commits --> ~~`の記述を埋め込んでおくことで、毎回記載することなく、PRの自動更新を実現しています。

# 最後に
基本構文すらも知らない状態で実装を進めたので、かなり手探りでしたが、
今回の実装でGithub Actionsの基本は学べたかなと思います。

（追記）
今記事を書き終わったくらいに、今回の実装を超簡単に実現できる既存のActionsがあることを知りました。。。
しかし、自分で実装したおかげで理解が深まったので、後悔とかは全くありません（泣）

Github Actionsでできることはまだまだ沢山あるので、今後も研究を続けていきたいです。

# 実装の際参考にしたリスト
- Github Actions公式ドキュメント：https://docs.github.com/ja/actions/learn-github-actions/understanding-github-actions
- permissionsについて：https://zenn.dev/not75743/scraps/926f2693809744
- Github Cliについて：https://cli.github.com/manual/