Goで作ったCLIツールのビルド・配布をGitHub Actionsで自動化する
Goで作ったdotfiles管理ツールのdotzをビルド・バイナリ配布・homebrewのアップデートまでを自動化したメモ。
GitHub Actionsを初めて本格的に利用してみました。beta版の時はyamlにズラズラとshell scriptのように記述した覚えがありますが現行のactionsでは考え方が違うようです。
github actions
現行のGitHub actionsについては日本語文献もたくさんあるので詳しいことはそっちを見てほしいんですが、GitHub上ではworkflowがpushやPR、タイマーなどのトリガーによって実行されます。workflow内には任意のactionを持ちこのactionが順次/並列で実行されます。
actionにはdockerのようにinputと環境変数を渡すことができ、任意の数のoutputができます。outputは別のactionのinputとして渡すことができます。
また、workflow内で使える環境変数にはリポジトリ名やcommit ハッシュ等の情報に加え、tagのpushをトリガーとした時などにはtag名等様々な情報を取得できます。さらにworkflowを実行しているリポジトリのみの権限を持ったonetime GitHub tokenが払い出されます。
github tokenは対象リポジトリにしか影響できないのでミスって他のリポジトリを消したりできないので安心。
dotzのビルド
dotzに利用しているcli用のライブラリurfave/cliはコマンド実行時にツールのバージョンを表示する昨日はあります、今回はtag名からバージョン番号を拾ってmakefileでビルドします。
makefileはCIだけではなく開発時にも利用すると思います。開発時はmake
コマンド単体のみでビルドし、CI上のビルド時のみバージョン名を渡してビルドしたいです。このようにパラメータをオプション的に使うにはmakefile内で使える変数をコマンドラインから渡してやるといいです。
makefile内で変数dotz_ver
を定義しておきます。
dotz_ver = 0.0.0
build: main.go
go build -v -ldflags "-X main.dotzVersion=${dotz_ver}" .
make build
をしたときにはdotz_ver
の中身は0.0.0
になりますがmake build dotz_ver=1.2.3
と呼び出せばコマンドライン側の値が優先されdotz_ver
の中身が1.2.3
になります。これを利用してworkflowからはtag名を渡しておきます。
~~~~抜粋
jobs:
build:
name: build
env:
GO111MODULE: "on"
runs-on: macos-latest
steps:
- name: Set up Go 1.13
uses: actions/setup-go@v1
with:
go-version: 1.13
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Build
run: make build dotz_ver=${{ github.ref }}
~~~~抜粋
上記のmakefileにありますが、go build 時に-ldflags "main.{変数名}={value}"
で値を埋め込んでいます。これでビルド時に変数を取り込み実行時は変数が格納済みの状態で実行が開始されます。
ビルド後は、actions/create-release@v1とactions/upload-release-assetでreleaseに生成したバイナリをアップロードします。
homebrewの自動化
homebrewのformulaを自動更新するactionを作りました。
https://github.com/magcho/dotz/tree/master/.github/actions/update_homebrew
brewの公式リポジトリではなくオレオレformulaを対象としています。更新するactionとuploadするactionを分けたので後者を公式リポジトリにPRを送るactionに差し替えれば運用できるかなと思います。
内部でやっていることは既存のformulaをcurlで落とし、ここでバイナリのURLとsha256を更新しているだけです。
formulaによっては書き換えルールを追加しなければいけないかもですね。
formulaのtestとformatを掛けたのち、formulaをuploadします。formulaのリポジトリにpushしたいところですがworkflowに払い出される通常のGitHub tokenでは実行リポジトリ以外にpushできないので別途用意します。
githubの個人設定からPersonal access tokenを払い出してリポジトリのSettingタブ->Secretsから任意の名前でsecretに登録しておきます。
あとはworkflowから${{secrets.****}}
で参照できるのでtokenを渡しておきます。
~~~~抜粋
- name: create commit
run: |
sh ./ci/create_commit.sh "dotz.rb" "magcho" "${{ secrets.github_personal_acces_token }}" "mail@magcho.com"
~~~~抜粋
これにてtag付きでmasterにpushすれば勝手にリリースまでやってくれるようになります。
おわり
そういやGitHub actionsハッカソンがありました。気づいた時は最終日でしたが、、
github actions marketplaceに全然actionの種類がないなーと思ってたとこなのでハッカソンで一気に増えた感じですかね。自分もなんか出したかったな。