Tauri v2 Updaterをlocal mock serverで検証する
Tauri updaterのテストは、静かに失敗することがあります。アプリは起動する、update bannerは出ない、UI上のerrorも薄い。その状態だけでは、updater codeが間違っているとは言えません。
local testでは、署名済みupdater artifact、有効なupdater JSON、WebViewからfetchできるmock server、local HTTPを許可するtest-only設定の4つが揃っている必要があります。
この記事では、UIの見た目から推測するのではなく、request logでどこまで進んだかを確認する手順を整理します。
症状: update checkしてもbannerもerrorも出ない
典型的な失敗はこうです。
- frontendまたはRust側で
check()は実行される - アプリは現在versionのまま
- update bannerが出ない
- mock serverにrequestが来ない、または1回だけ来る
- production updater endpointは関係していない
原因はいくつかあります。artifactが署名されていない、JSONのsignatureが違う、WebViewがCORSでmock serverを拒否している、HTTP endpointをTauriが拒否している、などです。
UIを書き換える前に、requestがどこで止まっているかを証明します。
先に署名済みupdater artifactを作る
Tauri updaterのinstallには署名が必要です。通常のinstallerだけでは、現実的なupdater testになりません。
updater artifactを作るrelease build commandを実行します。
npm run tauri -- build --features updater --config src-tauri/tauri.updater.conf.json
次に、期待するsignatureがあるか確認します。
Get-ChildItem src-tauri\target\release\bundle\nsis -Filter *.sig
.sigファイルがないなら、そこで止めます。mock serverでは欠落したupdater artifactは直せません。
updater JSONとinstallerをlocal mockで配信する
各requestをlogに出す小さなserverを使います。logが最初の証拠です。
const http = require("node:http");
const fs = require("node:fs");
const path = require("node:path");
const port = 8899;
const bundleDir = path.join("src-tauri", "target", "release", "bundle", "nsis");
const installerName = "my-app_1.0.1_x64-setup.exe";
const signatureName = `${installerName}.sig`;
const server = http.createServer((req, res) => {
console.log(`${req.method} ${req.url}`);
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
if (req.method === "OPTIONS") {
res.writeHead(204);
res.end();
return;
}
if (req.url === "/updater.json") {
const signature = fs
.readFileSync(path.join(bundleDir, signatureName), "utf8")
.trim();
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({
version: "1.0.1",
notes: "Local updater test",
pub_date: new Date().toISOString(),
platforms: {
"windows-x86_64": {
signature,
url: `http://127.0.0.1:${port}/${installerName}`
}
}
}));
return;
}
if (req.url === `/${installerName}`) {
const installerPath = path.join(bundleDir, installerName);
res.writeHead(200, {
"Content-Type": "application/octet-stream",
"Content-Length": fs.statSync(installerPath).size
});
fs.createReadStream(installerPath).pipe(res);
return;
}
res.writeHead(404);
res.end("not found");
});
server.listen(port, "127.0.0.1", () => {
console.log(`Updater mock server listening on http://127.0.0.1:${port}`);
});
CORS headerは飾りではありません。updater requestはWebView runtimeから行われます。curlでは読めるlocal serverでも、browser layerが拒否すればアプリ内では失敗します。
HTTP用のtest configを一時的に追加する
productionのupdater endpointはHTTPSにするべきです。local mock serverだけ、test-only configでHTTPを許可します。
{
"plugins": {
"updater": {
"endpoints": ["http://127.0.0.1:8899/updater.json"],
"dangerousInsecureTransportProtocol": true
}
}
}
この設定をproduction release configに入れないでください。名前の通り、insecure transportを許可します。local testには便利ですが、実配布には不適切です。
繰り返し使うなら、ファイル名も明確にします。
src-tauri/tauri.updater.local-test.conf.json
build toolが複数configをmergeできるなら、updater overlayとlocal endpoint overlayを両方適用します。できない場合は、local test用のcombined configを作ります。
request、download、install、relaunchを順に確認する
まずmanifest requestを確認します。
GET /updater.json
mock serverにこのrequestが来ないなら、アプリはendpointに到達していません。endpoint config、feature gate、plugin initialization、HTTP許可を確認します。
次にinstaller requestを確認します。
GET /my-app_1.0.1_x64-setup.exe
manifest requestだけ来る場合は、JSON fieldを見ます。
versionがinstalled app versionより新しいplatforms.windows-x86_64.urlが配信しているinstallerまたはupdater bundleを指しているplatforms.windows-x86_64.signatureに.sigファイルの中身が入っている- mock serverが
200を返している
最後にinstall behaviorを確認します。Windowsでは、install stepでアプリが終了することがあります。UIが消えたから失敗とは限りません。relaunch後に新versionが起動するか確認します。
mock testとrelease configを分ける
よいupdater test setupには明確な境界があります。
- production configはHTTPSを使う
- local mock configだけHTTPを許す
- production configでは
dangerousInsecureTransportProtocolを有効にしない - local mock serverはrequestをすべてlogする
- test artifactは使い捨てにする
local endpointをrelease build用の設定ファイルに混ぜないでください。急いだrelease時に見逃しやすい危険になります。
troubleshooting checklist
アプリコードを変える前に、この順で見ます。
- buildで
.sigファイルが生成されているか - mock serverが起動し、
/updater.jsonを返すか - アプリが
/updater.jsonをrequestしているか - アプリがinstallerまたはupdater bundle URLをrequestしているか
- JSONのversionがinstalled app versionより新しいか
- signature fieldはpathではなくfile contentか
- HTTP許可はlocal test configだけに入っているか
- install後にrelaunchまたは新version確認ができるか
この順番なら、missing signatureをUI bugと誤認したり、CORS失敗をupdater APIの問題と誤認したりしにくくなります。
参考
- Tauri updater plugin
- Tauri process plugin
- Tauri v2 Updaterビルドは設定overlayを分ける
- VitestでTauri Zustand storeをテストする: IPC mockとsingleton reset
まとめ
local updater testでは、network path、manifest、署名済みartifact、install stepをそれぞれ証明します。CORS header付きmock serverを使い、HTTP許可はtest configだけに置き、UIより先にrequest logを確認します。