GitHub Actions を使ってリリース時のあれこれを自動化する
GitHub Actions を使ってリリース時のあれこれを自動化する
結論
- リリース時のタグとリリースノートを自動で生成するようにした
- リリース時に自分がやることは 動作確認 => Merge pull request を押すだけにした
なぜやるのか
- Release ノートを手動で作るのは面倒
- 手動でやることには人為的なミスの恐れがある
- 面倒なことを続けるとモチベーションが低下する(これ重要)
要件
- リリース
- リリースは週に1度行う
- リリース前に開発した PR をリストで見ながら動作確認をしたい
- PR のリストがそのままリリースノートに記載されて欲しい
- 自動化
- タグの作成は手動でやりたくない
- リリースのための PR を手動で作りたくない
- リリース時のバージョンを手動で入力したくない
自動化の必要性を感じたきっかけ
都内でシステムエンジニアをしている itizawa です。
理想のブックマークアプリを開発するために2月頃からコードをちまちま書いてます。
本業があるので平日に作業できるのは多くても 夜寝る前の2時間。
1週間に一度のリリースを目標にしているので、平日はコツコツ実装、土曜にがっつり開発、日曜に動作確認とリリース、次週の計画を行っています。
開発自体は楽しいのでとても良いのですが、日曜日の動作確認とリリースに関する作業は結構面倒で、これはどうにかしないとまずいなと思っていました。
開発Flow の紹介
開発Flow は以下のように行ってます。(図は自作なので分かりづらかったらすいません)
ブランチの構成は適宜、皆さんの環境で読み替えてください
Master ブランチにマージされた時に実行する workflow
name: Create a release pull request
on:
pull_request:
types: [closed]
branches:
- master
jobs:
create-release-pr:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- name: get-npm-version
id: package-version
uses: martinbeentjes/npm-get-version-action@master
- name: echo-npm-version
id: echo-version
run: |
echo v${{ steps.package-version.outputs.current-version}}
- name: Create a release pull request
uses: bakunyo/git-pr-release-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_PR_RELEASE_BRANCH_PRODUCTION: release
GIT_PR_RELEASE_BRANCH_STAGING: master
GIT_PR_RELEASE_LABELS: release
NPM_VERSION: v${{ steps.package-version.outputs.current-version}}
GIT_PR_RELEASE_TEMPLATE: .git-pr-release-template
実行タイミングについて
pull_request:
types: [closed]
branches:
- master
pull_request で PR で、 types で指定したタイミングで実行できる。
詳しくはこちら
今回は master にマージしたタイミングで実行されて欲しいので、branches に master と書く。
version の取得について
- name: get-npm-version
id: package-version
uses: martinbeentjes/npm-get-version-action@master
Get current package version を使って pakage.json に記載されている version を取得します。
ここで取得した version は後述する PR 作成ステップで ${{ steps.package-version.outputs.current-version}}
を記述して使います。
release 後に package.json を編集して version をあげることは必要になりますが、package.json が SSOT となる構成は好みですね。
また、package.json のバージョンを変えると自動的に rename して対応してくれます。
PR の作成について
- name: Create a release pull request
uses: bakunyo/git-pr-release-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GIT_PR_RELEASE_BRANCH_PRODUCTION: release
GIT_PR_RELEASE_BRANCH_STAGING: master
GIT_PR_RELEASE_LABELS: release
NODE_VERSION: v${{ steps.package-version.outputs.current-version}}
GIT_PR_RELEASE_TEMPLATE: .git-pr-release-template
git-pr-release を使用して PR を作成します。
GitHub actions で Ruby をセットアップすることなく
git-pr-release(ruby のコード)を実行できます。
環境変数を設定し、PR元と先の設定をしたり label を付けたりします。
また、後述の release 時の workflow のために、GIT_PR_RELEASE_TEMPLATE
に .git-pr-release-template
を指定し PR をカスタマイズします。
.git-pr-release-template について
<%= ENV['NPM_VERSION'] %>
<% pull_requests.each do |pr| -%>
<%= pr.to_checklist_item %>
<% end -%>
example とあんまり変わりませんがカスタマイズを行います。
title に 前のステップで取得した package.json の version を設定します。
この workflow の output
create-release.yml が走りきると上記の画像のような PR が作成されます。
master ブランチから release ブランチに向けて作成され、実際にマージされた PR のタイトルとその author が記載されます。
日曜日の動作確認時には、この PR リストを見ながら動作確認を行えるようになりました。
Release ブランチにマージされた時に実行される workflow
name: Create Release
on:
pull_request:
types: [closed]
branches:
- release
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@master
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.event.pull_request.title }}
release_name: ${{ github.event.pull_request.title }}
body: ${{ github.event.pull_request.body }}
draft: false
prerelease: false
- name: Slack Notification
uses: weseek/ghaction-release-slack-notification@master
with:
channel: '#webev-dev'
url: ${{ secrets.SLACK_WEBHOOK_URL }}
created_tag: '${{ github.event.pull_request.title }}'
実行タイミングについて
こちらは先述のため詳細は省略。
release ブランチにマージされた時に実行されます。
リリースとタグの作成について
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.event.pull_request.title }}
release_name: ${{ github.event.pull_request.title }}
body: ${{ github.event.pull_request.body }}
draft: false
prerelease: false
create-release を用いリリースを行います。
tag_name の名前は PR のタイトルから取得します。
先ほど template を用いて PR のタイトルにバージョンを設定したのはこのためで、そのまま v1.0.1 のようなタグが生成されます。
ちなみに、template を用いないと Release 2021-03-20 11:24:53 +0000
のような形式が PR のタイトルに設定されますが、tag_name には使えない形式なので注意が必要です。
body には先ほどの PRリストが入ってきて、これがそのまま リリースノートになります。
Slack 通知について(optional)
- name: Slack Notification
uses: weseek/ghaction-release-slack-notification@master
with:
channel: '#webev-dev'
url: ${{ secrets.SLACK_WEBHOOK_URL }}
created_tag: '${{ github.event.pull_request.title }}'
こちらは完全に optional な機能ですが、release 完了後に smart な slack 通知を実現します。
ghaction-release-slack-notificationを使っています。(私がcommiter です。メンテしなければ...)
この workflow の output
いい感じのリリースノートができました 🚀
まとめ
リリースに関するあれこれを自動化することができました。
ちなみに、deploy に関しては vercel を使っているので merge 後に deploy されるようになっています。
実装前に色々な記事を参考にしましたが、なかなか自分の要件に合致するものがありませんでした。
GitHub actions のマーケットプレイスの組み合わせで多くのことができ、0から作るわけでなかったので2h ほどで実装できました。
先人に感謝です 🤲
参考にさせていただいた記事
Discussion
https://github.com/actions/create-release はアーカイブされているので、READMEにある代替を使ったほうが良いかと思います
ご指摘いただきありがとうございます
後ほど記事も修正します🙏