🚀

Github ActionsとSemantic ReleaseでUnityの自作パッケージのリリースを自動化する

2022/07/19に公開

概要

GitHubにPushしたら

  • コミットログを解析して
  • CHANGELOG.mdを更新
  • package.jsonのバージョン欄を更新
  • npmにパブリッシュ
  • gitにtagを追加、変更したファイルを改めてPush
  • GitHubのReleaseページを追加

という自動化をします。

Scoped Registryのススメ

npm?と気になった方もいらっしゃるかもしれません。

Unity Package Managerでパッケージをインストールする方法はローカルファイルの指定、GitURLの指定、Scoped Registry経由の3つです。

このうちScoped Registryには次の利点があります。

  • 依存パッケージも自動的にインストールしてくれる
  • PackageManagerが公開済みのバージョンを認識する
    Updateボタンが出たり、バージョンを選択してのインストールできる

反面、次のような手間がかかります。

  • リリース担当者はパッケージをScoped Registryにパブリッシュする必要がある
  • インストールする方もScoped Registryの設定が必要

はじめはよくわからないし手間もかかるしと敬遠してたのですが、使ってみるとPackageManagerが本気を出してくれるのが思ったりよりも快適でおすすめです。

Scoped Registryは自前でサーバーを建てるのもありなのですが、公開前提であれば次の2つがメジャーな選択肢のようです。

今回はnpmをターゲットにしています。

自動化の仕組み

全体像はこんな感じです。

GitHub Actionでsemantic-releaseを使うとやりたいことをだいたいやってくれます。すごい。

semantic-release

Semantic Versioning(SemVer)のルールベースでパッケージリリースのワークフローを自動化してくれるツールです。

https://github.com/semantic-release/semantic-release

デフォルトの動作ではnpmへのパブリッシュとGitHubのリリースページの更新しかしませんが、プラグインを追加することでCHANGELOG.mdの更新などが出来るようになります。

また、Angularのコミットメッセージの書式に基づいてコミット履歴から新しいバージョン番号とリリースノートの文言を生成します。

Commit message Release type
fix(pencil): stop graphite breaking when too much pressure applied Patch Fix Release
feat(pencil): add 'graphiteWidth' option Minor Feature Release
perf(pencil): remove graphiteWidth option

BREAKING CHANGE: The graphiteWidth option has been removed.
The default graphite width of 10mm is always used for performance reasons.
Major Breaking Release
(Note that the BREAKING CHANGE: token must be in the footer of the commit)

https://github.com/semantic-release/semantic-release/blob/master/README.md より

このルールのおかげで人間がバージョン番号をつけたり、CHANGELOGの更新といった手間から解放されます。便利!
かわりにコミットにちょっとした緊張感が漂います。

設定手順

GitHub

GitHub Actionが動くように設定を確認しておきます。

GitHubのリポジトリから Settings > Actions > General

  • Action permissionsDisable actions以外のものに
  • Workflow permissionsRead and write permissions

なっているか確認しておきましょう。
自分の環境ではデフォルトのままで大丈夫でした。

NPM_TOKEN

npmにパブリッシュできるように認証用のトークンを取得しGitHubに登録しておきます。
npmのアカウントが必要なのでなければ事前に取得しておきましょう。

  1. npmjs.comの自身のアイコンからAccess Tokensを選択

  2. Generate New Tokenをクリック

  3. 適当な名前をつけ、Select typeのAutomationを選択、Generate Tokenボタンを押す

  4. トークン(1行のランダムな文字列)が生成されます

こちらのトークンは二度と表示されないので気をつけてください。
(とはいえわからなくなったらまた作れば大丈夫です)

こちらのトークンをGitHub Actionで使えるように登録します。

GitHubのリポジトリから Settings > Secrets > Actions
Nameに"NPM_TOKEN"、Valueにさきほど取得したトークンを入力します。

GitHub Action

  1. リポジトリに.github/workflowフォルダを作る
  2. .github/workflow下にPublish.ymlを置く
Publish.yml
name: Publish

on: 
  push:
    branches:
      - main
  workflow_dispatch:    
    
jobs:
  publish:
    runs-on: ubuntu-latest

    steps:
    - name: Checkout
      uses: actions/checkout@v3
      with:
        fetch-depth: 0

    - name: Semantic Release
      uses: cycjimmy/semantic-release-action@v3
      with:
        semantic_version: 19
        branch: main
        working_directory: ./Packages/ga.fuquna.testpublishingpackage
        extra_plugins: |
            @semantic-release/changelog@6
            @semantic-release/git
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

mainブランチにPushされたら、最新の状態をチェックアウトしsemantic-releaseにかける、といった動作になっています。

semantic-release-action

semantic-release-actionというsemantic-releaseを動かすGitHub Actionがすでにあるのでこちらを利用しています。

- name: Semantic Release以下が該当部分になります。

  • branch:はデフォルトがmasterなのでmainを指定しています。
  • working_directory:はパッケージとして公開するフォルダに置換してください。
  • extra_plugins:ではsemantic-releaseの追加プラグインを指定しています。
    今回はCHANGELOG.mdの更新と、更新したファイル(package.json、CHANGELOG.md)のPushをするために、semantic-release/changelogsemantic-release/gitの2つのプラグインを指定しています。このままでは動作せず後述の.releaserc.ymlでも指定が必要です。
  • env:で先程設定したNPM_TOKENを教えています。GITHUB_TOKENは自動的に使えるのでここで指定するだけでOKです。

記述していないですがdry-runオプションもあるので最初は指定しておくと安心かもしれません。

semantic-release

最後にsemantic-release用の設定ファイルを作ります。
リポジトリのルートフォルダに.releaserc.ymlを置きます。

.releaserc.yml
{
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/changelog",
    "@semantic-release/npm",
    "@semantic-release/git",
    "@semantic-release/github"
  ]
}

pluginsでプラグインを指定しています。
実行順もこの順にしたがっているのでで注意が必要です。

ちなみに、何も指定しないデフォルトでは次のようになっているようです。

{
  "plugins": [
    "@semantic-release/commit-analyzer",
    "@semantic-release/release-notes-generator",
    "@semantic-release/npm",
    "@semantic-release/github"
  ]
}

semantic-releaseは単体ではなにもせずプラグインの集合として動作してるみたいですね。
上記.releaserc.ymlはこちらにsemantic-release/changlogsemantic-release/gitを良きタイミングのところに追加した形になっています。

動作確認

以上でリリースの自動化が出来ているはずです。
とはいえ結構typoなどで途中でエラーになっていたりするのでGitHubのActionsタブでうまく動いているか確認しましょう。

Angular書式のコミットメッセージがないと最初のリリースも行われないので注意してください。

使ってみて

semantic-releaseではバージョンが1.0.0スタートで0.0.0スタートにはできないところにちょっとひっかかりました。これはSemVer的にはメジャーバージョン0以下は1以上のルールが適応されない(破壊的変更しまくる開発初期扱い)ため良くないよ、とのことです。やるならかわりにpre-releaseの作法がおすすめみたいです。
https://semantic-release.gitbook.io/semantic-release/support/faq#can-i-set-the-initial-release-version-of-my-package-to-0.0.1

semantic-relase自体はただのnode.jsプログラムなので、オンライン上の動作がよくわからないときはローカルで動かしてみるのもいい作戦だと思います。またコンフィグが豊富でいろいろできそうなので、困ったらドキュメントを漁ってみるのもいいと思います。

参考

https://qiita.com/goma_recorder/items/d4dd1a3d1c04726f55b5

Discussion