年中アイス

いろいろつらつら

GoReleaser+GithubActionsを使って、releaseファイルのアップロードとhomebrew対応を自動で行う

※2021/04/06 動かなくなってた部分があったので対応を後半に追記しました。

先日、rnzooに機能を追加して、久しぶりにリリースをしようとしたら、色々動かなくなっててハマりました。しばらくやってなかったので、Rubyのバージョンアップや、hubコマンドの再設定などが必要でした。だいぶオレオレリリーススクリプトになっていたので、もうちょっと普遍的なフローでリリースできないかと思って調べました。

ちょうど先週、以下のGoReleaser+GithubActionsで決まり!というエントリが上がっていました。

tellme.tokyo

たまたま、ちょっとしたツールを作る予定もあって、それを上記エントリのやり方で構成し、追加でhombrew-tap対応を行いました。

github.com

基本的な内容は、前述のエントリにわかりやすく書いてあるので、そちらを確認、全体はリポジトリを見てみてください。個人的に失敗して対応した部分と、homebrew-tap対応を中心に書いていきます。

GithubActionsで失敗して、releaseファイルがアップロードされない

初回、リリースタグを打ってworkflowが実行されて失敗しました。以下がworkflowのエラーです。

   • GETTING AND VALIDATING GIT STATE
      • releasing v0.1.0, commit 5d807106bbd8d6dc2b9233e0fd4f3b2ec3cc6708
   ⨯ release failed after 6.29s error=git is currently in a dirty state, please check in your pipeline what can be changing the following > files:
  M go.mod
  M go.sum

内容を見ると、git がdirty stateであると。workflowでcheckoutしてきたのになぜ?と考えましたが、.goreleaser.ymlに以下の記述があります

before:
  hooks:
    - go mod tidy

そういえば、ローカルでgo mod tidyは実行していませんでした。そのため、checkout後に変更差分が出ており、それが原因で失敗していました。案の定、その変更をcommitしたら、無事完了しました

homebrew-tap対応を追加

mogura, rnzoo, rnsshなど、私のツールはhomebrew-tapで入れられるようにしています。GoReleaserはhomebrew-tap向けのファイルを生成する機能を持っています。それを参考に.goreleaser.ymlに以下を追加しました。

...

brews:
  - description: "update ECS agent with CLI."
    github:
      owner: reiki4040
      name: homebrew-tap
    homepage: "https://github.com/reiki4040/ecs-agent-updater"
    install: |
      bin.install "ecs-agent-updater"

homebrew-tapは、homebrewでインストールするための定義Formulaを持つリポジトリで、ツール自体のリポジトリとは別に作ります。今回はhomebrew-tapというリポジトリを作って、そこにFormulaを自動で追加します。*1

そしてこれを動かしてみましたが失敗しました。

• HOMEBREW TAP FORMULA     
         • writing                   formula=dist/ecs-agent-updater.rb
         • pushing                   formula=ecs-agent-updater.rb repo=reiki4040/homebrew-tap
   ⨯ release failed after 31.47s error=homebrew tap formula: failed to publish artifacts: PUT https://api.github.com/repos/reiki4040/homebrew-tap/contents/ecs-agent-updater.rb: 403 Resource not accessible by integration []

アクセス権限がない。これは予想通りというか、最小の権限しか持ってないトークンが自動で割り当てられるはずなので、当然ながら、他のリポジトリにファイルを追加することはできません。調べてみると、似たようにGithubActionsで、他のリポジトリへのアクセスをしたい場合についてのエントリがありました。

blog.marcnuri.com

やり方としては、リポジトリのsecretsにユーザアクセストークンを設定して、それをworkflow内で使うというものでした。同様に、自分のSettings > Developer Settings > Personal Access Token ここで私の場合は、public repositoryだけにチェックを入れて、tokenを生成しました。これをリポジトリのsettings > secretsにACCESS_TOKENという名前で保存し、workflow設定の参照変数を変えました。

env:
-         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 
+         GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }} 

これで無事に完了し、homebrew-tapファイルも生成されました

2021/04/06追記

1年ぶりぐらいに別のツール(mogura)でリリースしようとしたら動かなくなってたので取り急ぎ追記。

2021/04/06時点の最新、gorelease 0.612.0で動かなくなっており、2箇所直したらとりあえず動きました。詳細はまた別途調べる予定です。

  • brewsの中でgithubという属性名の部分がtapに変わっているので変更する
  • tapリポジトリを扱うトークンを別の属性でgoreleaserに渡せるようになっており、そこにgithub secret経由でパーソナルアクセストークンを入れる

github.com

パーソナルアクセストークン自体は生きていますが、なぜかmogura自体の取得に失敗していたので、何かトークンの仕様が変わったのかよくわかっていません。この点はまた別途調べる予定です。

tapリポジトリを扱うトークンは以下の記事を参考しました

qiita.com

最後に

最終的には、リリースタグを打つだけで、バイナリがreleaseに追加され、homebrew-tapまで更新されて、とても楽になったことと、GithubActionsを使ったモダンな作りになりました。

rnzooなどでは、homebrewのdevelオプションでの開発版インストールにも対応していたので、そこもできるかは別途調べようと思っています。

参考

*1:今まで、各ツールごとにtapリポジトリを作ってましたが、実は1つでも良さそうなので、このフローに変更しながら集約する予定です。