2019-10-05

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 の展開方法はそれぞれ異なる
  • うっかり 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

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 に応じて環境変数の展開方法などを変える必要がある。

  1. 少なくとも 2019-10-05 時点で 

About

例によって個人のなんちゃらです

Recent Posts

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Document SVG AsciiDoc Pandoc DocBook Develop Jekyll macOS Node.js Vite Heroku Transformer AI Data Cloud Wasm