[メモ] GitHub Actions を使って Electron の multi-platform-build をやる

# やりたかったこと

最近個人的に Electron で小さなアプリを作る機会があったが、公開するにあたってビルド -> Release のフローを自動化したかった。当初 TravisCI を使っていたが、この機会に GitHub Actions を使ってみたのでその時のメモ。

ちなみに今回想定しているフローは、

1. 新しい Tag を Push (e.g., v0.0.2)
2. Tag Push をトリガーに GitHub Actions の build job がスタート
3. 成功すると、Tag 名の Release (draft) を作成し、ビルドした成果物 (e.g., `.exe` `.dmg`) ファイルを作成した Release の Assets としてアップロード。
4. Release を行う (手動で draft -> public release として更新する)

勝手に public release まで公開してほしくはなかったので、今回のゴールは draft 状態の Release までです。

イメージ
<img width="523" alt="Screen Shot 2020-01-08 at 15.43.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19942/ce363a0b-50a7-276d-6e8a-48a7a4687a4a.png">

# electron-builder

Electron アプリをビルドするには、

- electron-forge
- electron-builder
- electron-packager

といったツールがありますが、おそらく electron-builder が1番使われていると思います。今回は [electron-builder](https://github.com/electron-userland/electron-builder) を使います。

## electron-builder 本体の GitHub インテグレーション

今回は GitHub Actions の中でビルドしたパッケージを Release に紐付ける、という事をやるのでこの機能は使いませんが、electron-builder 自体がもっている GitHub インテグレーションを使うことでも、同様に Release の作成 -> ビルドしたパッケージを紐付け、が可能です (`-p` オプション)。当初 TravisCI ではこの機能を使っていました。

`.travis.yml` の設定例も公開されています。
https://www.electron.build/multi-platform-build#sample-travisyml-to-build-electron-app-for-macos-linux-and-windows

## build options

実際にビルドする時には下記のようなコマンドを使います。

```sh
# macOS 用にビルド
$ electron-builder --mac
# Windows 用にビルド
$ electron-builder --win --x64
```
\* 使っているネイティブモジュールがビルド対象となる OS 用の prebuilt バイナリを提供していない場合は、実際にその OS 上でしかビルドができない。(i.e., Windows 用のパッケージは Windows 上でしかビルドできない)

この時、色々なオプションが指定でき、通常は `package.json` 内に `build` オプションを記載していきます。
https://github.com/electron-userland/electron-builder#quick-setup-guide

`package.json` 内に書かず、個別に YAML ファイルとして保存し、`-c` で指定することもできます。

# GitHub Actions 設定

ワークフローの YAML は下記のようになりました。

```yaml

name: CI

on:
  push:
    tags:
    # "v" で始まる Tag 名の push だけをトリガーの対象にします (e.g., "v0.0.2")
    - 'v*'

jobs:
  # macOS 用の job 定義
  build_on_mac:
    runs-on: macos-latest
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js 12.x
      uses: actions/setup-node@v1
      with:
        node-version: 12.x
    - name: npm install
      run: npm install
    # ここでアプリをビルド
    - name: build application
      run: npm run build:mac
    # Release の作成とビルドしたパッケージのアップロード
    - name: create release
      uses: softprops/action-gh-release@v1
      if: startsWith(github.ref, 'refs/tags/')
      with:
        # 作成される Release は draft に留めておきたい
        draft: true
        # アップロード対象となるファイル名
        files: |
          dist/*.dmg
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

  # Windows 用の job 定義
  build_on_win:
    runs-on: windows-latest
    steps:
    - uses: actions/checkout@v2
    - name: Use Node.js 12.x
      uses: actions/setup-node@v1
      with:
        node-version: 12.x
    - name: npm install
      run: npm install
    - name: build application
      run: npm run build:win
    - name: create release
      uses: softprops/action-gh-release@v1
      if: startsWith(github.ref, 'refs/tags/')
      with:
        draft: true
        files: |
          dist/*.exe
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

今回はアプリに対して署名を行わず、あくまでもオレオレアプリとしての公開だったので内容はとてもシンプルです。使っているパッケージも少なく、いずれも prebuilt バイナリが提供されていたので、実際には Windows 環境は使わなくてもビルドできたのですが、試しに綺麗に分けてみました。

# TravisCI から切り替えて良かった点

- 体感ではビルド時間が早くなった (個人的な感覚)。
- Token をいちいち発行して env に設定、みたいな手間がなくなった。
- なんかいい