Murasaki
ビルド & 配布

配布

本物のネイティブインストーラを出荷する — クロスアーキテクチャビルド、署名、公証、CI。

murasaki bundle / murasaki installer は、macOS(.app / .dmg)と Windows(ポータブル .zip、NSIS .exe、MSI .msi)で本物のインストーラを 出力します。いずれもクロスアーキテクチャ(arm64 / x64)対応です。@murasakijs/native は Linux(x64/arm64)向けのビルド済みバイナリも提供しています — Linux 向けのアプリ パッケージングはロードマップに含まれています。

TargetBundleInstaller公開 code signing
macOS arm64 / x64.app + .app.zip.dmgDeveloper ID + notarization を組み込み対応
Windows x64 / arm64portable folder + .zipNSIS .exe、Windows 上で WiX .msiSignTool Authenticode を組み込み対応
Linux予定

ファイルが生成されたことは distribution-ready を意味しません。clean machine で installed artifact をテストし、signature と全 production dependency / resource を 検証してください。Murasaki は 1.0 未満で、Node dependency packaging はすべての dynamic native addon / runtime-discovered asset layout をまだ網羅していません。

クロスアーキテクチャビルド

バンドルには、ポータブルでターゲット固有の Node ランタイム(nodejs.org からのチェック サム検証済みダウンロードで、~/.murasaki/node/ にキャッシュされます)と、コンパイル 済みのネイティブランチャーバイナリが同梱されます — CLI をたまたま実行している node ではありません。つまり、Apple Silicon の開発マシンから Intel 向けビルドを生成 することも、その逆もできます:

murasaki bundle --arch x64             # Apple Silicon Mac 上で x64 の .app をビルド
murasaki bundle --arch arm64           # Intel Mac 上で arm64 の .app をビルド
murasaki bundle --target win32-arm64   # arm64 の Windows バンドル

murasaki installer も、同じ方法で --arch / --targetbundle に転送します。 Windows は win32-x64 / win32-arm64

URL scheme と file association

packaged app が扱う handler を murasaki.config.ts で宣言します。

murasaki.config.ts
import { defineConfig } from 'murasaki'

export default defineConfig({
  appId: 'com.example.notes',
  productName: 'Notes',
  protocols: [{ scheme: 'example-notes', name: 'Notes link' }],
  fileAssociations: [{
    extensions: ['enote'],
    name: 'Notes document',
    role: 'editor',
    mimeType: 'application/x-example-note',
  }],
})

target ごとの登録結果は次のとおりです。

Artifact登録動作
macOS .app / .dmgsigning 前に app の Info.plistCFBundleURLTypesCFBundleDocumentTypes、exported document UTI を書き込む。DMG にはその app がそのまま入る
Windows NSIS .exeprotocol、ProgID、Open With entry、Default Apps capability を既定で per-user、installMode: 'perMachine' で per-machine 登録
Windows WiX .msi同じ handler を per-machine 登録
Windows portable folder / .zipregistry を変更せず、自動登録しない
Linux登録と app packaging は予定

cold start、2 回目の起動、macOS open event のいずれでも、一致した URL / file は ready() 完了後に Node Main の openRequested() hook へ渡されます。Windows portable build でも URL / file を command line で直接渡せば受け取れますが、 installation-free artifact が OS default を自動で取得することはありません。

Windows への登録はアプリを選択可能な handler にしますが、user の protected default-app choice を上書きしません。fresh install / upgrade の両方をテストし、 uninstall が自分の handler entry だけを削除することを確認してください。

署名と公証

Murasaki が提供するのは signing orchestration であり、publisher identity ではありません。 Apple Developer ID または Windows certificate / Artifact Signing profile を用意してください。 --sign は未署名成果物を黙って公開せず、署名できなければ失敗します。

既定では murasaki bundlead-hoc signed .app を生成し、murasaki installer はその app を .dmg に入れます。macOS は local bundle integrity を検証できますが、 信頼された developer identity にはならず、成果物は notarize できません。自分の download 済み development artifact に限り quarantine を外せます:

xattr -dr com.apple.quarantine "<path>"

これを end user 向け installation path にしないでください。警告なしの public 配布には Developer ID signing と notarization が必要です。

警告なしで配布するには、あなた自身の Apple Developer ID で署名・公証してください — Murasaki は独自の証明書を一切同梱していません:

murasaki bundle --sign                 # .app を Developer ID で署名する
murasaki installer --sign --notarize   # + .dmg を Apple に提出し、チケットをステープルする
  • --sign は、.app をハードンドランタイムで署名します(Apple のドキュメント 化されたフローどおり: まず内側のコード、その後外側のバンドル)。署名 identity は $MURASAKI_SIGN_IDENTITY、次に config.sign.identity、次にキーチェーン内の最初の "Developer ID Application" identity の順で解決されます。Entitlements は、設定され ていれば config.sign.entitlements から、そうでなければハードンドランタイムの下で Node が必要とする JIT / 未署名実行可能メモリ / ライブラリ検証なしの entitlements を 付与するデフォルトの plist から取得されます。
  • --notarize には --sign が必須です(公証は Developer ID 署名済みのコードしか 受け付けません)。認証情報は APPLE_IDAPPLE_TEAM_IDAPPLE_APP_PASSWORD (アプリ専用パスワード)から読み取られます — 設定やファイルからは決して読み取りま せん.dmg を Apple の notary サービスに提出し、結果を待ってから、Gatekeeper が オフラインで検証できるようチケットをステープルします。

どちらも、有料の Apple Developer Program メンバーシップが必要です。

macOS artifact を検証する

signing 後の最終 .app と notarization 後の最終 .dmg に対して実行します。

codesign --verify --strict --verbose=2 "dist/bundle/My App.app"
codesign -dvvv --entitlements :- "dist/bundle/My App.app"
spctl -a -t open --context context:primary-signature -vv "dist/My App-1.0.0.dmg"
xcrun stapler validate "dist/My App-1.0.0.dmg"

codesign --verify は app の code / resource seal、spctl は配布 DMG の Gatekeeper policy、stapler validate はその notarization ticket を検査します。public release では すべてを実行してください。

Windows installer と signing

murasaki bundle --target win32-x64 は portable folder / .zip を生成します。 murasaki installer は build host に存在する tool も呼びます。

  • NSIS .exe: makensis。macOS / Windows で実行可能
  • .msi: WiX v4。Windows 上で実行

NSIS は perUser(既定、elevation なし)または perMachine、MSI は常に per-machine です。branding と upgrade identity は 設定を参照してください。

署名済み release は Windows 上で実行します(未署名 Windows artifact の cross-build は 引き続き他 OS でも可能です):

pnpm exec murasaki bundle --target win32-x64 --sign
pnpm exec murasaki installer --target win32-x64 --sign

bundle command は portable ZIP を作る前に <productName>.exe を署名します。installer command はその署名済み payload を NSIS / MSI に格納し、生成した setup executable と MSI 自体も署名します。すべて SHA-256 と既定の RFC 3161 timestamp を使用し、別の signtool verify /pa /v /tw pass で検証します。署名または検証の失敗は release を停止します。

signer は次の1つを選びます。CI では config を編集せず環境変数で override できます。

SignerConfig環境変数 override
PFX/P12sign.windows.certificateFileMURASAKI_WINDOWS_CERTIFICATE_FILE + 任意の MURASAKI_WINDOWS_CERTIFICATE_PASSWORD
import 済み証明書の subjectsign.windows.certificateSubjectNameMURASAKI_WINDOWS_CERTIFICATE_SUBJECT
import 済み証明書の thumbprintsign.windows.certificateSha1MURASAKI_WINDOWS_CERTIFICATE_SHA1
Microsoft Artifact Signingsign.windows.artifactSigning.{dlib,metadata}MURASAKI_WINDOWS_ARTIFACT_SIGNING_DLIB + MURASAKI_WINDOWS_ARTIFACT_SIGNING_METADATA

selector を指定しない場合は SignTool /aCurrentUser/My から最適な code-signing certificate を選択します。machine store は certificateStore: 'localMachine'、SignTool path は MURASAKI_SIGNTOOL_PATH、timestamp は MURASAKI_WINDOWS_TIMESTAMP_URL で override できます。false で timestamp を無効化できますが public release では非推奨です。

Microsoft Artifact Signing では dlibAzure.CodeSigning.Dlib.dllmetadata に 非secretの account/profile JSON を指定します。認証は Azure CLI、workload identity、 managed identity 側に残し、credential を JSON や Murasaki config に書かないでください。

updater の Ed25519 manifest signature は Windows SmartScreen の publisher identity を 確立しないため Authenticode の代わりにはなりません。正しく署名しても新規 publisher は reputation が育つまで SmartScreen prompt が出る場合があります。

GitHub Actions の Windows 署名済み release

最小構成の PFX 例です。certificate は runner の一時ディレクトリだけに書きます。証明書 policy に合う場合は import 済み store certificate または cloud/HSM provider を優先してください。

.github/workflows/release-windows.yml
jobs:
  windows:
    runs-on: windows-2025
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
      - run: pnpm install --frozen-lockfile
      - name: Materialize signing certificate
        shell: pwsh
        env:
          CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE_PFX }}
        run: |
          [IO.File]::WriteAllBytes(
            "$env:RUNNER_TEMP\release.pfx",
            [Convert]::FromBase64String($env:CERTIFICATE_BASE64)
          )
      - name: Build signed installers
        env:
          MURASAKI_WINDOWS_CERTIFICATE_FILE: ${{ runner.temp }}\release.pfx
          MURASAKI_WINDOWS_CERTIFICATE_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }}
        run: pnpm exec murasaki installer --target win32-x64 --sign

GitHub Actions による macOS 署名済みリリース

タグの push で .dmg をビルドし、(任意で)署名・公証して GitHub Release に添付しま す。あなたのアプリに .github/workflows/release.yml として次を追加してください:

.github/workflows/release.yml
name: Release
on:
  push:
    tags: ['v*']
jobs:
  release:
    runs-on: macos-14
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 24
      - run: pnpm install
      - name: Import signing certificate
        if: ${{ secrets.APPLE_CERTIFICATE_P12 != '' }}
        env:
          CERT_P12: ${{ secrets.APPLE_CERTIFICATE_P12 }}
          CERT_PW: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
        run: |
          KC="$RUNNER_TEMP/app.keychain-db"
          security create-keychain -p "" "$KC"
          security set-keychain-settings -lut 21600 "$KC"
          security unlock-keychain -p "" "$KC"
          echo "$CERT_P12" | base64 --decode > "$RUNNER_TEMP/cert.p12"
          security import "$RUNNER_TEMP/cert.p12" -k "$KC" -P "$CERT_PW" -T /usr/bin/codesign
          security set-key-partition-list -S apple-tool:,apple: -s -k "" "$KC"
          security list-keychains -d user -s "$KC" $(security list-keychains -d user | tr -d '"')
      - name: Build installer
        env:
          APPLE_ID: ${{ secrets.APPLE_ID }}
          APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
          APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }}
          HAS_CERT: ${{ secrets.APPLE_CERTIFICATE_P12 != '' }}
        run: |
          if [ "$HAS_CERT" = "true" ]; then
            pnpm exec murasaki installer --sign --notarize
          else
            pnpm exec murasaki installer
          fi
      - uses: softprops/action-gh-release@v2
        with:
          files: dist/*.dmg

署名・公証するには、次のリポジトリシークレットを追加してください(未署名の .dmg に するにはすべて省略します): APPLE_CERTIFICATE_P12(あなたの Developer ID .p12 の base64)、APPLE_CERTIFICATE_PASSWORDAPPLE_IDAPPLE_TEAM_IDAPPLE_APP_PASSWORD

これらのシークレットを設定やソースにコミットしないでください — --notarize は意図 的に、環境変数からしかそれらを読み取りません。

Release checklist

  • clean checkout と lock 済み dependency graph から build
  • installer 化の前に bundle を launch
  • 公開する全 platform / architecture の clean target で install / update / uninstall
  • 設定した URL scheme / file association を cold start と primary app 起動中の両方で確認
  • Node Main shutdown、offline startup、network failure を確認
  • macOS signing / notarization と Windows Authenticode signature を検証
  • 最終 payload が immutable になってから Murasaki update manifest を生成・署名
  • payload、latest.jsonlatest.json.sig を同時公開
  • signing credential / MURASAKI_UPDATE_KEY は CI secret に保存し、 murasaki.config.ts に書かない

Code signing と update signing は独立しています。 セキュリティ自動更新を確認してから in-app update を有効にして ください。

次へ

GitHub でこのページを改善

On this page