🚀

GitHub Actions を使ってリリース時のあれこれを自動化する

2021/03/21に公開
2

GitHub Actions を使ってリリース時のあれこれを自動化する

結論

  • リリース時のタグとリリースノートを自動で生成するようにした
  • リリース時に自分がやることは 動作確認 => Merge pull request を押すだけにした

なぜやるのか

  • Release ノートを手動で作るのは面倒
    • 手動でやることには人為的なミスの恐れがある
    • 面倒なことを続けるとモチベーションが低下する(これ重要)

要件

  • リリース
    • リリースは週に1度行う
    • リリース前に開発した PR をリストで見ながら動作確認をしたい
    • PR のリストがそのままリリースノートに記載されて欲しい
  • 自動化
    • タグの作成は手動でやりたくない
    • リリースのための PR を手動で作りたくない
    • リリース時のバージョンを手動で入力したくない

自動化の必要性を感じたきっかけ

都内でシステムエンジニアをしている itizawa です。
理想のブックマークアプリを開発するために2月頃からコードをちまちま書いてます。
本業があるので平日に作業できるのは多くても 夜寝る前の2時間。
1週間に一度のリリースを目標にしているので、平日はコツコツ実装、土曜にがっつり開発、日曜に動作確認とリリース、次週の計画を行っています。
開発自体は楽しいのでとても良いのですが、日曜日の動作確認とリリースに関する作業は結構面倒で、これはどうにかしないとまずいなと思っていました。

開発Flow の紹介

開発Flow は以下のように行ってます。(図は自作なので分かりづらかったらすいません)
ブランチの構成は適宜、皆さんの環境で読み替えてください

Master ブランチにマージされた時に実行する workflow

実際のコード(GitHubに飛びます)

create-release.yml
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 について

実際のコード(GitHubに飛びます)

.git-pr-release-template
<%= ENV['NPM_VERSION'] %>
<% pull_requests.each do |pr| -%>
<%= pr.to_checklist_item %>
<% end -%>

example とあんまり変わりませんがカスタマイズを行います。
title に 前のステップで取得した package.json の version を設定します。

この workflow の output

PR(GitHubに飛びます)

create-release.yml が走りきると上記の画像のような PR が作成されます。
master ブランチから release ブランチに向けて作成され、実際にマージされた PR のタイトルとその author が記載されます。
日曜日の動作確認時には、この PR リストを見ながら動作確認を行えるようになりました。

Release ブランチにマージされた時に実行される workflow

実際のコード(GitHubに飛びます)

release.yml
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 ほどで実装できました。
先人に感謝です 🤲

参考にさせていただいた記事

https://zenn.dev/ucwork/articles/41cf2f20ecd2a0

Discussion