GitHub Actionsでpkgを使ったNode.js実行バイナリをWindowsを含めてmatrixビルドする
目的
pkgでNode.jsスクリプトを実行バイナリにする - あーありがち(2019-10-04) において、各プラットフォーム上で pkg を叩けば Node.js スクリプトを Windows, macOS, Linux それぞれで動く単体のバイナリにできることは分かった。
今日はこの pkg を使って各 platform 上で build する処理を GitHub Actions で自動化してみたときのメモ。これが完成すれば基本的には Windows 上のちょっとしたツールを、いつもの macOS で、いつもの JavaScript で書いて git push すればオッケーと言える。便利。
※ 現時点では公開できる完成リポジトリはないので、日本語だけ。
対象
CircleCI など YAML で CI の設定をした経験のある人向け。細かい説明は一切しません。
参考
GitHub ActionsでElectronアプリのクロスプラットフォームバイナリを配布する | Web Scratch
メモ
About GitHub Actions - GitHub Help
matrixビルド
複数の環境を指定していくつもビルドを実行することをmatrixビルドと呼ぶらしい。これは GitHub Actions 独特のものではない。
- strategy で matrix を指定したうえで runs-on は ${{ matrix.os }} で
- pkg の target にはこの matrix.os をそのまま使うことはできないので、「matrix.os を加工する action」を加える必要がある
環境の課題
- step の run に複数行与える書き方は Windows 標準の shell の cmd では正しく動かない1
- run の中の文字列は shell の世界。bash だったり cmd だったりするので env の展開方法はそれぞれ異なる
- つまり if で環境を特定してそれぞれの shell 向けの書き方をする必要あり
- if も含めて run 以外のところは Contexts and expression syntax for GitHub Actions - GitHub Help に従う
- GitHub Actions の便利機能を利用できるのはこの部分
- うっかり yarn <command> と書くと Windows では動かない。しっかり yarn run <command> と書く。
YAMLの中の条件判別などのSyntax大事
Contexts and expression syntax for GitHub Actions - GitHub Help
何が大事って、この部分は shell でも JavaScript でもない独自の文法の世界ってこと。リファレンス見ないと分からないし、オフラインの linter などもまず存在しない世界。
Actionの書き方
- uses で action を利用する際の書き方は二種類。GitHub上のactionとそのバージョンの指定か、同一repos内のディレクトリのいずれか。外部のリポジトリを指す場合はバージョンを明記しろと言われるが、ローカルのファイルの場合はむしろ書いたらダメ。
- <owner/repos@version>
- ./.github/actions/<name>
- uses で action を利用する場合、inputs / outputs ともに決められた方法でやりとりする
- action を JavaScript で書く場合、npm install は実行されないので node_modules も含める。Linux / macOS ではなんとなく動く場合もあるけど、Windows だとちゃんとエラーになる。
..github/ ディレクトリの中に直接 action を置いてしまってもよいが、uses の書き方がやや異なるので注意が必要。
共通で使いそうなものは独立させて Creating a JavaScript action - GitHub Help に書いてある通り zeit/ncc を使って node_modules 込みでパッケージにしてしまった方がテストもしやすい(入出力は環境変数っぽい)のでよさそう。
※ 急に zeit さんと親しくなってしまった。
役に立つAction
- actions/checkout
- actions/setup-node: Set up your GitHub Actions workflow with a specific version of node.js
- actions/upload-artifact
- softprops/action-gh-release: 📦 GitHub Action for creating GitHub Releases
release にできあがった file を upload する方法に go binary を使っている記事も見かけたけど、action があるのでそっちを使う方が手軽でよさげ。
matrix buildしてるYAMLの例の一部
outputs の読み取り方が結構独特。
run-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- uses: <owner/repos@version>
id: <action>
with:
os: ${{ matrix.os }}
- name: package executable
env:
<NAME>: ${{ steps.<action>.outputs.<name> }}
run: command $<NAME>
if: matrix.os == 'windows-latest'
- name: package executable
env:
<NAME>: ${{ steps.<action>.outputs.<name> }}
run: command %<NAME>%
if: matrix.os != 'windows-latest'
ここで env, if の部分は完全に GitHub Actions 独自の Syntax で、if の部分は ${{ }}
で囲まなくてもよい。ただし、参照できるオブジェクトは決まっている。
run の中身は shell で実行されるので、shell に応じて環境変数の展開方法などを変える必要がある。
少なくとも 2019-10-05 時点で ↩