Electronアプリの自動更新を実現した後、リリースページが公開され、最初のサポートチケットが到着する前に、コーヒーメーカーが完了する前に。1つのユーザーは、アプリがアップデートを見つけることができなかったと言いました。もう1人は、ダウンロードしたが、インストールすることができませんでした。3番目のユーザーは、古いバイナリを実行し続け、認証フローが破損しているのに対し、ログにはほとんど有用な情報が表示されていません。
それは、 Electron アプリの自動更新. updater API は、1 つのコンポーネントのみです。生産用リリースも、プラットフォームの署名、トランスポートポリシー、マニフェスト、ホスティング、ライフサイクルイベント、観察性、ロールアウト制御、およびロールバックパスに依存します。 それぞれを任意の 1 つとして扱うと、定期的なパッチは 1 夜の出来事になります。
目次
- 2 時間の夜の更新インシデントがこのガイドの始まり
- Electron アプリのアップデートのための適切なパスを選択する
- Main プロセス内で自動更新フローを実装する
- 署名されたリリースとマニフェストのための CI/CD を構成する
- ロールアウト、チャネル、およびロールバック戦略
- 自動更新をセキュリティコントロールとして扱う
- 生産用の更新実行書とチェックリスト
2時8分の更新インシデントがこのガイドの始まり
リリースはCIを通過し、通常のもののように見えました。金曜日の夜遅く、開発者は署名されていないElectronビルドをプッシュし、公開ジョブはリリースが完了しているように十分なアセットをアップロードしました。アプリケーションはテストで起動しましたが、誰もインストール済みの生産ビルドからアップデートパスを実行していませんでした。
2時8分、PagerDutyはオンコールエンジニアに警告を送りました。新しい認証フローは一部の艦隊で失敗し、更新を受けたユーザーはサインインを完了できませんでした。ユーザーはアップデートが検証またはインストールできなかったため、前のバージョンに留まりました。顧客は部分的に壊れたリリースを持っており、残りの艦隊は異なるバージョンを実行しており、明確な説明はありません。
調査は5つのチェックに続きました:
- リリースフィードを確認する バイナリは存在しましたが、期待されるメタデータは明確にクライアントが受け取るべきものを示していませんでした。マニフェストはリリースパイプラインとインストール済みクライアントとの契約であり、オプションのアップロード詳細ではありません。
- 署名を検査してください。 署名が正しくないため、影響を受けるプラットフォームで検証が失敗しました。署名は欠落または無効の場合に発行をブロックする必要があります。
- クライアントログを比較してください。 アップデートエラーは中央のテレメトリに届かなかった。アプリケーションはイベントを飲み込んで実行を続け、チームには信頼できる証拠が得られませんでした。
- ロールアウト制御を確認してください。 内部チャネルまたはステージドコホートは存在していませんでした。すべての有効なクライアントは同じフィードを使用していたため、失敗は拡散し、収束点が存在しませんでした。
- ロールバックを探してください。 チームにはテスト済みの手順が存在していませんでした。前のバージョンを再発行したり、クライアントを破綻したリリースから遠ざける方法を提供するものではありませんでした。
Electronの公式ドキュメントではプラットフォームの制限が明確に記載されています。 Linuxには組み込みの自動アップデートサポートが存在しません。、macOSのアップデートリクエストは満たす必要があります App Transport Security の要件ドキュメントでは、信頼性の高い macOS の更新とリリースの検証のために署名が必要であることも指摘されています。 Electron の autoUpdater ドキュメント API の制約を定義するのは Electron の autoUpdater ドキュメントですが、リリースシステムは周辺の運用制御を強制する必要があります。
Postmortem の教訓: 説明ができないアップデートは、不完全なテレメトリとともにリモートのインストール試行です。
コストはエンジニアリング時間の他に、顧客の信頼を失い、サポートが不一致な動作を説明し、チームがリリースプロセスを再構築するのに費やした 1 日の労働時間にまで及んだ。
自動更新を運用システムとして扱う 署名はリリースゲート、manifests はクライアント契約を定義し、ロールアウトチャネルは露出を制限し、ロールバックはテスト済みのパスであるべきであり、緊急の発明ではならない。Electron のアップデートパスを選択する
2 時間後の間違ったアップデートの選択は運用上の問題となる。ネイティブバイナリの更新は署名、manifests、インストーラー、ロールバックを処理する必要がある。一方、レンダラーのみの JavaScript または CSS の変更は別のパスを辿る。ホスティングの制約も考慮される: 小規模な __CAPGO_KEEP_0__ ホストされたプロジェクトには、企業向けの配布サービスと同じリリース制御が必要ではない。
At 2 a.m., the wrong updater choice becomes an operational problem. A native binary update must handle signing, manifests, installers, and rollback. A renderer-only JavaScript or CSS change follows a different path. Hosting constraints also matter: a small GitHub-hosted project does not need the same release controls as an enterprise distribution service.
Electron Builder を使用するプロジェクトの場合、署名アーティファクトの公開とともに、 electron-updater 通常、実用的デフォルトです。 Electron updater integration for Capgo 複数のホスティングモデルをサポートしていますが、チームは署名、フィードの可用性、チャンネルポリシー、ロールアウト制御、監視を所有しています。
update-electron-app suits teams that want a small integration around GitHub Releases. It checks at startup and then on a recurring interval, which keeps the setup simple but leaves less room for advanced channel selection, staged traffic, and custom rollback rules. The package is reasonable for a small release process, provided GitHub Releases and its availability match your operational requirements.
| を評価する際に、ウェブ層のバンドルとネイティブのリリースのハイブリッド配信モデルを検討する際に関連しています。 | チームが小規模な統合を必要とする __CAPGO_KEEP_0__ リリースに対して適しています。 | 起動時と定期的な間隔でチェックし、設定が簡単ですが、進んだチャンネル選択、ステージドトラフィック、カスタムロールバックルールの余地が少なくなります。 | 小規模なリリースプロセスに適したパッケージですが、__CAPGO_KEEP_1__ リリースとその可用性が運用要件と一致する場合に限ります。 | オプション |
|---|---|---|---|---|
| ホスティングの制御はありません。署名のサポートはありません。チャンネルとステージドロールアウトはありません。メンテナンスの負担はありません。electron-updater | S3、GitHub、汎用HTTPS、他社の公開先 | リリースされたパッケージと統合された署名 | 強固な基盤、カスタムポリシーは通常フィードの周りで動作 | 普通 |
| update-electron-app | GitHubリリースワークフローが主に簡単 | Electronの下位の署名モデルを使用 | 制限が少ない、サーヴィスを追加するまで | 低 |
| Squirrel.WindowsまたはSquirrel.Mac | プラットフォームに特化した配布フロー | プラットフォームの署名要件に依存 | 可能ですが、通常は追加のリリースインフラが必要です。 | レガシーアプリケーション向けのモジュレート |
| カスタムサービス | マニフェスト、認証、コホート、フィードの完全な制御 | 検証設計とキー管理を自社で行う | 最大限の柔軟性 | __CAPGO_KEEP_0__ ライブアップデート |
| Capgo live updates | アップデータと配信モデルを使用 | ターゲットアウディエンスとチャネルベースの配信 | ネイティブバイナリアップデートから運用モデルを分離 | 可能ですが、通常は追加のリリースインフラが必要です。 |
Azure、Hazel、Nutsなどのカスタムサービスが必要なのは、リリースの承認、テナントのターゲット設定、監査レコード、または規制されたデプロイのルールが実装コストを正当化する場合です。トレードオフは、継続的な所有権です。チームはマニフェストの意味を定義し、署名キーを保護し、クライアントの互換性を維持し、ダウンロードの失敗、リリースの拒否、ロールバックの動作をテストする必要があります。
ライブアップデートはレンダラーのみの変更を送信できます。レンダラーのシェルを再構築する必要はありません。Electron、ネイティブモジュール、パーミッション、またはインストーラーの動作が変更された場合、バイナリアップデートは置き換えられません。 electron-updaterを使用する場合は、カスタムロールアウトロジックが必要な場合のみです。 カスタムロジックが必要な場合は、既存のマニフェストとアーティファクトの慣習を基に構築するのではなく、ダウンロードと差分アップデートの動作を再作成するのではなく、依存できるパスを選択してください。チームは、プレッシャー下でも観察、ステージ、逆行できるようにする必要があります。
メインプロセスでAuto-Updateフローを実装する
メインプロセスはアップデートのチェックとインストールを所有する必要があります。レンダラーはステータスを表示できますが、実行可能なアップデートを信頼するか、またはアプリケーションが終了するかどうかを決定することはできません。
まずパブリッシュターゲットを設定する
最小限のelectron-builderの構成は次のようになります。
{
"build": {
"appId": "com.example.desktop",
"publish": [
{
"provider": "s3",
"bucket": "example-electron-releases",
"channel": "stable"
}
],
"nsis": {
"oneClick": false,
"allowToChangeInstallationDirectory": true
}
}
}
ベータとステーブルフィードを分離する。チャネルはUIのラベルではなくリリースポリシーです。各チャネルは正しい署名されたアーティファクトとマニフェストに解決する必要があります。
チェックのスケジュールとライフサイクルイベントを公開する
Calling checkForUpdates() 起動時のみ、一般的な生産性の低下の原因となる。ユーザーはアプリケーションを開いたままにし、数日間続けることがあるため、メインプロセスには制御された間隔とリトライ戦略が必要であり、オフライン操作を尊重する必要がある。
const { app, BrowserWindow, ipcMain } = require('electron');
const { autoUpdater } = require('electron-updater');
let mainWindow;
let isQuitting = false;
let retryDelay = 60 * 1000;
function sendUpdateStatus(status, payload = {}) {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.webContents.send('update-status', { status, ...payload });
}
}
function scheduleUpdateCheck() {
setTimeout(async () => {
try {
await autoUpdater.checkForUpdates();
retryDelay = 60 * 1000;
} catch (error) {
sendUpdateStatus('error', { message: error.message });
retryDelay = Math.min(retryDelay * 2, 30 * 60 * 1000);
}
scheduleUpdateCheck();
}, retryDelay);
}
app.whenReady().then(() => {
mainWindow = new BrowserWindow({
webPreferences: {
preload: require('path').join(__dirname, 'preload.js')
}
});
autoUpdater.autoDownload = true;
autoUpdater.autoInstallOnAppQuit = false;
autoUpdater.on('checking-for-update', () => {
sendUpdateStatus('checking');
});
autoUpdater.on('update-available', info => {
sendUpdateStatus('available', { version: info.version });
});
autoUpdater.on('download-progress', progress => {
sendUpdateStatus('progress', { percent: progress.percent });
});
autoUpdater.on('update-downloaded', info => {
sendUpdateStatus('downloaded', { version: info.version });
});
autoUpdater.on('error', error => {
sendUpdateStatus('error', { message: error.message });
});
autoUpdater.checkForUpdates().catch(error => {
sendUpdateStatus('error', { message: error.message });
});
scheduleUpdateCheck();
});
ipcMain.handle('install-update', () => {
isQuitting = true;
autoUpdater.quitAndInstall(false, true);
});
app.on('before-quit', event => {
if (!isQuitting) {
return;
}
});
アップデートイベントの正確な動作はプラットフォームとパッケージング設定によって異なるため、開発モードではなくインストール済みアーティファクトからテストする。Electronのドキュメントでは、Windowsでの起動タイミングに関する懸念事項を呼び出しており、Squirrelの初回起動ケースも含まれている。アプリケーションが必要なプラットフォーム固有の初期化を完了するまで、アップデートチェックをトリガーしないようにする。
ワークをブロックせずにレンダラーに情報を伝える
プリロードブリッジは、狭いAPIを公開するべきである:
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('updates', {
onStatus(callback) {
ipcRenderer.on('update-status', (_event, status) => callback(status));
},
install() {
return ipcRenderer.invoke('install-update');
}
});
レンダラー側の進行状況バーは、意図的に単純なままにすることができる:
window.updates.onStatus(status => {
const progress = document.querySelector('#update-progress');
const message = document.querySelector('#update-message');
if (status.status === 'progress') {
progress.hidden = false;
progress.value = status.percent;
message.textContent = `Downloading update, ${Math.round(status.percent)}%`;
}
if (status.status === 'downloaded') {
message.textContent = `Version ${status.version} is ready to install`;
}
if (status.status === 'error') {
message.textContent = 'The update could not be downloaded. We will retry later.';
}
});
生産環境ではユーザーの同意を得ることでインストールを遮断する。すぐに再起動する必要があるアプリケーションがなければ、旗をセットする。 isQuitting 旗をセットする前に、 quitAndInstall()通常のウィンドウクローズハンドラーがインストーラーが制御を取るのを防ぐのを防ぐため、

2 つの失敗は明示的なテストに値する。最初に、すでに実行中のクライアントはスケジュールに呼び出し、起動時のみに呼び出すのではなく。2 番目に、イベントはログとテレメトリに到達する。アプリケーションがイベントを報告せずに飲み込むと、 checkForUpdates() アプリケーションがイベントを報告せずに飲み込むと、 error アプリケーションがイベントを報告せずに飲み込むと、 アプリケーショントラブルシューティングワークフロー 証拠ではなく推測から始まる
CI/CDを有効にするための署名されたリリースとマニフェスト
リリースパイプラインはユーザーがインストールするものの真実の元です。開発者1人のマシン上で動作するローカルビルドは、公開されたバイナリ、マニフェスト、署名、チャネルがすべて同じリリースを表すことを証明するものではありません。
Electron-builderのpublishモデルは、リリースメタデータとアップデートのターゲットが一緒に移動することを期待しています。多くの構成では、リリースメタデータとアップデートのターゲットが一緒に移動することを期待しています。多くの構成では、プラットフォーム固有のパッケージとブロックマップファイルとともに、Windows用の latest.yml macOS用の latest-mac.yml リリースメタデータとアップデートのターゲットが一緒に移動することを期待しています。多くの構成では、プラットフォーム固有のパッケージとブロックマップファイルとともに、Windows用の
macOS用の
A simplified GitHub Actions pattern looks like this:
name: release
on:
push:
tags:
- "v*"
jobs:
build:
strategy:
matrix:
os: [macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 24
cache: npm
- run: npm ci
- run: npm run test
- run: npm run build
- name: Build and publish
shell: bash
env:
CSC_LINK: ${{ secrets.CSC_LINK }}
CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }}
WIN_CSC_LINK: ${{ secrets.WIN_CSC_LINK }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: npx electron-builder --publish always
署名をCIで明示的に指定する
| Actionsパターンは次のようになります。 | プラットフォーム固有のシークレットを使用し、署名材料をリポジトリ外に保管する。署名が失敗した場合、ジョブを停止し、手動でアップロードされる署名なしのフォールバックを生成しないようにする。 |
|---|---|
CSC_LINK |
macOS証明書または証明書参照 |
CSC_KEY_PASSWORD |
macOS署名材料のパスワード |
WIN_CSC_LINK |
Windows証明書または証明書参照 |
AWS_ACCESS_KEY_ID |
限定されたアクセスを持つ公開資格情報 |
AWS_SECRET_ACCESS_KEY |
公開資格情報のシークレット |
公開設定では、プロバイダーとチャネルを一貫して識別する必要があります:
{
"build": {
"publish": {
"provider": "s3",
"bucket": "example-electron-releases",
"channel": "stable",
"publishAutoUpdate": true,
"updaterCacheDirName": "example-desktop-updater"
}
}
}
パッケージバージョン、タグ、コミットSHA、smokeテスト結果でジョブをゲートする。公開後、フィードに期待どおりのマニフェストが含まれていることを確認し、マニフェストが生成したジョブによって生成された正確なアーティファクトを指していることを確認します。 継続的インテグレーションの設定ガイド チェックを正式化する際に役立ち、パイプラインオーケストレーションを比較するチームも、JenkinsとAnsibleを組み合わせるタイミングを理解することで利益を得ることができます。 一般的に不完全なリリースを露出するコマンドは意図的に面白みがなくてすみません:.
チェックは署名されたインストールテストを置き換えるものではありません。ただし、クライアントがそれを発見するために必要なメタデータがアップロードされたバイナリが存在しないことを操作上のミスで捕捉します。
npx electron-builder --publish never
test -f dist/latest.yml
test -f dist/latest-mac.yml
find dist -name "*.blockmap" -print
macOS証明書または証明書参照
ロールアウト、チャンネル、ロールバック戦略
リリースフィードは、展開先としてではなくダウンロードフォルダとして振る舞うべきです。内部 内部, ベータ、 最新 チャンネルを分離し、各チャンネルは独自のマニフェストと署名アーティファクトセットでサポートされるようにします。プロモーションは、テストされたリリースをポリシー間で移動するのではなく、クライアントがダウンロード中のファイルを上書きしないようにします。
チャンネル分離は、誤ってテストビルドが生産環境に流れ込まないように保護します。アップデーターは、クライアントが内部コホート、ベータアウディエンス、または安定した人口に属しているかを判断する前に、フィードを評価する必要があります。
コホートを使用する前に広範な露出を避ける
カスタムマニフェストフィールドは、ステージングされた配信を表現できます:
version: 4.8.0
path: Example-Setup-4.8.0.exe
sha512: signed-artifact-hash
rolloutPercentage: 10
メインプロセスは安定したユーザーごとのバケットを割り当て、次にそのバケットを rolloutPercentageと比較します。安定した割り当ては重要です。ユーザーが毎回有効または無効の状態に切り替わると、不確実な動作を受け、サポートの報告が難しくなります。
リリースが観察期間を乗り越えた後、コホートを拡大する。観察期間の正確な期間は、利用パターンに基づいて反映するべきですが、決定はシグナルに基づいて行うべきであり、カレンダーだけに依存してはなりません。アップデートチェック結果、ダウンロード完了、起動正常性、クラッシュ、レンダラー例外、認証成功を追跡する。
| シグナル | アクション | 理由 |
|---|---|---|
| フィードまたは署名エラーがチームの承認制限を超えます | ロールアウトを保留 | クライアントがリリースを検証または検出できない可能性があります |
| ポストアップデート起動チェックが失敗します | フィードを戻す | バイナリがインストールされるかもしれませんが、起動中に失敗する可能性があります |
| レンダラー例外がプロモーション後にも増加する | 現在のコホートで保留する | The native installer may be healthy while the new application code is not |
| 信号はリリース予算内に残っています。 | コホートを拡大する | 証拠はより広範な露出を支持しています。 |
ロールバックを削除したアーティファクトと混同しないでください。既存のクライアントにはキャッシュされたメタデータがあり、あるいはすでに悪いバージョンを実行している可能性があります。ロールバック計画には前の署名されたリリース、フィードの変更、クライアントの動作が必要です。クライアントは元のバージョンに戻ることができます。
運用規則: ロールバックは、インシデント中のアプリケーションを再構築せずに、オンコールエンジニアが実行できる必要があります。
実際には、ランブックは影響を受けたチャネルに前のリリースマニフェストをプロモートし、ステージングマーカーを無効化し、新しいチェックが安全なバージョンに解決されることを確認する必要があります。問題はレンダラー code ではなくネイティブシェルにある場合、ターゲットされたウェブ層ロールバックが速くなります。ウェブ層ロールバックとは別の配信レイヤーでは、code フェイズドロールアウトのようなプラットフォームが関連性がありますが、ネイティブバイナリロールバックとウェブバンドルロールバックの境界を曖昧にすることは避けるべきです。 Capgo phased rollouts Electronのアップデートャーは実行可能な __CAPGO_KEEP_0__ をダウンロードし、ユーザーが少ないインタラクションでインストールすることができます。そのため、更新パスは
__CAPGO_KEEP_0__ フェイズドロールアウト
An Electron updater downloads executable code and can install it with little user interaction. That makes the update path a セキュリティ境界セキュリティ上の問題であり、単に便利な機能ではありません。Electronの公式ドキュメントでは、macOS ATSなどのプラットフォーム制約について説明されており、セキュリティカバレージは2022年のシナリオを文書化しており、攻撃者が更新インフラストラクチャを制御することで、まだcode署名チェックを通過する可能性のある悪意のあるパッケージを提供することができたことを説明しています。 Electron Builderの自動更新セキュリティドキュメント.
Code署名は基本的なものですが、信頼モデル全体ではありません。すべてのリリースを署名し、CIで証明書とアイデンティティを検証し、ドキュメント化されたキーローテーション手順を維持してください。macOSでは署名と認証とハード化されたランタイムを組み合わせて、適切なアプリケーションに応じてください。Windowsでは、証明書の所有権、更新、ビルドへのアクセスを監査してください。Linuxでは、Electronが提供する統一的なアップデータを提供していないため、ディストリビューション固有の戦略が必要です。
メタデータもバイナリと同じように保護する必要があります。
署名されたバイナリは、メタデータチャネルが妨害または不正設定されている場合に、間違ったリリースと関連付けられる可能性があります。パブリックキーをアプリケーションに埋め込んだものとして、メニifest署名を検証し、最低許可されたバージョンを強制し、予期せぬダウングレードを拒否することを検討してください。
フィードにも生産管理が必要です:
- パブリッシュアクセスを制限する: CIにリリースアセットをパブリッシュするための必要な権限だけを与えます。
- 署名シークレットを保護する: 証明書と秘密鍵をマネージドシークレットストレージに保管し、リポジトリファイルにしないでください。
- 依存関係を固定する: CIでElectron、electron-builder、依存関係を固定する。
- アーティファクトを確認する: 生成されたパッケージを確認し、意図したコミットとバージョンと比較する。
- 安全なトランスポートを要求する: 更新要求にATSと厳密なHTTPS要件を遵守する。
- 検証失敗を監視する: 署名またはマニフェストの繰り返し失敗をセキュリティイベントとして扱い、通常のネットワークノイズと区別する。
Electronのメンテナンスされたツールキットは、パッケージングとアップデートのカバレッジを追加していますが、脅威モデリングの必要性は維持されます。実際の目標は、攻撃者がバケット、CDN、またはビルドステップを乗っ取っても、クライアントが承認されていないリリースを受け入れないようにすることです。 署名検証ガイドライン 脅威モデリングの追加検証層を設計するための有用なコンテキストを提供します。

生産用更新の実行書とチェックリスト
リリースは、他のエンジニアがプレッシャー下でも操作できるようになるまで待つ必要があります。デプロイジョブとインシデントチャンネルにチェックリストを近づけてください。
前リリースゲート
- バージョン識別: パッケージバージョン、リリースタグ、コミットSHA、変更履歴が一致していることを確認してください。
- 署名: すべてのプラットフォームアーティファクトが署名され、認証または同等の検証が完了していることを確認してください。
- マニフェスト契約: 確認
latest.yml,latest-mac.ymlアップロードされたアーティファクトのハッシュ、パス、ブロックマップと一致していることを確認してください。 - チャンネル安全性: 内部またはベータフィードに公開する前にリリースチャンネルを昇格することを確認してください。
- メトリクス: 確認更新チェック、ダウンロード進捗、インストール完了、起動正常性、エラーの到着はあります。
カニラとフルロールアウト
- コホート制御: 内部またはベータ版の意図的に小さな内部またはベータ版のユーザーから始めます。
- ヘルスバジェット: リリースの失敗、更新ダウンロードの失敗、レンダラー例外、または認証の失敗がチームの承認された制限を超えると、プロモーションを保留します。
- プロモーション承認: リリースを安定したフィードに移動する前に、明確な「はい」または「いいえ」の決定を必要とします。
- 顧客への影響: 広範な配布前に、最初のインシデント後にサポートメッセージを準備するように準備してください。
インシデント対応
新ビニヤリが起動しない場合、プロセス生成が途切れ、または更新ダウンロードが完了しない場合、即時停止します。前の署名されたマニフェストを復元し、ステージングマーカーを無効化し、最新のクライアントが前のバージョンに解決することを確認します。次に、テレメトリを通じて艦隊が回復していることを確認する前に、閉鎖を伝えます。
提供元によっては、ロールバックコマンドの詳細は異なりますが、シーケンスは常にドキュメントされるべきです: 前のバージョンのチャネルマニフェストを切り替え、ステージングタグを無効化し、回復が必要な場合は強制更新マーカーをプッシュし、ライブテレメトリを通じてダウングレードパスを検証します。テストされていないロールバックはただの希望です。

Capgoは、各レンダラー変更でネイティブシェルを再構築することなく、署名されたウェブ層変更を配信するためのElectronアップデータを提供し、ターゲットチャネル、ロールアウト制御、更新観察性を提供します。ネイティブバイナリーリリースを制御されたJavaScriptとCSS配信から分離したい場合は、 Capgo を参照してください。