はじめに
こんにちは、シックスティーパーセントでソフトウェアエンジニアをしているakktです。この記事を公開したら、即座に帰宅してポケモンSVをプレイする予定です。最初の一匹はニャオハにしたいですね。かわいいですし、夢特性がへんげんじざいの高速アタッカーということで、対戦環境でも活躍が期待出来そうです。
自分は普段シックスティーパーセントの裏側で動いている管理システムの開発をしているのですが、先日このシステムのリリースノートの作成をrelease-drafterを使って完全に自動化したので、今回はその取り組みについて紹介したいと思います。
ざっくりどういうモノなのか
GitHub上でmasterブランチに対してmergeが走った時に、Slackに以下のようなリリースノートが飛ぶようになっています。
シックスティーパーセントではブランチ運用にGitHub Flowを採用しているため、ブランチはmasterと各feature, fixブランチがあるのみです。developブランチやreleaseブランチは採用していません。
背景
入社して二週間ほど経ったある日、それまで開発していた機能が日の目を見ることになり、本番環境にデプロイしました。その後上司であるknchstにSlackにリリースノートを書くように頼まれ、書きました。当時書いていたのはこういう感じのやつです。
この作業には大きく分けてふたつの問題点があります。
第一に、前回デプロイされてからの正確な資源の差分が分からないということです。当時はリリースタグも打っておらず、デプロイも手動で行っていたため、前回のリリースからの正確な資源の差分が分かりませんでした。ほぼknchstの記憶頼みでリリースノートが書かれている状況でした。
第二に、面倒くさいということです。ラリー・ウォールが「怠惰 (Laziness)」という言葉で表現している通り、単純で退屈な作業を自動化することは我々ソフトウェアエンジニアにとっての至上命題です。また、面倒くさいが故にリリースノートが必ずしも書かれないという問題もありました。結果、デプロイ頻度にも影響していたと思います。
どうやったか
以下の技術を使用して自動化しました。
- release-drafter
- GitHub Actions
- github-action-required-labels
- Slack用Git Hubアプリ
最初はGitHubのAutomatically generated release notesを使って半自動で書ければいいや、位に思っていたのですが、どうやらrelase-drafterを使えば完全に自動化出来そうだったのでやってみることにしました。
やったこととしては、以下のふたつのファイルを追加しただけです。
.github/workflows/release-drafter.yml
name: Release Drafter
on:
push:
branches:
- master
permissions:
contents: read
jobs:
update_release_draft:
permissions:
contents: write
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: Generate CalVer version
id: calver
run: |
export VERSION=$"v$(date "+%Y%m%d%H%M%S")"
echo ::set-output name=version::${VERSION}
- uses: release-drafter/release-drafter@v5
with:
tag: ${{ steps.calver.outputs.version }}
name: ${{ steps.calver.outputs.version }}
version: ${{ steps.calver.outputs.version }}
publish: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
このファイルは、Actionで実行されるrelease-drafterの本体です。
ポイントとしては二点あります。
第一に、タグの採番です。幸運なことに、我々にとってSemantic VersioningはYAGNIなのでバージョニングには日時をそのまま使っています。Semantic Versioningが必要なのであれば、自動化へのハードルはかなり高くなります。そのリリースによってパッチが上がるのかマイナーが上がるのか、あるいはメジャーが上がるのかをActionに教えるのが困難であるためです。(Pull Requestにラベルを貼るなどすれば、技術的には実現可能だと思います)
余談かつ完全に個人的な意見ですが、必要でないにも関わらずSemantic Versioningを採用している開発チームは結構多いのではないかと思います。また、一日に何度もデプロイがされるようなソフトウェアとの相性は必ずしも良くありません。不要なのであれば、Semantic Versioningでの管理を辞めて、よりシンプルなバージョニング手法を使うことを検討しても良いのかなと思います。
第二に、publish: trueを指定している点です。この値はdefault: falseなのですが、falseだとリリースノートはDraftの状態でGitHub上に作成されるのみで、実際のリリースはされません。drafterなので当たり前かもしれないですが…笑
trueにすることでDraftではなくpublishされた状態でいきなりリリースノートが作成されます。
.github/release-drafter.yml
categories:
- title: 'All :fire:'
label: 'all'
- title: 'Staff :zombie:'
label: 'staff'
- title: 'Shop :department_store:'
label: 'shop'
- title: 'TPL :truck:'
label: 'tpl'
- title: 'Bug Fixes :bug:'
label: 'bug'
- title: 'Others :pizza:'
label: 'other'
exclude-labels:
- 'exclude from release'
template: |
$CHANGES
このファイルは上述のworkflows/に置かれるファイルと併せて必要です。
こちらも二点ほどポイントがあります。
第一に、labelによるセクション分けです。Pull Requestに貼られたlabel次第で出すセクションを分けることが出来ます。
弊社の場合はStaff(社内ユーザー)、Shop(ブランドのユーザーさん)、TPL(配送業者さん)という三種類のActorがシステムを利用しているため、どこに影響があるリリースなのかが分かりやすいようにこのようにしています。
また、exclude-labelsを指定することで、exclude from releaseを貼ったPull Requestはリリースノートに含まれないようにしています。リファクタリングやライブラリのバージョンアップなど、ユーザーに周知する必要のない変更も多くあるためです。
第二に、$CHANGESの指定です。これを指定しないとPull Requestを取得出来ません。単純なことですが、自分はこれで結構詰まってしまいました…。
ここまでで、リリースノートを自動で作成することが出来るようになりました。
ただ、これだけでは開発者が適切にPull Requestにlabelを貼るモチベーションが無いため、これらのlabelを貼らないと指摘してくれるActionをgithub-action-required-labelsを使用する形で書きます。
name: Required Pull Request Labels
on:
pull_request:
branches:
- master
types: [opened, synchronize, reopened, labeled, unlabeled, review_requested, ready_for_review]
jobs:
label:
runs-on: ubuntu-latest
steps:
- uses: mheap/github-action-required-labels@v2
with:
mode: exactly
count: 1
labels: "all, shop, staff, tpl, other, bug"
こんな感じです。all, shop, staff, tpl, other, bugの中からひとつを貼らないとActionが落ちるので、labelを貼ってもらう動機付けになっています。
最後に、Slackのリリースノートを通知したいチャンネルでいつものおまじないを唱えれば完成です!
/github subscribe sixty-percent/repo_name
/github unsubscribe sixty-percent/repo_name issues,pulls,commits,deployments
おわりに
ここまでお付き合いいただきありがとうございます。Semantic Versioningを使っていない前提にはなりますが、release-drafterを使うと簡単にリリースノートの作成を自動化出来るので非常にオススメです。
今後の課題として、リリースノートの公開をデプロイ完了時に行うことが挙げられます。現状デプロイの完了よりもリリースノートの公開の方が先に来てしまうため、リリースノートが出ているのに変更が本番に反映されていない時間が発生してしまっています。
方法としては、masterマージ時にはDraftでリリースノートを作っておいて、デプロイ完了時にCI/CDパイプラインからGitHubのAPIを叩いて公開するのが良さそうだと思っています。
シックスティーパーセントでは一緒に 越境ECを作っていく仲間を全方位で募集しています!プロダクト開発以外にもさまざまなポジションがあるので興味ある方は気軽にお声がけいただけると嬉しいです!