キャラデータの配信(リソースパック)
新キャラの名前・コスト・画像を、アプリのリリースと再起動なしでユーザーに届ける仕組みの運用手順。 設計は docs/superpowers/specs/2026-10-15-cdn-resource-update-design.md。
仕組み
| どこ | 何をする |
|---|---|
GitHub Actions publish-resources | main で src/data/characters.json / public/images/starward/** / 版が変わったら、パックを組み立てて署名し Cloudflare Pages wingstats-resources に公開 |
Cloudflare Pages wingstats-resources | latest.json(いま配っている版)・packs/<版>/manifest.json・blobs/<sha256>.* を配る。無料枠で足りる |
| アプリ(Recorder / 単独の Manager) | 起動 30 秒後・6 時間ごと・キャラ DB に無いキャラを保存したときに確認。手元に無いファイルだけを取り、署名と sha を確かめて <userData>/resources/ に置く |
| アプリ(全プロセス) | <userData>/resources/active.json を見て、同梱より新しい版なら使う。新キャラが届くと管理画面に「新キャラのデータを取り込みました」 |
- 配るのはデータ(JSON)と画像だけ。コードはこれまでどおりアプリ更新で配る
- 版は
src/data/characterDataVersion.tsのBUNDLED_CHARACTER_DATA.version(YYYYMMDDnn)。yarn update-charactersが自動で上げる - アプリ更新で同梱の版が配信に追いついたら、自動で同梱に戻る
- 配信を読めるのは、この仕組みを含むリリース以降のアプリだけ。それより前のアプリは同梱のままなので、移行期間に新キャラを急いで届けたいときは従来どおり patch リリースする
最初に 1 回だけやること
- Cloudflare で Pages の編集権限を持つ API トークンを発行する
- GitHub の Secrets に 2 つ入れる
CLOUDFLARE_API_TOKEN: 1 のトークンRESOURCE_PACK_SIGNING_KEY: 署名用の秘密鍵(PEM 本文)。開発者の PC で次を実行すると、画面に出さずに登録できるbashgh secret set RESOURCE_PACK_SIGNING_KEY --repo mouriman2/broadcast-Overlay < "$USERPROFILE/.config/wingstats/resource-pack-signing-key.pem"
- Actions の
publish-resourcesを Run workflow で一度手動実行し、https://wingstats-resources.pages.dev/latest.jsonが返ることを確かめる
Pages プロジェクト wingstats-resources は、無ければワークフローが初回に作る。アカウント ID はワークフローに書いてある(秘密ではない)。
キャラを足したとき
add-character スキル(または Add New Character)の手順で chars/* → main にマージすれば、 publish-resources が自動で走る。キャラだけのために patch リリースする必要はない(次のリリースで同梱も追いつく)。
確認:
gh run list --workflow publish-resources --limit 3
curl -s https://wingstats-resources.pages.dev/latest.jsonアプリ側は「設定 → デバッグ・性能 → キャラデータ」で、使っている版と最後の確認結果を見られる。「今すぐ確認」で 6 時間を待たずに取りに行ける。
ネタキャラ(ボブ・デイビッド・ヘンリー)
ID 9001〜9003 のボブ(コスト 3)・デイビッド(2.5)・ヘンリー(2)は、ゲームに居ないネタのキャラ。リリースのたびに残すため、 同梱の src/data/characters.json("joke": true 付き)と public/images/starward/{30,25,20}/{bob,david,henry}.png に置いてある。 配信だけに入れると、アプリ更新で同梱の版が追いついた時点で同梱に戻って消えるので、同梱側に入れている。
- 消さない。
src/data/__tests__/jokeCharacters.test.tsが、データか画像が欠けたら落ちる update-charactersは足す・書き換えるだけで消さないので、キャラ追加で巻き込まれることはない- 画像は Pexels の写真(Pexels ライセンス)
壊れたデータを出してしまったとき
直したデータを main に入れて publish-resources を走らせれば、新しく発行された latest.json に全員が従う (版の番号が前より小さくても、発行時刻が新しければ従う)。同梱より古い版を配ると、アプリは手元の版を外して同梱に戻る。
手元で試す
# CDN に置く形で書き出す
yarn resources:build --out ./tmp-resource-pack --key %USERPROFILE%\.config\wingstats\resource-pack-signing-key.pem
# ダウンロードを経ずに、サンドボックスの userData に入れて使う版にする
yarn resources:build --install <userData のパス> --key <秘密鍵> --data-version 2099010100WINGSTATS_RESOURCE_BASE_URL=http://127.0.0.1:<port>で配信元を手元の HTTP サーバに差し替えられる- 開発中(未パッケージ)に限り、
WINGSTATS_RESOURCE_PACK_PUBLIC_KEY=<PEM ファイル>で検証に使う公開鍵を差し替えられる(別の鍵で作ったパックを試すとき)
CDN で試験配信する
本番(https://wingstats-resources.pages.dev の latest.json)には触らずに、Cloudflare Pages の別の URL に 試験用のパックを置き、手元のアプリだけをそこへ向けて確かめる。
試験用のパックを作る。本物のキャラに、
scripts/resources/test-characters.jsonの試験キャラ(ボブ(試験)・デイビッド(試験)・ ヘンリー(試験)。ID 9101〜9103、画像は Pexels の写真)を足し、版を2099010101にしてtmp/resource-pack-testに書き出すbashRESOURCE_PACK_SIGNING_KEY="$(cat "$USERPROFILE/.config/wingstats/resource-pack-signing-key.pem")" yarn resources:build:testCloudflare Pages の
previewという名前で置く(本番はmain。別の名前なら本番には出ない)。初回だけログインとプロジェクト作成が要るbashnpx wrangler@3.114.0 login npx wrangler@3.114.0 pages project create wingstats-resources --production-branch main npx wrangler@3.114.0 pages deploy tmp/resource-pack-test --project-name wingstats-resources --branch preview置いた先は
https://preview.wingstats-resources.pages.dev(/latest.jsonが返れば OK)空のサンドボックスで起動したアプリを、試験 URL へ向ける。版
2099…のパックは一度入ると以後の本物の配信より新しい扱いになるので、 普段使っている userData(%APPDATA%/streaming-overlay-manager)では試さないbashWINGSTATS_RESOURCE_BASE_URL=https://preview.wingstats-resources.pages.dev yarn dev:electron:fresh設定 → デバッグ・性能の「キャラデータ」カードで、「使っているデータ」が
2099/01/01の配信になり、 「配信で増えたキャラ」に試験キャラが画像つきで並べば成功。届いていなければ「今すぐ確認」を押す
試験キャラを変えるときは test-characters.json を直す(ID は本物と重ならない番号。画像は PNG を返す URL か、JSON からの相対パスのファイル)。 --extra は --data-version と一緒でないと使えない(試験用の版を本番の版と混ぜないため)。CI(publish-resources)は --extra を使わない。
署名鍵を入れ替えるとき
- 新しい Ed25519 の鍵ペアを作る
- 新しい公開鍵を
electron/services/resources/resourcePackSignature.tsのRESOURCE_PACK_PUBLIC_KEY_PEMに入れてアプリをリリースする - 新しいアプリが行き渡ったら、
RESOURCE_PACK_SIGNING_KEYを新しい秘密鍵に替える
古いアプリは新しい鍵の署名を受け付けないので、入れ替え後に配ったデータは古いアプリには届かない(同梱のまま動く)。