はじめに
こんにちは。
フューチャーアーキテクト株式会社、TIG/EXユニット所属の宮永です。
※TIG(Technology Innovation Group)はテクノロジーカットでお客様の課題解決を行う部門です。
中でもEX(Energy Transformation)ユニットは2022年に新設されたエネルギー業界特化型のコンサルティング集団で、「エネルギー×テクノロジー」をコンセプトにエネルギーサプライチェーン全体での需給の最適化やレジリエンス強化を図り、地域の活性化やビジネスモデルを変革することで透明性の高いフェアなマーケット形成を目指します。
本記事ではCircleCIでGitHubのPR作成時の負荷を軽減するために、PR作成者の自動アサインおよびラベルの付与を自動化した話をご紹介します。
経緯
CircleCIでGitHubのPullRequest作成時の負荷を軽減したいと思った経緯について説明します。
私が所属するチームのブランチモデルは簡易的なgit-flowモデルに則っており、main
、develop
、feature
の3つのブランチで運用しています。
デフォルトブランチをdevelop
として、改修する時はdevelop
ブランチからfeature
ブランチを切ります。改修が完了したらfeature
→develop
ブランチにマージして、リリースするタイミングでdevelop
→main
ブランチにマージします。
最近まで、リリースするときにはdevelop
→main
へのPullRequestを手動作成する運用を行っていましたが機械的な作業なのでgit-pr-releaseを使って自動化しました。
git-pr-releaseの導入はこちらのSongmuさんの記事が非常に参考になりました。
余談にはなりますが、弊チームはSongmu/flextimeのヘビーユーザーであり、非常にお世話になっております。時刻操作系のGoのテストをする時はflextimeが欠かせません!
git-pr-releaseの導入に合わせてGitHubの標準機能であるリリースノート自動生成も導入しました。
以下のymlファイルをリポジトリの.github
配下に格納するだけでリリースノートを自動生成できます。
# .github/release.yml |
release.ymlについて少し説明します。-title
と-label
タグが必須項目であり、-title
にはリリースノートのセクションを、-label
にはそのセクションに記載するPullRequestのラベルを記載します。
例えば、前回リリース時から今回のリリースまでにmain
にとりこまれたenhancement
ラベルをもつPullRequestはすべてExciteing New Featuresのセクションに記載されるようになります。
release.ymlを作成したらリリース時にGenerate release noteを押下するだけでリリースノートが自動生成されます。
GitHub標準機能を用いずにtagのPUSHをトリガーにCircleCIで自動化する場合は当技術ブログの過去記事が参考になると思います。
今回、「CircleCIでPullRequest作成時の負荷を軽減したい」と思った経緯ですが、このリリースノートの自動生成が背景にあります。
既に記載したように自動生成したChangeLogはPullRequestのラベルに依存しているため、きちんと運用をまわすには、メンバー全員にラベルの付与を徹底させる必要があります。
この「きちんとラベルを付与する」というのは簡単な作業に思えますが案外忘れてしまいがちです。せっかくリリースノートの自動生成まで行ったのですから、ラベルの付与も自動化してしまいたいと思い、CircleCIベースでラベルの付与を自動化しました。
ラベルの振り分け方
さて、ラベルの振り分け方ですがいくつか方法が考えられます。例えば特定のディレクトリの変更に依存してラベルを付与する方法です。
これを実現するにはactions/labelerを利用するのが最も導入コストが低いと思います。
他にはブランチ名に依存してラベルを振り分ける方法なども考えられます。今回私が採用したのはブランチ名に依存してラベルの振り分けを行う方法です。
ブランチ名ベースでラベルを振り分ける方法を採用したのは、弊チームのリポジトリが複数サービスが含まれたモノリポ構成であることが大きな理由です。
一部機能は同じ階層のファイルを共有していたりするため、果たして改修部分がservice Aの改修なのか、service Bの改修なのかはコードを見ないと判断できません。ブランチ名ベースでラベルの振り分けを行えば正確にラベルを付与できます。
そこで、「actions/labelerにそんな機能搭載されていないかな?」と思い、確認しましたが2020年にIssue#54が起票されてから2023年現在もOpenのままで、簡単に導入とはいかないようです。
加えて、諸事情がありGitHub ActionsではなくCircleCI上に導入したかったので、actions/labelerの導入は見送りました。
GitHub CLIの利用
どうやら、自前でGitHubAPIを操作する必要が出てきそうでしたので、まずはGitHub CLIでラベルの付与操作などがサポートされていないかを調査したところ、それらしい機能がサポートされていることがわかりました。
GitHub CLIをインストールして、以下コマンドを実行することでPullRequestを操作できます。
gh pr edit [<number> | <url> | <branch>] [flags] |
[<number> | <url> | <branch>]
を空のまま実行した場合、現在チェックアウトしているブランチに対して実行されます。
flags
には以下オプションがサポートされています。
--add-assignee <login> |
今回利用するのは--add-label
です。
CircleCIの設定
GitHub CLIでなんとかなりそうなことが判明しましたので、あとはCircleCIでの実行環境です。
利用者の多そうなツールなのでOrbsで環境が提供されていないかなと思い探してみたところ、最適な環境を見つけました。circleci/github-cli
あとは、このOrbsを利用してGitHub CLIコマンドを実行するだけです。
以下、設定ファイルです。
Orbsとは
OrbsはCircleCI 2.1で追加された機能で、CircleCIの設定を再利用可能なパッケージとして提供したものです。
Slack連携などは利用している方も多いのではないでしょうか。Slack連携のOrbs
# .cicleci/config.yml |
-gh/setup
でGitHub CLIの初期設定を行います。この際のCicleCIの環境変数にGITHUB_TOKEN
の設定が必要です。
GITHUB_TOKENの権限
GITHUB_TOKENの権限はPullRequestに対して操作を行うためrepoの権限が必要です。GITHUB_TOKENのアクセス許可
GitHub CLIのセットアップ完了後ブランチにチェックアウトします。
その後GitHub CLIのコマンドを記載したShellスクリプトを実行しています。
以下、実行対象のShellスクリプトです。
|
GitHub CLIを利用することで複雑なスクリプトを書かずにすみました。
ラベルの自動付与のついでにAssigneesにPullRequest作成者の付与も自動化しています。
ブランチ名やPullRequest作成者の情報はgh pr viewコマンドで取得します。とても便利なことに--jq
オプションでフィルタリングできます。
-c, --comments |
試しに、gh pr view --json author
を実行してみると、以下のレスポンスを取得できます。
❯❯❯ gh pr view --json author |
これをjq
をつかってフィルタリングしてauthor
変数に代入するには以下のようにします。
author=$(gh pr view --json author --jq .author.login) |
--json
オプションはカンマ区切りで複数指定ができますので以下のようにして1回のリクエストにまとめることができます。
prinfo=$(gh pr view --json author,headRefName --jq .author.login,.headRefName) |
あとは事前に設定してあるラベル名にブランチ名が合致しているかを確認して文字列一致していればPullRequestにラベルを付与していきます。
Shellスクリプト初心者のため、こちらの記事を参考にさせていただきました。
set "${labels}" |
動作確認
CircleCIのOnly build pull requests
今回CircleCIの発火はPullRequestが作成されている状態を想定しています。そのためリリースフローに支障がない場合はこちらに記載のOnly build pull requestの設定をONにすることをおすすめします
▼成功すると以下のようにPR作成時にブランチ名にしたがってラベルの付与とPR作成者の自動アサインができます
GitHubアカウントのユーザー名
add_label.shでは、author.nameがスペースで区切られていないことを想定しています。
アカウント名にスペースが含まれる場合は、author.nameを別にリクエストして変数に格納するなどしてください。
少しハマったところ
circleci/github-cliの- gh/setup
は何も指定しないとGitHub CLIのデフォルトバージョンは2.3.0です。
記事執筆時の2023年2月18日にローカルにインストールされていたGitHub CLIは2.23.0でした。
❯❯❯ gh --version |
どうやらバージョン2.3.0ではgh pr view --json author
のレスポンスにname
という属性はなかったようで、ローカルのバージョンとの差分に気づかずにPullRequest作成者の情報の取得ができずに悩んでいました。(スクリプトではnameではなく、loginで取得しています)
バージョン情報を事前に確認しておくことは大事ですね。- gh/setup
にはversion
を指定できるので、最新のバージョンを確認しつつ指定してください。
- gh/setup: |
おわりに
今回、諸事情がありGitHubActionsではなくCircleCIで実装しましたが、GitHubActionsであればGitHub CLIはプリインストールされているので本記事よりも簡単に導入できます。
まだ自動化の運用を初めて日が浅く、今後運用を続けていく中で改善点などでてくるかと思いますが、現状では満足しています。
開発体験の向上は生産性の向上に直結すると思っていますので、今後も機械的な作業は積極的に自動化していきたいです。