個人でHomeBrew通してバイナリを公開する時、formulaを作成してレポジトリを立ち上げる必要があります。
そこにはバージョンやリリースしたいファイルのURL、SHA256 checksumを含めなくてはならないのですが、バイナリをアップデートしたい時にソースコードのレポジトリだけでなくformulaのレポジトリも更新しなくてはならず面倒です。
そこでGitHubActionsで2つのレポジトリを連携してリリースとformulaの更新を一度に行える様にしてみました。
対象レポジトリ
Rustで書いたCLIアプリであるGitHub - QWYNG/harvest: stashes grep tool with rustとそのformulaである GitHub - QWYNG/homebrew-harvestが対象レポジトリです。
workflow
まずリリースする側のレポジトリのworkflowの設定です。長いので中略してます。
name: Release
on:
push:
tags:
- 'v*.*.*'
jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, macOS-latest]
rust: [stable]
runs-on: ${{ matrix.os }}
steps:
~~~ snip ~~~
- name: Set version
id: set_version
run: echo ::set-output name=version::${GITHUB_REF/refs\/tags\//}
env:
GITHUB_REF: ${{ github.ref }}
- name: Build for linux
if: matrix.os == 'ubuntu-latest'
run: |
cargo build --release --target=x86_64-unknown-linux-musl
zip -j harvest-${VERSION}-x86_64-lnx.zip target/x86_64-unknown-linux-musl/release/harvest
env:
VERSION: ${{ steps.set_version.outputs.version }}
- name: Build for macOS
if: matrix.os == 'macOS-latest'
run: |
cargo build --release --target=x86_64-apple-darwin
zip -j harvest-${VERSION}-x86_64-mac.zip target/x86_64-apple-darwin/release/harvest
env:
VERSION: ${{ steps.set_version.outputs.version }}
- name: Set SHA256
if: matrix.os == 'macOS-latest'
id: sha_256
run: |
echo "::set-output name=sha::$(shasum -a 256 harvest-${VERSION}-x86_64-mac.zip |awk '{print $1}')"
env:
VERSION: ${{ steps.set_version.outputs.version }}
- name: Release
id: release
uses: softprops/action-gh-release@v1
with:
files: '*.zip'
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Dispatch homebrew Repo update
if: matrix.os == 'macOS-latest'
uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.HOMEBREW_REPO_GITHUB_TOKEN }}
repository: QWYNG/homebrew-harvest
event-type: update
client-payload: '{"version": "${{ steps.set_version.outputs.version }}", "sha": "${{ steps.sha_256.outputs.sha }}" }'
Build for macOSではビルドとzipへの圧縮を行っています。
GitHubActionsは::set-output name={name}::{value}の形で後のstepでsteps.<step id>.outputs.{name}として値を使用できます。これを利用してSet versionとSet SHA256でバージョンとzipファイルのchecksumをセットしています。
最後に取得したバージョンとchecksumをrepository-dispatchをつかってformulaレポジトリに投げます。普通にcurlで発火させることもできますが、今回は
GitHub - peter-evans/repository-dispatch: A GitHub action to create a repository dispatch eventが便利そうだったので使ってみました。
dispatchを受け取るformulaレポジトリ側のworkflowは以下
name: Release
on: repository_dispatch
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
with:
persist-credentials: false
fetch-depth: 0
- name: Create local version change
run: |
truncate version.rb --size 0
echo 'VERSION = "${{ github.event.client_payload.version }}"' > version.rb
echo 'SHA = "${{ github.event.client_payload.sha }}"' >> version.rb
- name: Commit version change
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git commit -m "update version" -a
- name: Push changes
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
dispatchで受け取ったペイロードを使ってversion.rbを書き直してコミットしてプッシュしてます。
無事自動でformulaレポジトリを更新できました。
まとめ
愚直な実装なのでHomeBrewに詳しければもう少しスマートにできるかもしれないです。
後harvestをgit diffではなくgit stash show -pの結果で検索するように改良し、更に標準出力にページャを導入しました。大分使いやすくなったので満足。