金曜日にホットフィックスを出した。月曜になっても、サポートにはホットフィックスを受け取れていないユーザーからの連絡が続き、ベータテスターは古いbundleのまま。さらに、あるエンタープライズ顧客は現場チームがどのバージョンを実行しているか正確に知りたがっている。その時、はっきりする—— アプリの更新通知 は単なるモーダルではない。リリース制御のためのOSだ。
Capacitor や Electron プロジェクトにおいて、アップデートの存在を検知すること自体は、実はそれほど難しくありません。本当に難しいのは、その周辺の設計です。誰に、いつ通知すべきか、無視された場合にどう扱うか、CI/CD パイプラインでの更新フロー、そしてロールアウト後のテレメトリから何を読み取るか。アップデートのプロンプトを単なる UI の飾りとして扱うと、ノイズの多い通知や脆弱なリリースロジック、そしてユーザーの混乱を招きます。逆に、プロダクトのライフサイクルの一部として捉えれば、より安全なロールアウトが可能になり、サポートへの問い合わせも劇的に減らすことができます。
目次
- アプリのアップデート戦略が重要な理由
- Capgo を使ったアップデート検知の実装
- 効果的な通知パターンの設計
- アップデートフローの自動化とユーザーの選択肢
- ChannelsとTelemetryを活用した高度なロールアウト
- よくある通知問題のトラブルシューティング
アプリのアップデート戦略が重要な理由
アップデートは単なる保守ではなく、継続率に影響する
多くのチームは、アップデートを単なる「保守作業」と捉えがちです。「バグを直して、ユーザーに促して、次へ」。この考え方では、プロダクトへの影響を見落としてしまいます。
プッシュ通知は、インストール後にユーザーをアプリへ呼び戻すことができる数少ないライフサイクルチャネルの一つです。以下にまとめたデータは、 Invespのモバイルプッシュ通知に関する研究では、 プッシュ通知によってアプリのエンゲージメントを 最大88%向上させることができ、通知を許可したユーザーの継続率は、 許可していないユーザーの 約2倍に達します。アップデート戦略においてこれが重要なのは、古いバージョンのままのクライアントは、あなたがリリースした新機能や修正、コンプライアンス対応を二度と目にすることのないユーザーになり得るからです。
不十分なアップデートフローは、通常、以下の3つの問題を同時に引き起こします:
- プロダクトの停滞 新機能のリリースが不均一になり、PMが分析データから一貫性のないシグナルを受け取ることになります。
- サポートの負担 サポート担当者が、問題を再現する前にスクリーンショットやバージョン、デバイス情報を聞かなければならないときに表面化します。
- セキュリティリスク 古いクライアントが、すでに更新されたAPIにアクセスし続けることで拡大します。
実践的なルール: アップデートの配信を、スプリントの最後に出す単なる「お知らせ」ではなく、リリース管理の一環として捉えてください。
ストア更新とLive Updatesは解決する問題が異なります
App StoreやPlay Storeのアップデートは依然として重要です。ネイティブ依存関係の変更、ポリシーに基づくリリース、権限の変更、バイナリレベルの修正はストア更新の領域です。しかし、ストア経由のアップデートはシステムの一層に過ぎず、審査とユーザーの更新が直接コントロールできないため、設計上遅くなります。
CapacitorやElectronアプリでは、Live Updatesは異なるカテゴリの作業をカバーします。JavaScript、CSS、テキスト、アセット、フィーチャーフラグなど、新しいバイナリを必要としないWeb bundleの変更に適しています。実務的には、リリースに関する2つの問いを切り離せます。
| リリースに関する問い | 最適 |
|---|---|
| この変更に新しいネイティブバイナリは必要か? | ストアリリース |
| この変更はWeb bundleとして安全に配信できますか? | Live update |
| 続行する前にユーザーへの通知は必要ですか? | アプリ内通知の判断 |
| 今、一部のユーザーだけに必要ですか? | Channelベースのロールアウト |
その使い分けこそ、クライアントアプリを開発するエージェンシーが単一の「アップデートがあります」ポップアップ中心の設計をやめるべき理由です。プロのチームには、控えめなプロンプト、サイレント適用の経路、ロールバックルール、Channelターゲティング、後からサポートが確認できるログが必要です。
信頼の観点も重要です。ユーザーはアップデート自体よりも、予期せぬ中断をはるかに気にします。アプリがスムーズに更新され、大きな変更が明確に説明され、本当の不具合やセキュリティリスクのときだけ利用をブロックするなら、ユーザーはそれを有能さの表れと受け取ります。
Capgo によるアップデート検知の実装
最初のステップはシンプルです。ユーザーがどのバージョンを使用しているか、どのチャンネルに属しているかを確認し、取得すべきデータがあるかを判断することです。自作のアップデートシステムが複雑になりがちなのは、これらの判断を混同してしまうからです。これらは明確に分けて管理しましょう。

まずはバージョン管理から始める
信頼性の高いアップデーターには、実行時に以下の3つの値が必要です:
- インストール済みのアプリバージョン
- 割り当てられたリリースチャンネル
- 現在のアップデート状態(idle、checking、available、downloading、ready、failed など)
この状態モデルを省略すると、すぐに通知のバグが発生します。チェックが頻繁に走りすぎたり、起動するたびに同じプロンプトが表示されたり、バックグラウンドでのダウンロードが完了しているのに UI が「checking」のままだったりといった問題です。
ここでマネージドサービスを選択するのが賢明な理由は、運用負荷が code のスニペットで見る以上に重いためです。署名済みbundle、チャンネルルール、ロールバック対応、バージョン履歴、デバイスレベルのlogs、そして配信インフラが必要になります。 Capgo updater pluginとホスト型の配信ワークフローを通じて、CapacitorやElectronアプリにその機能を提供します。そのため、多くのクライアントチームにとって、スタックを自前で再構築するよりもこれを利用する方が効率的です。
アプリの起動時にupdaterを組み込む
アプリ起動時、シェルが準備できた後に軽量なチェックを実行します。アップデートがないとアプリが続行できない場合を除き、ファーストペイントをブロックしないでください。
Capacitorアプリにおける一般的なパターンは以下の通りです:
import { App } from '@capacitor/app'
// import your updater SDK here
type UpdateDecision =
| { kind: 'none' }
| { kind: 'soft'; version: string }
| { kind: 'hard'; version: string }
| { kind: 'silent'; version: string }
async function checkForUpdate(): Promise<UpdateDecision> {
try {
// Replace with your updater SDK call
const result = await updater.check()
if (!result || !result.available) {
return { kind: 'none' }
}
if (result.metadata?.mandatory === true) {
return { kind: 'hard', version: result.version }
}
if (result.metadata?.silent === true) {
return { kind: 'silent', version: result.version }
}
return { kind: 'soft', version: result.version }
} catch {
return { kind: 'none' }
}
}
App.addListener('appStateChange', async ({ isActive }) => {
if (!isActive) return
const decision = await checkForUpdate()
handleUpdateDecision(decision)
})
の目的は check() isn’t just “is there a newer thing”. It’s “is there a newer thing for この ユーザーに対して この channel用の新しいものがあるか、そしてアプリはどう反応すべきか」を確認することです。
健全な実装では、前回のチェック成功時刻と最後にプロンプトを表示したバージョンも保存します。これにより、アプリのアップデート通知ロジックが、しつこいものではなく、べき等性を保ったものになります。
結果を読み取り、早めに分岐させる
分岐処理は、チェック結果の直後に行うべきです。更新ルールを各画面に分散させないようにしましょう。
私が実際に採用している、実用的な切り分け方は以下の通りです:
- アップデートなし は何もしない状態で、通常のチェック結果をログに記録します。
- ソフトアップデート は、バナーや設定画面のバッジ、軽量なインアプリプロンプトを表示するキューに追加します。
- サイレントアップデート は、バックグラウンドでダウンロードを行い、次回の起動時に適用します。
- 強制アップデート は、アプリを強制的なブロックフローへと切り替えます。
実装の後半では、この決定を一つのセントラルストアに公開し、React、Vue、または Ionic UI から一貫して利用できるようにするのが理想的です。
このチュートリアルは、Capacitor アプリ全体の構成を確認したい場合に役立ちます:
検知レイヤーは地味に保ちましょう。賢さはロールアウトポリシーに置くべきで、起動時の code ではありません。
効果的な通知パターンの設計
ほとんどのアップデートプロンプトが失敗するのは、チームが1つのパターンを選んで何にでも使ってしまうからです。だから、文言の微修正にブロッキングモーダルを出したり、重要なマイグレーションを誰も気づかないトーストの裏に隠したりすることになるのです。
通知環境はすでに飽和状態です。 Business of AppsのAirshipベンチマーク概要によると、 米国のスマートフォンユーザーは平均して 1日46件のプッシュ通知を受け取っており、一方、プッシュ通知の平均反応率とクリック率は、 iOSで3.4%、 と Androidで4.6%と、依然として低い水準にとどまっています。アプリのアップデート通知は、ユーザーを疲れさせずに注目を集める必要があります。

効果を維持しつつ、ユーザーへの影響が最も少ないパターンを選びましょう。
優れたアップデートUIは、割り込みのコストを意識します。ユーザーが決済情報を入力中、患者のメモを記録中、在庫をスキャン中の場合、モーダルは修正しようとしているバグよりも悪影響になり得ます。
私は普段、以下のように使い分けています:
- 画面上部または下部のバナー 軽微な修正、緊急度の低い改善、およびサイレントアップデートの通知用。
- トースト通知 「次回起動時にアップデート可能」といったバックグラウンドの状態表示用。重要な意思決定には使いません。
- 設定やプロフィール画面への導線 自分でコントロールしたい、または変更履歴を確認したいユーザー用。
- モーダル(強制) 旧バージョンではアプリを安全に継続利用できない場合にのみ使用します。
派手なモーダルよりも、控えめなバナーの方がユーザーにUI操作を強いることがないため、効果的な場合が多いです。
主要パターンの簡単な比較
| パターン | 適した用途 | 主なリスク | 実装上の注意 |
|---|---|---|---|
| バナー | 任意アップデート、緊急度の低い通知 | 無視されやすい | バージョンごとに非表示状態を保持 |
| トースト | バックグラウンドでの状態変化 | 消えるのが早すぎる | 永続的な設定項目と組み合わせる |
| インアプリメッセージ | コンテキストに応じた機能リリース | すぐに気づかれない可能性がある | 関連する画面に紐付ける |
| モーダル | 必須のアクション | ユーザーのフラストレーション | 強制的なゲートにのみ使用する |
最も重要な実装の詳細は 状態の永続化ユーザーが「後で」をタップした場合は、その情報を提供済みのバージョンに関連付けて保存してください。バナーを閉じた場合、ルートが変わるたびに再表示しないようにします。これを怠ると、アップデート機能自体は正常でも、ユーザーにはアプリが壊れているように感じられてしまいます。
すでにライフサイクル管理にプッシュ通知を導入しているチームは、アプリアップデートのUXを既存のメッセージング環境と比較検討する価値があります。Capgoによるガイドはこちら: Firebase を使った Ionic と Capacitor のプッシュ通知 ここで役立つのは、トランスポートの関心事を、ユーザーにアクションを促すアプリ内UIから切り離せるからです。
Push通知だけでは不十分です
よくある間違いは、OSレベルのアップデートバッジやストアの通知だけで十分だと考えてしまうことです。実際には、デバイスの設定、バッジの権限、自動更新の挙動、あるいは省電力モードなどの影響で、ユーザーはそれらの通知を見逃しがちです。だからこそ、ストアのエコシステムが正常に機能していても、アプリ内メッセージングが重要になります。
Electronの場合は、これがより顕著です。デスクトップユーザーは、モーダルによる割り込みではなく、控えめなステータス表示を求める傾向があります。ワークフローの途中でフォーカスを奪うシステムダイアログよりも、シェル内に表示される小さな「Update ready」チップの方が、プロフェッショナルな印象を与えます。
最適なパターンは、アップデートのリスクとユーザーの現在のタスクに合うものです。それ以外は単なる演出です。
アップデートフローの自動化とユーザーの選択肢
検知とUXパターンが整ったら、核となるのはワークフローです。開発チームは、自動化しすぎて制御不能になるか、自動化が足りずにサポートコストを増大させるかのどちらかに陥りがちです。

Coderioのアプリメンテナンスガイドラインでは、 実用的なリリースサイクルとして、 2〜4週間ごとのマイナーアップデートを推奨しています。 と 3〜6ヶ月ごとのメジャーリリース、ハードアップデートは 重大なセキュリティや安定性の問題に限定します。これが正しい考え方です。判断基準は開発者の不安ではなく、リリースの種類であるべきです。
低リスクな変更向けのサイレントアップデート
Capacitor アプリで、サイレントアップデートは最も活用されていない手法です。スタイル、文言、フィーチャーフラグの配線、非破壊的なJavaScriptバグの修正なら、ユーザーを中断させる理由は通常ありません。
フローは非常にシンプルです:
- アプリが新しいbundleを確認します。
- アップデートがバックグラウンド適用可能とマークされていれば、バックグラウンドでダウンロードされます。
- アプリは次回の起動時に新しいbundleを有効化します。
- 再起動後、ユーザーには「アップデートが完了しました」という短い通知が表示されるか、何も表示されないこともあります。
その判断は変更内容によります。アップデートでユーザーに見えるワークフローが変わる場合は、次回起動時に小さな「新機能」カードを表示すると状況を把握しやすくなります。変わらない場合は、何も表示しないで問題ありません。
シンプルな状態管理の実装例は以下の通りです:
async function handleUpdateDecision(decision: UpdateDecision) {
if (decision.kind === 'silent') {
await updater.download()
await updater.setNextBundle()
localStorage.setItem('pendingUpdateVersion', decision.version)
return
}
if (decision.kind === 'soft') {
showBanner(decision.version)
return
}
if (decision.kind === 'hard') {
showForcedUpdateScreen(decision.version)
}
}
目に見えるプロダクト変更向けのユーザー選択フロー
アップデートによって挙動が大きく変わる場合は、ユーザーに選択を促すフローが適しています。新しいナビゲーション、オンボーディングの刷新、承認フローの変更、あるいはダッシュボードの大幅なリデザインなどがこれに該当します。
プロンプトは簡潔に保つ必要があります:
- 変更点
- なぜ重要か
- 今すぐアップデートするとどうなるか
- ユーザーが更新を後回しにしたらどうなるか
ダイアログにリリースノートを詩のように書き連ねないでください。明確な1文と2つのボタンの方が、長文のコピーよりも優れた結果をもたらすのが一般的です。
私はこのパターンを推奨しています:
新しいバージョンが利用可能です。レポートワークフローの更新とエクスポートの修正が含まれています。今すぐアップデートするか、後でインストールするために続行します。
「後で」の扱いは慎重に。旧クライアントが引き続き有効なら、そのまま続行させてください。もし API の移行によって旧クライアントが動作しなくなるなら、選択肢であるかのように装ってはいけません。
アプリの配信だけでなくガバナンスを検討しているチームにとって、同じロジックはセキュリティ運用にも当てはまります。優れた自動化は、日常的な変更を静かに処理し、リスクが正当化される場合にのみエスカレーションを行います。それが、こちらの SOCチーム向けセキュリティ自動化の概要 が役立つ理由の一つです。ここでは、イベントを分類し、安全なパスを自動化し、人間による介入を意図的なものにするという、より広範な設計原則が示されています。
また、ターゲット層のロジックによってこれをさらに強化することもできます。Capgo による アプリアップデートの利用頻度セグメンテーションに関する記事 は、実用的なリファレンスになります。なぜなら、頻繁に利用するユーザーとたまに利用するユーザーに対して、常に同じタイミングやプロンプト形式を用いるべきではないからです。
限定的な重大ケース向けの強制アップデート
強制アップデートは正当な手段ですが、悪用されやすい側面もあります。
以下に該当する場合は、ハードゲート(強制更新)を適用してください:
| 条件 | 強制アップデート |
|---|---|
| 脆弱性が判明しているセキュリティパッチ | はい |
| 深刻な不具合を引き起こす安定性の問題 | はい |
| バックエンド契約の破壊的変更 | はい |
| 軽微なUIの調整 | いいえ |
| オプション機能のロールアウト | いいえ |
実装は明示的に行うべきです。起動時にインストール済みバージョンを確認し、サポートする最小バージョンと比較してください。ユーザーをブロック状態に移行させるのは、そのしきい値を下回っている場合のみです。「新しいバージョンが存在する」という理由で「必須」と判断しないでください。
強制アップデート画面には3つの性質が必要です:
- 行き止まりを作らないこと. ユーザーに明確なリトライ手段を提供してください。
- 分かりやすい説明. なぜアップデートが必要なのかを伝えてください。
- オフライン時の対応. ネットワークが利用できない場合も、その旨を説明してください。
うまくいかないのは、不安定なモバイル通信で何の表示もなく失敗する「Update」ボタンが1つだけのモーダルです。アプリがブロックされた場合、復旧導線は通常時よりも洗練されている必要があります。
ChannelsとTelemetryを活用した高度なロールアウト
アップデートに関するトラブルの多くは、検知の失敗ではなく、実際の挙動を確認する前に広範囲へリリースしてしまうことが原因で起こります。
Channelsで影響範囲を抑える
クライアントアプリでLive Updateを配信する際、最も安全な方法はチャンネルベースのロールアウトです。全員に一斉に1つのbundleを公開するのではなく、内部向け、QA、beta、staging、production、あるいは特定の顧客向けといった対象ごとに配信します。
これにより、単なる「公開か否か」という二択ではなく、運用コントロールに近いリリース形態が可能になります。1つのbuildを順次異なる対象へ展開し、各フェーズで動作を確認しながら、次のグループへ進むための確信を得ることができます。
以下に、アップデートのワークフローを含む、このロールアウトモデルの商用プラン構成のスクリーンショットを掲載します。

これは通知戦略においても重要です。 Adaptyのプッシュ通知ベストプラクティス 報告では、 送信時間を最適化することで反応率が40%向上し、 と 高度なターゲティングにより反応率が3倍になる可能性があります。. アップデートシステムにおいては、これは全インストールベースへの一律なプロンプトではなく、チャンネルを意識したロールアウトやバージョンごとのメッセージングを意味します。
Telemetryでユーザーが実際に移行したかがわかる
プロフェッショナルなアップデートシステムは、エンジニアがアドホックなログを掘り返さなくても、以下の疑問に答えられるべきです:
- 各デバイスはどのbundleバージョンを使用しているか?
- アップデートのダウンロードは完了したか?
- 次回の起動時に正常に適用されましたか?
- ロールアウト後に起動失敗が増えていませんか?
- どのユーザーが非推奨バージョンで止まっていますか?
テレメトリがあれば、アップデートは単なる「リリース作業」から「運用プロセス」へと変わります。これがないと、何を配信したかしか分かりません。これがあれば、ユーザーが実際に何を導入したかが分かります。
サポートがアップデートの状態を把握できないと、本来はロールアウトの問題である事象を製品の問題としてエスカレーションしてしまいます。
私は、集計のみのダッシュボードよりも、デバイスごとのタイムラインを強く重視します。全体の導入曲線も有用ですが、「なぜ特定のエンタープライズ顧客が、1週間経っても古いbundleでアプリを開いているのか」は説明できません。デバイスレベルのログなら、それが分かります。
特定のコホートを分離できるようになれば、バージョン指定の配信もより実用的になります。こちらのガイドでは 特定のバージョンをユーザーに配信する ことは、複数の顧客環境をサポートするエンタープライズチームが、最終的に必要とする制御の好例です。
CI/CDはビルドだけでなく、公開と観測も行うべき
モダンなパイプラインは「ビルド成功」で終わるべきではありません。以下のステップが必要です:
- bundleをビルドする
- 署名して適切なチャンネルへ公開する
- リリースメタデータを付与する
- 適用状況と失敗をモニタリングする
- ヘルスが悪化したらロールバックする
ロールバックがあるかどうかが、デモ用アップデータと本番用アップデータの分かれ目です。bundleが原因で起動クラッシュや起動時のデッドロックが起きたとき、チームには影響範囲を素早く食い止める手段が必要です。多くのエージェンシーにとって、マネージドツールが自作より優れている最大の理由のひとつがこれです。デリバリー、ガードレール、オブザーバビリティ、ロールバックは付加機能ではありません。それらこそがシステムです。
CI/CDの統合自体は複雑である必要はありません。重要なのは、公開が決定的かつ追跡可能であることです。リリースはコミット、環境、実行者、チャンネルに紐付けられるべきです。この4つにすぐ答えられないと、インシデント対応は悲惨なことになります。
よくある通知問題のトラブルシューティング
以下の問題は、Capacitor や Electron のアップデート作業で繰り返し発生します。そのほとんどはネットワークではなく、state drift(状態のずれ)に起因します。
起動するたびにプロンプトが表示される
症状: ユーザーがアプリのアップデート通知を閉じたのに、アプリを起動するたびにまた表示されてしまう。
考えられる原因: チェック自体は成功していますが、提示したバージョンごとにプロンプト状態を保持していません。
解決策: ユーザーが拒否または延期したバージョンを保存し、UIを再表示する前にそれと比較してください。
function shouldPrompt(version: string): boolean {
const dismissed = localStorage.getItem('dismissedUpdateVersion')
return dismissed !== version
}
function dismissPrompt(version: string) {
localStorage.setItem('dismissedUpdateVersion', version)
}
ここでチームは「利用可能」と「割り込むべき」を混同しがちです。これは別々の判断です。
サイレントアップデートはダウンロードされるが適用されない
症状: ログにはbundleが取得されたと記録されていますが、古いUIが読み込まれ続けます。
考えられる原因: アプリがアップデートをダウンロードしたものの、次回起動用にマークしておらず、起動パスが最後に有効だったbundleを指したままになっています。
解決策: 適用を明示的に行い、起動時に検証してください。codeやアナリティクスでは、「ダウンロード済み」と「有効」を別の状態として扱ってください。
ライフサイクルを以下のようにモデル化すると、多くのバグが解消されます。 available -> downloading -> ready -> active 単一のboolean値ではなく。
開発環境と本番環境でチェックの挙動が異なる
症状: リリースビルドではアップデート検知ができるのに、ローカル開発ではできない(またはその逆)といった状況。
考えられる原因: 環境ごとの設定の違い。チャンネル名の相違、デバッグ時のプラグイン無効化、あるいは起動時の code が誤ったガードでラップされている場合など。
解決策: 環境ごとの挙動を可視化すること。起動時にチャンネル、アプリバージョン、ビルドモードをログに出力しましょう。記憶に頼ってはいけません。
- 開発用ビルド 通常は live update のチェックをバイパスするか、専用のテストチャンネルを参照すべきです。
- ステージングビルド 本番と同じように動作させつつ、ロールアウトストリームは分離すべきです。
- プロダクションビルドは 社内QA用のトラフィックとチャンネルを共有すべきではありません。
チェック中にユーザーがオフラインになる
症状: 接続がない状態でアプリを開くと、アップデートに失敗したような表示になってしまいます。
考えられる原因: チェックのパスがネットワークの成功を前提としており、失敗時に中立的な状態ではなくエラーUIにマッピングされているためです。
解決策: グレースフルに縮退させましょう。現在のバージョンは動かしたまま、失敗したチェックを記録し、アプリが再びアクティブになったタイミングでリトライします。
オフラインは例外的な事態ではなく、実行時の正常な状態の一つです。
強制アップデートの場合、オフライン時の挙動には細心の注意が必要です。最小サポートバージョンが既に無効な場合は、アプリをブロックしたままにする必要があるかもしれません。その場合は理由を明確に説明し、接続が復旧したらリトライのアクションを提示してください。アップデートが任意の場合は、一時的なネットワーク断でユーザーに不利益を与えないようにしましょう。
これらのケースすべてに共通する原則はシンプルです。分離することです。 検知, ポリシー, UIや アクティベーション。これらの懸念事項が1つのフックや1つのスクリーンコンポーネントに集約されてしまうと、デバッグは推測の域を出なくなります。
もしあなたのチームが Capacitor や Electron アプリをリリースしており、チャンネル管理、署名済み bundle の配信、ロールバック保護、そしてデバイスレベルのオブザーバビリティを備えた、制御可能なアップデートシステムを必要としているなら、 Capgo 検討する価値は十分にあります。Live Updateを、手作り感のあるサイドプロジェクトではなく、リリース用インフラとして運用したいチームに最適です。
「効果的なアプリ更新通知戦略」の続きはこちら
使用している場合 効果的なアプリ更新通知の戦略 CI/CD自動化を計画するには、次と連携してください Capgo での CI/CD 設定 Capgo CI/CDでのプロダクトワークフローについては、 Capgo Native Build Capgo Native Buildsでのプロダクトワークフローについては、 Capgo インテグレーション Capgo インテグレーションでのプロダクトワークフロー向けに、 CI/CD 連携 CI/CD Integrationの実装詳細については、 GitHub Actions 連携 GitHub Actions Integrationの実装詳細については。