0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GitHub Actions と Tauri 2 でマルチプラットフォームのデスクトップアプリ配布を自動化するメモ

0
Posted at

はじめに

最近、Tauri 2 を使ったデスクトップアプリの配布まわりを見ていて、
GitHub Actions で Windows / macOS / Linux 向けのインストーラや配布物をどう自動化するかがきれいだったので、メモとして整理しておきます。

デスクトップアプリは実装だけで終わりではなく、
最終的に各 OS 向けの成果物をどう作るかまで考えないと、リリース運用がすぐ重くなります。

特にマルチプラットフォーム対応では、次のあたりが気になりやすいです。

  • 何をきっかけにリリースを始めるか
  • Windows / macOS / Linux をどう分けてビルドするか
  • OS ごとの依存をどこで解決するか
  • 生成した成果物をどう公開するか

今回は、Tauri 2 + GitHub Actions でこの流れをどう組めるかを、workflow 中心に見ていきます。

先に前提だけ確認しておく

まず、Tauri 側の設定を少しだけ見ておくと、GitHub Actions 側の動きが理解しやすくなります。

{
  "build": {
    "frontendDist": "../dist",
    "beforeBuildCommand": "npm run build"
  },
  "bundle": {
    "active": true,
    "targets": "all"
  }
}

ここで押さえておきたいのは 2 点です。

  • 配布ビルド前に npm run build を実行する
  • その OS で作成可能な bundle を対象にする

つまり CI 上で Tauri の配布ビルドが走るときは、ざっくり次の順番になります。

  1. フロントエンドをビルドする
  2. 生成した dist を Tauri が取り込む
  3. Windows / macOS / Linux それぞれで成果物を作る

GitHub Actions は、この一連の流れを 3 プラットフォーム分まとめて回す役目です。

リリースの起点は Git tag にする

まず入口です。

on:
  push:
    tags:
      - "v*"

ここはかなり分かりやすくて、v1.0.0 のようなタグを push したときだけ workflow が動きます。

この形のよいところは、
「どのタイミングを正式リリースとするか」を Git の操作にそのまま乗せられることです。

ブランチ push のたびに配布ビルドを走らせるより、
tag push を起点にしたほうが公開タイミングが明確になります。

3 プラットフォームのビルドは matrix で並列化する

次に、workflow の中心になる部分です。

jobs:
  publish-tauri:
    name: Publish ${{ matrix.label }}
    runs-on: ${{ matrix.platform }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - label: Windows x64
            platform: windows-latest
            args: ""
          - label: macOS universal
            platform: macos-latest
            args: "--target universal-apple-darwin --no-sign"
          - label: Linux x64
            platform: ubuntu-22.04
            args: ""

ここでは、3 プラットフォーム分の配布ビルドを matrix で並列化しています。

  • Windows は windows-latest
  • macOS は macos-latest
  • Linux は ubuntu-22.04

こういう構成を見ると、
マルチプラットフォーム対応は特別な大きい仕組みではなく、
GitHub Actions の matrix に素直に乗せるだけでもかなり整理できる ことが分かります。

個別の job を 3 つコピペして管理するより、この形のほうが見通しがよいです。

macOS は universal build にしておくと扱いやすい

macOS だけ引数が付いています。

args: "--target universal-apple-darwin --no-sign"

ここでは Apple Silicon と Intel の両方に対応する universal build を作っています。

macOS 向け成果物を CPU 別に分ける構成もできますが、
配布する側から見ると universal のほうが説明が単純になります。

利用者から見ても、

  • どちらの Mac でも基本的に同じ配布物を使える
  • ダウンロードページが増えすぎない

というメリットがあります。

今回は --no-sign なので、署名なしの構成です。
まず GitHub Releases で配布するところまで作りたい、という段階なら、この形はかなり現実的だと思います。

Linux は system dependency を先に入れる

Linux だけは最初に依存を追加しています。

- name: Install Linux system dependencies
  if: runner.os == 'Linux'
  run: |
    sudo apt-get update
    sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf

ここは地味ですが重要です。

Tauri の Linux ビルドでは WebKit 系ライブラリなどが必要になるので、
ローカルでは通っても CI ではここで詰まりやすいです。

こういう OS 固有の前提を workflow に書いておくと、
あとから見返したときにも「Linux だけなぜ準備が必要なのか」がすぐ分かります。

マルチプラットフォームの配布パイプラインでは、
この「依存を隠さずに書いておく」がかなり大事だと感じます。

Node と Rust の準備も job の中で完結させる

そのあとに、ビルドに必要なツールチェーンを入れます。

- name: Setup Node.js
  uses: actions/setup-node@v4
  with:
    node-version: lts/*
    cache: npm
    cache-dependency-path: package-lock.json

- name: Install Rust stable
  uses: dtolnay/rust-toolchain@stable

- name: Install macOS universal Rust targets
  if: matrix.label == 'macOS universal'
  run: rustup target add aarch64-apple-darwin x86_64-apple-darwin

- name: Install frontend dependencies
  run: npm ci

ここでやっていることはシンプルです。

  • フロントエンドのために Node.js を入れる
  • Tauri のために Rust を入れる
  • macOS universal build のときだけ Rust target を追加する
  • フロントエンド依存は npm ci で固定的に入れる

必要なものをすべて job の中で完結させているので、
runner の状態にあまり期待しない構成になっています。

CI は手元の環境と違って毎回きれいな状態から始まるので、
このくらい明示的なほうが安心です。

配布前にバージョンずれを止める

この workflow で特によいと思ったのが、配布前にバージョン整合性を見ているところです。

- name: Verify release version matches tag
  shell: bash
  run: |
    node - <<'EOF'
    const fs = require('fs');

    const packageVersion = JSON.parse(fs.readFileSync('package.json', 'utf8')).version;
    const tauriVersion = JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json', 'utf8')).version;
    const cargo = fs.readFileSync('src-tauri/Cargo.toml', 'utf8');
    const cargoMatch = cargo.match(/^version\s*=\s*"([^"]+)"/m);
    const tagVersion = (process.env.GITHUB_REF_NAME || '').replace(/^v/, '');

    if (!cargoMatch) {
      console.error('Unable to read version from src-tauri/Cargo.toml.');
      process.exit(1);
    }

    const cargoVersion = cargoMatch[1];

    if (!tagVersion || packageVersion !== tagVersion || tauriVersion !== tagVersion || cargoVersion !== tagVersion) {
      console.error(
        `Tag and app versions must match. tag=${tagVersion} package=${packageVersion} tauri=${tauriVersion} cargo=${cargoVersion}`
      );
      process.exit(1);
    }
    EOF

ここで見ているのは次の 4 つです。

  • Git tag
  • package.json
  • src-tauri/tauri.conf.json
  • src-tauri/Cargo.toml

Tauri ベースのアプリは、JavaScript 側と Rust 側でバージョン情報が分かれるので、
うっかりずれると「ビルドは通ったけど、公開物としては気持ち悪い」という状態が起こります。

なのでこのチェックはかなり実用的です。
単に配布物を作るだけではなく、ちゃんと公開してよい状態か を先に確認しています。

最後は tauri-action にまとめて任せる

最後に、実際のビルドと GitHub Releases へのアップロードです。

- name: Build app and upload release assets
  uses: tauri-apps/tauri-action@action-v0.6.2
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  with:
    tagName: ${{ github.ref_name }}
    releaseName: "Desktop App ${{ github.ref_name }}"
    releaseBody: "See the assets to download this version and install."
    generateReleaseNotes: true
    releaseDraft: false
    prerelease: false
    args: ${{ matrix.args }}

ここでやっていることはかなり明快です。

  • 各 OS 向けの成果物をビルドする
  • 生成した成果物を GitHub Releases にアップロードする
  • リリース名や本文も workflow 側で管理する

運用としては、最終的に次の流れになります。

  1. バージョンをそろえる
  2. tag を push する
  3. GitHub Actions が Windows / macOS / Linux を並列ビルドする
  4. GitHub Releases に成果物が並ぶ

手元でビルドして zip や installer を集めて手動アップロードする運用より、
この形のほうがだいぶ安定します。

まとめ

今回見た構成では、マルチプラットフォームの desktop application 配布を次の流れで自動化していました。

  1. Git tag をリリースの起点にする
  2. matrix で Windows / macOS / Linux を並列ビルドする
  3. Linux 依存や macOS target を job 内で準備する
  4. 配布前にバージョン不整合を止める
  5. tauri-action で成果物生成と GitHub Releases への公開まで流す

マルチプラットフォームの installer / 配布物づくりは大変そうに見えますが、
GitHub Actions の matrix と tauri-action をうまく使うと、かなり見通しよく整理できます。

自分で desktop application の配布パイプラインを組むなら、
まずは tag push + matrix + tauri-action という形から始めるのが扱いやすそうだなと思いました。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?