現在、GitHubでは複数のIssueテンプレートを作成することができますが、複数のPull Requestテンプレートを作ることはできません。
コメントアウトを活用して、うまく誤魔化す手法などが取られますがそうすると、テンプレートが肥大しがちです。
そこで、今回はRailsアプリケーションのmigrationを例に、GitHub Actionsを使ってdescriptionに加筆することで肥大化を解決してみましょう。
今回加筆したいもの
db/schema.rbが更新された時に、下記をdescriptionに追記するものとします。
## Migration list
- Migration time: s
- Record size:
Migrationにかかる時間と、レコードサイズを記入する部分をDescriptionに追記するというわけですね。(レコードサイズは本来カラムやインデックスの追加・削除時だけで良さそうですが、今回はそこが本題ではないので考えないこととする)
作成したもの
下記のymlファイルです。
name: Add Migration list
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- 'db/schema.rb'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
add_migration_lists:
name: Add migration lists to description of pull request
runs-on: ubuntu-latest
outputs:
replaced_description1: ${{ steps.get_description.outputs.replaced_description }}
steps:
- name: checkout
uses: actions/checkout@v3
- name: Get current pull request description
id: get_description
run: |
DESCRIPTION=$(gh pr view ${{ github.event.pull_request.number }} --json body --jq .body)
REPLACED_DESCRIPTION=$(echo $DESCRIPTION | sed 's/\n/;;;:::;;;/g')
echo "replaced_description=$REPLACED_DESCRIPTION" >> $GITHUB_OUTPUT
- name: URL to Pull Request description
if: contains(steps.get_description.outputs.replaced_description, '## Migration Lists') == false
run: |
DESCRIPTION=$(echo $REPLACED_DESCRIPTION | sed 's/;;;:::;;;/\n/g')
gh pr edit ${{ github.event.pull_request.number }} --body "$DESCRIPTION
## Migration Lists
- Migration time: s
- Record size: "
env:
REPLACED_DESCRIPTION: ${{ steps.get_description.outputs.replaced_description }}
特定のファイル変更が起きたときにだけワークフローが走るようにする
まず、db/schema.rb
に変更が起きたときだけ走るようにします。
下記のような記述で、PRをOpenしたとき、Pull Requestが追跡しているブランチがPull Requestのソースブランチと同期されたとき、再度Openしたとき、Draftから変更した時をトリガーとしています。
name: Add Migration list
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
paths:
- 'db/schema.rb'
Pull Requestのdescriptionを取得して一時保存するr。
まず、現在のPull Requestのdescriptionに追記する形を取るので、現在のPull Requestの情報を取得しましょう。
checkoutでリポジトリのソースコードを引っ張ってきた後に、ghコマンドを利用してpull requestの情報を取得します。
DESCRIPTION=$(gh pr view ${{ github.event.pull_request.number }} --json body --jq .body)
--json body
でdescriptionを取得し、--jq .body
でjson形式になっているのを平文に直しています。
また、このテキストは次のステップで使うので一時保存しましょう。
outputs:
replaced_description1: ${{ steps.get_description.outputs.replaced_description }}
この記述で、idがget_description
のステップで、replaced_descriptionとして保存したものを別ステップで ${{ steps.get_description.outputs.replaced_description }}
のような記述で取り出せます。
格納はecho "outputs.の後に指定した文字列=格納したい文字列" >> $GITHUB_OUTPUT
の形式で行います。
格納する際、sedで置換していますが、これはoutputs
を使うためには一行にする必要があるためです。
containsを使って何度もMigration listsを作らないようにする
さて、更新する前にまずPull RequestにMigration listsが既に作られてないかチェックします。
- name: URL to Pull Request description
if: contains(steps.get_description.outputs.replaced_description, '## Migration Lists') == false
runなどの前にifを置いて条件式を書くわけですが、今回は## Migration Lists
という文字列がなかったらとします。
否定はcontainsの場合は contains(捜索する文字列, 含まれてるか確認したい文字列) == false
形式で書きましょう。 !contains
のような形式で書いたりしても普通にエラーになります。
descriptionの更新をする
それでは、実際に更新をしていきましょう。まずはenvから先ほど格納した値を呼べるようにします。
env:
REPLACED_DESCRIPTION: ${{ steps.get_description.outputs.replaced_description }}
まず、再度sedで改行が置換された文字列を再度置換しなおします。
その後、ghコマンドで、今度はPRを更新するためのコマンドを打ちます。 --bodyオプションでdescriptionを更新することができます。
run: |
DESCRIPTION=$(echo $REPLACED_DESCRIPTION | sed 's/;;;:::;;;/\n/g')
gh pr edit ${{ github.event.pull_request.number }} --body "$DESCRIPTION
## Migration Lists
- Migration time: s
- Record size: "
まとめ
今回は特定条件でPull RequestのDescriptionを更新するというスクリプトを書いてみました。
GitHub Actionsではghコマンドを組み合わせることでPRを作成したり、編集したりかなり色々とできるので、是非何かやりたいことがあれば自作してみてください。