🤖

Tauri製のmacOSユニバーサルアプリケーションをGitHub ActionsでReleaseするCDを実現する

2025/02/09に公開

タイトルがてんこ盛り。

pushしたらReleasesに署名済みの .dmg が焼きあがってる世界を目指します。

追記:公式にサンプル追加のPRを送り取り込んで頂きました

対象の読者

  • Mac App Storeに並べるほどでもないが、とはいえ広範にアプリ配布したい人
  • リリースしたアプリケーションを「プライバシーとセキュリティ」で実行を許可してもらう必要がありモヤモヤしている人

要件

  • Intel CPU Mac / Apple Silicon Macともに利用できる
    → ユニバーサルアプリとしてビルドし、.dmg でパッケージングして配布する

  • ユーザーはGitHubリポジトリのRelease経由でダウンロードできる
    → GitHub Actionsでいい感じにする

  • ユーザーはダウンロードした.dmg ファイルから一般的なUXでアプリをインストール・起動できる

    • dmgをマウントすると左側にインストールしたいアプリ / 右側に Applicationsフォルダが配置され、D&Dすることでインストールできる
    • 起動すると特別な認証を求められずそのまま起動できる
      →公式Actionのサンプルに具体例が無くて苦労した

リリースするもの

公式サンプル に最低限の変更を加えたアプリケーション
完成品のサンプルリポジトリはこちら
https://github.com/8beeeaaat/tauri_distribution_sample

参照すべき公式ドキュメント

https://v2.tauri.app/distribute/


Apple Developer Programで識別子を準備

この後すぐIdentiferが必要となるので作っておきます
(過去のものを流用する場合はスキップしてもOK)

0. メンバーシップ登録しましょう 💰

円安つらいよう ( 151円/ドル 2025/02/08時点)

https://developer.apple.com/account/

1. Identifierの新規作成を開始


https://developer.apple.com/account/resources/identifiers/list

2. 種別は App IDs を選択

3. 続いてAppを選択

4. Bundle IDを指定して作成を完了

今回は決め打ちで指定しましたが、ワイルドカードで作ってしまっても問題ないはず。
Capabilities や App Servicesはひとまず未指定(後でも変更できます)


サクッとサンプルアプリをビルド可能な状態にする

リポジトリを作ってgit clone

プロジェクトのリポジトリは分かりやすく tauri_distribution_sample とします

空のリポジトリを git clone

% pwd
/Users/8beeeaaat

% git clone git@github.com:8beeeaaat/tauri_distribution_sample.git
Cloning into 'tauri_distribution_sample'...
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0 (from 0)
Receiving objects: 100% (3/3), done.

1. セットアップ

1. Identifier 以外は適当にセットアップ。

Identifierは先ほど Apple Developer Program で作ったものを指定します。

% cd tauri_distribution_sample
 % pwd
/Users/8beeeaaat/tauri_distribution_sample

% bun create tauri-app
✔ Project name · tauri-app
✔ Identifier · 作ったIdentifier
✔ Choose which language to use for your frontend · TypeScript / JavaScript - (pnpm, yarn, npm, deno, bun)
✔ Choose your package manager · bun
✔ Choose your UI template · React - (https://react.dev/)
✔ Choose your UI flavor · TypeScript

Template created! To get started run:
  cd tauri-app
  bun install
  bun run tauri android init
  bun run tauri ios init

For Desktop development, run:
  bun run tauri dev

For Android development, run:
  bun run tauri android dev

For iOS development, run:
  bun run tauri ios dev

2. tauri_distribution_sample 直下にプロジェクトファイルを移動させる

% ls
README.md  tauri-app

% mv tauri-app/* tauri-app/.* .  # .gitignoreなども移動させる

% pwd
/Users/8beeeaaat/tauri_distribution_sample

% ls -a
.   .git        .vscode    index.html    package.json  src        tauri-app      tsconfig.node.json
..  .gitignore  README.md  dist      public        src-tauri  tsconfig.json  vite.config.ts

3. パッケージをインストールして開発ビルドの起動を確認

% bun install

% bun tauri dev


親の顔より見たデモ画面が立ち上がったらOK

4. ビルドしてみる

% bun tauri build

...

    Finished 2 bundles at:
        /Users/8beeeaaat/tauri_distribution_sample/src-tauri/target/release/bundle/macos/tauri-app.app
        /Users/8beeeaaat/tauri_distribution_sample/src-tauri/target/release/bundle/dmg/tauri-app_0.1.0_aarch64.dmg

ビルドに成功すると src-tauri/target/release/bundle/dmg に.dmg パッケージが作られます。
マウントするとよく見るインストーラの面構えをしています。早速目標を達成できそう。

このままApplicationsに放り込むとそのまま使うこともできます。

5. アプリ名を変えてみる

  • 仮名称にしていたけど正式名称が決まったので変えたい
  • 天の声で変えざるを得なくなった

人生いろいろなことがありますので、そんな時は tauri.conf.json を編集します。

src-tauri/tauri.conf.json
{
  "$schema": "https://schema.tauri.app/config/2",
-  "productName": "tauri-app",
+  "productName": "8beeeaaatのアプリ",
  "version": "0.1.0",
  "identifier": "com.8beeeaaat.tauri-app",
  "build": {
    "beforeDevCommand": "bun run dev",
    "devUrl": "http://localhost:1420",
    "beforeBuildCommand": "bun run build",
    "frontendDist": "../dist"
  },
  "app": {
    "windows": [
      {. // ウィンドウ名も変更したければ
-        "title": "tauri-app",
+        "title": "8beeeaaatのアプリ",
        "width": 800,
        "height": 600
      }
    ],
    "security": {
      "csp": null
    }
  },
  "bundle": {
    "active": true,
    "targets": "all",
    "icon": [
      "icons/32x32.png",
      "icons/128x128.png",
      "icons/128x128@2x.png",
      "icons/icon.icns",
      "icons/icon.ico"
    ]
  }
}
  • インストーラ / アプリケーション名

  • app.windows.title を変更するとウィンドウ名を変えられる

ユニバーサルアプリ化

build コマンドの target オプションで Intel Mac / Apple Silicon Mac 両対応のユニバーサルアプリとしてビルドさせることができます。

% bun tauri build --target universal-apple-darwin

It must be one of the values outputted by $rustc --print target-list or universal-apple-darwin for an universal macOS application.
https://v2.tauri.app/reference/cli/#build

ということでやってみると...

failed to build x86_64-apple-darwin binary: Target x86_64-apple-darwin is not installed (installed targets: aarch64-apple-darwin, aarch64-apple-ios, aarch64-apple-ios-sim, aarch64-linux-android, armv7-linux-androideabi, i686-linux-android, x86_64-apple-ios, x86_64-linux-android). Please run `rustup target add x86_64-apple-darwin`.
    Error failed to build x86_64-apple-darwin binary: Target x86_64-apple-darwin is not installed (installed targets: aarch64-apple-darwin, aarch64-apple-ios, aarch64-apple-ios-sim, aarch64-linux-android, armv7-linux-androideabi, i686-linux-android, x86_64-apple-ios, x86_64-linux-android). Please run `rustup target add x86_64-apple-darwin`.
error: script "tauri" exited with code 1

aarch64-apple-darwin(Apple Silicon)用のビルドターゲットだけ設定しているので、 x86_64-apple-darwin も設定せよと怒られています。
指示通りに rustup を設定して再挑戦。

% rustup target add x86_64-apple-darwin          
info: downloading component 'rust-std' for 'x86_64-apple-darwin'
info: installing component 'rust-std' for 'x86_64-apple-darwin'
 24.9 MiB /  24.9 MiB (100 %)  23.3 MiB/s in  1s ETA:  0s

% bun tauri build --target universal-apple-darwin
 ...

ユニバーサルアプリとしてのインストーラが完成しました。
src-tauri/target/universal-apple-darwin/release/bundle/dmg/8beeeaaatのアプリ_0.1.0_universal.dmg

両アーキテクチャのバイナリが含まれているのでサイズはほぼ倍ですね。致し方なし。


mainブランチにpushされたらRelease機能で署名済みのインストーラを配布できるようにする

Releaseで配布する上で最低限の設定だけを紹介していきます

1. Workflow permissionsを書き込み可に変更する

成果物を書き込ませるので、 リポジトリの settings > Code and automation > actions > General の Workflow permissions を Read and write permissions に変更する

“Resource not accessible by integration” error when running the workflow. If this happens, you may need to add write permissions to this token. To do this, go to your GitHub project settings, select Actions, scroll down to Workflow permissions, and check “Read and write permissions”.
https://v2.tauri.app/distribute/pipelines/github/#github-environment-token


Saveをお忘れなく

2. Repository secrets に定数を設定する

settings > Security > Secrets and variables > Actions > Repository secrets

認証関連のドキュメント を参考に設定します。(手順を全て説明すると大変なので割愛)
https://v2.tauri.app/distribute/sign/macos/

最低限ビルドに必要なもの

  • APPLE_ID: Apple Developer Programで使用しているE-mailアドレス
  • APPLE_ID_PASSWORD: 同ログインパスワード
  • APPLE_CERTIFICATE: Developer ID Application Certificateから作成 Creating a signing certificate参照
  • APPLE_CERTIFICATE_PASSWORD: APPLE_CERTIFICATE の作成過程で自分で決める
  • KEYCHAIN_PASSWORD: キーチェーンアクセスのパスワード(通常 macOSのログインパスワードと同じはず)

アプリへの署名に必要なもの

https://support.apple.com/ja-jp/102654

必ずしもパスワードタイトルをアプリID / 名称などと一致させる必要はない

3. 公式サンプルを調整してWorkflow を設定

https://v2.tauri.app/distribute/pipelines/github/#example-workflow

.github/workflows/publish.yml
name: 'publish'

on:
  push:
    branches:
      - main
jobs:
  publish-tauri:
    permissions:
      contents: write
    strategy:
      fail-fast: false
      matrix:
        include:
          - platform: 'macos-latest' # ユニバーサルアプリとしてビルド
            args: '--target universal-apple-darwin'
          # 今回はWindows / Linux向けインストーラは作らない
          # - platform: 'ubuntu-22.04' # for Tauri v1 you could replace this with ubuntu-20.04.
          #   args: ''
          # - platform: 'windows-latest'
          #   args: ''

    runs-on: ${{ matrix.platform }}
    steps:
      - uses: actions/checkout@v4

      # ※ Bun向け: お手元のパッケージマネージャに合わせて依存関係をインストールしてください
      - name: Cache Bun modules
        uses: actions/cache@v3
        with:
          path: node_modules
          key: bun-modules-${{ hashFiles('bun.lockb') }}
      - uses: oven-sh/setup-bun@v2
        with:
          bun-version: latest
      - name: install frontend dependencies
        run: |
          bun install

      - name: Cache Cargo registry
        uses: actions/cache@v3
        with:
          path: ~/.cargo/registry
          key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}

      - name: install Rust stable
        uses: dtolnay/rust-toolchain@stable
        with:
          # Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds.
          targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}

      - name: Prepare for Release
        run: |
          echo "Preparing release..."
          echo "Tagging version..."
          # Additional release preparation steps here

      - name: Import Apple Developer Certificate (macOS only)
        if: matrix.platform == 'macos-latest'
        env:
          APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
          APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
          KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
        run: |
          echo $APPLE_CERTIFICATE | base64 --decode > certificate.p12
          security create-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
          security default-keychain -s build.keychain
          security unlock-keychain -p "$KEYCHAIN_PASSWORD" build.keychain
          security set-keychain-settings -t 3600 -u build.keychain
          security import certificate.p12 -k build.keychain -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign
          security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" build.keychain
          security find-identity -v -p codesigning build.keychain

      - name: verify certificate (macOS only)
        if: matrix.platform == 'macos-latest'
        run: |
          CERT_INFO=$(security find-identity -v -p codesigning build.keychain | grep "Developer ID Application")
          CERT_ID=$(echo "$CERT_INFO" | awk -F'"' '{print $2}')
          echo "CERT_ID=$CERT_ID" >> $GITHUB_ENV
          echo "Certificate imported."

      - name: Read version and set env
        run: | #tauri.conf.jsonのversion情報をタグに使う
          VERSION_TAG=v$(jq -r '.version' < src-tauri/tauri.conf.json)
          echo "VERSION_TAG=$VERSION_TAG" >> $GITHUB_ENV

      - name: Build and Publish
        uses: tauri-apps/tauri-action@v0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
          APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
          APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
          APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
          APPLE_SIGNING_IDENTITY: ${{ env.CERT_ID }} #証明書から取得したものが適用される
        with:
          tagName: ${{ env.VERSION_TAG }}
          releaseName: 'tauri-app ${{ env.VERSION_TAG }}'
          releaseBody: 'See the assets to download this version and install.'
          # releaseDraft: true 一旦リリースをドラフトとして作成したい場合はコメントアウトを外す
          includeDebug: true
          args: ${{ matrix.args }}

      - name: Set Version Tag
        run: |
          if git rev-parse "${{ env.VERSION_TAG }}" >/dev/null 2>&1; then echo "Tag ${{ env.VERSION_TAG }} already exists. Skipping tagging."
          else echo "Tagging with version: ${{ env.VERSION_TAG }}"
            git tag ${{ env.VERSION_TAG }}
            git push origin ${{ env.VERSION_TAG }}
          fi

あるあるActionのエラー達

リポジトリ設定の settings > Code and automation > actions > General の Workflow permissions を Read and write permissions にし忘れていないか確認する

  • Developer ID Application 証明書が存在するか確認する
% security find-identity -v -p codesigning | grep "Developer ID Application"
  1) 〜〜〜 "Developer ID Application: ユーザー名 (チームID)"
  • APPLE_CERTIFICATE を Developer ID Application 証明書からエンコードして出力したか確認する


Apple Development と取り違え注意


Releaseされた .dmg を確認

Actionが終了するとReleaseで .dmg が配布されることを確認


リポジトリのReleasesにlatestタグと共に追加される


Releases

https://github.com/8beeeaaat/tauri_distribution_sample/releases

ダウンロードした .dmg からインストール / アプリケーションを起動できることを確認

  • ローカル同様、マウントするとインストーラを起動できる

  • Applicationsからそのまま起動できる

    初回はWebからダウンロードしたので確認を求められます。致し方なし

めでたしめでたし!!
Tauriを使ってアプリケーション開発をしたい方はご相談ください

Discussion