Homebrewの自作CLIツールの配布がとても面倒くさい
以前Homebrew/tapによる配布方法をまとめたが、やることが結構あって面倒くさい。
どうやらGithubActionsを使えばめちゃくちゃ楽にできるみたいなのでやってみた。
今までの流れ
1. tagをpush 2. GithubでReleaseの作成 3. Formulaファイルの作成or更新 5. 完了
今回目指すのはこれ
1. tagをpush 5. 完了
- Githubのページを開いてReleaseノートを作成
- Formulaリポジトリの.rbファイルを更新
この2つの作業を撲滅する。
死ぬほど参考にさせていただいたサイト
基本的に下記のサイトを参考にすればいけました、感謝です。
参考にしていて詰まったところと、変更している箇所を書いていきます。
対象リポジトリ
- Rasukarusan/gitblamer(自作CLIツール、リリース用のリポジトリ)
- Rasukarusan/homebrew-tap(Formula用のリポジトリ)
FormulaリポジトリにはFormula
ディレクトリを設置していて、複数のツールが登録してある状態。ツールごとにFormulaリポジトリを用意せず、1つのリポジトリで管理するスタイルです。
流れ
- リリースノートを作成するworkflow(リリース用のリポジトリ)
- Formulaファイルを作成/更新するworkflow(Formula用のリポジトリ)
リリースノートを作成するworkflow
リリースノートには
- 前回のtagからの差分
- バイナリファイルのアップロード
を載せます。
リリースリポジトリに.github/workflows/release.yml
を作っていきます
name: Release on: push: tags: - 'v*' jobs: build: name: Create Release runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 with: fetch-depth: 0 # 1つ前のtagからの差分を取得 - name: Get commit summary id: get_commit_summary run: | PREVIOUS_TAG=$(git tag --sort=-creatordate | sed -n 2p) COMMIT_SUMMARY="$(git log --oneline --pretty=tformat:"%h %s" $PREVIOUS_TAG..${{ github.ref }})" COMMIT_SUMMARY="${COMMIT_SUMMARY//$'\n'/'%0A'}" echo ::set-output name=COMMIT_SUMMARY::$COMMIT_SUMMARY # リリースノートの作成 - name: Create Release id: create_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ github.ref }} release_name: Release ${{ github.ref }} body: | ${{ steps.get_commit_summary.outputs.COMMIT_SUMMARY }} draft: false prerelease: false # バイナリファイルのアップロード - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./gitblamer asset_name: gitblamer asset_content_type: application/octet-stream # Formulaに値を渡す準備 - name: Set value for formula id: set_value_for_formula run: | SHA256=$(openssl dgst -sha256 gitblamer | awk '{print $2}') echo ::set-output name=SHA256::$SHA256 echo ::set-output name=BINARY::gitblamer echo ::set-output name=CLASS::Gitblamer # Formulaリポジトリ更新(Formulaリポジトリのworkflowを発火) - name: Update Formula Repository uses: peter-evans/repository-dispatch@v1 with: token: ${{ secrets.REPO_ACCESS_TOKEN }} repository: Rasukarusan/homebrew-tap event-type: released client-payload: ' { "ref": "${{ github.ref }}", "sha256": "${{ steps.set_value_for_formula.outputs.SHA256 }}", "binary": "${{ steps.set_value_for_formula.outputs.BINARY }}", "url": "${{ steps.create_release.outputs.upload_url }}", "class": "${{ steps.set_value_for_formula.outputs.CLASS }}" } '
とりあえずこれでtagをpushしたらリリースノートが作られます。
# tagをpush git tag v1.2.2 git push origin v1.2.2
Formulaファイルを作成/更新するworkflow
本来手動でbrew create
コマンドで作るファイルを、step内で作っている感じですね。
name: Update Formula on: repository_dispatch: types: [released] jobs: myEvent: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 with: fetch-depth: 0 - name: Update formula file run: | VERSION=$(echo ${{ github.event.client_payload.ref }} | sed -e "s#refs/tags/##g") BINARY=${{ github.event.client_payload.binary }} URL="https://github.com/Rasukarusan/$BINARY/releases/download/$VERSION/$BINARY" data=$(cat <<EOF > Formula/$BINARY.rb class ${{ github.event.client_payload.class }} < Formula url "$URL" sha256 "${{ github.event.client_payload.sha256 }}" def install bin.install "$BINARY" end end EOF ) - name: Commit version change run: | git config --local user.email "action@github.com" git config --local user.name "GitHub Action" git add -A git commit -m "update version" - name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }}
この状態でリリースリポジトリにtagがpushされたら新しいformulaファイルがコミットされる。
ここまで終わったらTerminalでCLIツールを更新できるようになっている。
brew info gitblamer brew upgrade gitblamer
詰まったところ
前回のtagからの差分を出す
# 1つ前のtagからの差分を取得 - name: Get commit summary id: get_commit_summary run: | PREVIOUS_TAG=$(git tag --sort=-creatordate | sed -n 2p) COMMIT_SUMMARY="$(git log --oneline --pretty=tformat:"%h %s" $PREVIOUS_TAG..${{ github.ref }})" COMMIT_SUMMARY="${COMMIT_SUMMARY//$'\n'/'%0A'}" echo ::set-output name=COMMIT_SUMMARY::$COMMIT_SUMMARY
こちらは下記サイトを参考にさせていただきました。
注意点として、最初のstepでCheckoutするときにwith: fetch-depth: 0
を設定しないと前回のtagが取得できないので注意。デフォルトでは1らしい。
バイナリファイルのアップロード
# バイナリファイルのアップロード - name: Upload Release Asset id: upload-release-asset uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} asset_path: ./gitblamer asset_name: gitblamer asset_content_type: application/octet-stream
Homebrewではバイナリを直接指定する方式を取っていたため、zipではなくバイナリをアップロードする必要があります。
つまりasset_content_type
をapplication/octet-stream
にする。
Github Actionsのusesって何?
誰かが作成したアクション。自分で作ることもできる。Githubが公式でいくつか用意している。
Marketplaceで色んなworkflowが検索できる。
Formulaリポジトリのworkflowを発火する箇所も、本来はcurlでGithubAPIを叩くだけなので別にusesを使わなくてもいいが、使ったほうがcurlで書くよりシンプルに見やすくなる。
# Formulaリポジトリ更新(Formulaリポジトリのworkflowを発火) - name: Update Formula Repository uses: peter-evans/repository-dispatch@v1 with: token: ${{ secrets.REPO_ACCESS_TOKEN }} repository: Rasukarusan/homebrew-tap event-type: released client-payload: ' { "ref": "${{ github.ref }}", "sha256": "${{ steps.set_value_for_formula.outputs.SHA256 }}", "binary": "${{ steps.set_value_for_formula.outputs.BINARY }}", "url": "${{ steps.create_release.outputs.upload_url }}", "class": "${{ steps.set_value_for_formula.outputs.CLASS }}" } '
${{ github.ref }} の他には何がある?
終わり
自作ツールのアップデートが最高に楽になった、やったね。