Github Action|ZReviewTenderで無料即時App評価監視ロボットを簡単3ステップで構築
App開発者向けにGithub ActionとZReviewTenderを活用し、無料で安定・安全な評価監視ロボットを3ステップで導入。ユーザーの最新レビューを即座に把握し、品質向上を実現します。
本記事は AI による翻訳をもとに作成されています。表現が不自然な箇所がありましたら、ぜひコメントでお知らせください。
記事一覧
[クイックスタート!] Github Action x ZReviewTender 無料で素早くあなたのAppストア評価監視ロボットをデプロイする方法
簡単な3ステップで無料かつ安定・安全なAppレビュー監視ロボットを構築し、ユーザーの最新レビューをリアルタイムで把握。
ZReviewTender
ZReviewTender — これは私が2022年8月に作成したオープンソースのアプリストア評価ロボットで、iOS App StoreやAndroid Google Playのアプリユーザー評価を自動で取得し、指定したSlackチャンネルに転送する機能があります。
また、評価の取得ルールを指定したり、Google翻訳、Asana、Google Sheetsとの連携も可能で、カスタム操作にも対応しています。
Github Action
Github Action は Github が提供する CI/CD 自動化統合ツールであり、自分のマシンをサーバー(Github Runner)として使うことも、Github が提供するマシンを直接使って CI/CD や自動化スクリプトを実行することもできます。
費用と制限
GitHub Free は基本的に500MBのストレージ(CI/CDアーティファクト用)と、月間2,000分の実行時間を提供します。
GithubのWindowsマシンを使用する場合、消費される分数は実際の分数の2倍になります。
GithubのmacOSマシンを使用する場合、消費される分数は実際の分数×10となります。
詳細な料金計算については、公式価格計算ツール をご参照ください。
ZReviewTender 月間消費時間:約120分
基本料金のLinux上で実行するだけで、1回の実行は約1分以内に収まり、デフォルトで6時間ごとに実行されます。1日あたり4分、1ヶ月で約120分の消費となり、無料枠で十分対応可能です。
ZReviewTender ストレージ消費:0
Artifactを使用してデータを保存しないため、ストレージコストはかかりません。
Slack
会社で使用している社内コミュニケーションツールとして、Slack Appを作成し、このSlack Appの権限でAppストアの評価通知を指定したチャンネルに転送します。
ZReviewTender x Github Action x Slack
私たちは Github Action を使って ZReviewTender スクリプトを実行し、その結果を Slack に送信しています。Github リポジトリ(Action)は単なる実行環境として使用しているため、メインプロジェクトが Github でホスティングされていなくても、以下の手順に従えば簡単に ZReviewTender を導入できます。🎉🎉🎉
私はすでに5社の異なるアプリに成功裏にデプロイし、少なくとも2年以上安定して無料で運用しています。
利点:
無料 : ZReviewTender は私が開発したオープンソースの無料サービスで、Github Action にデプロイしており、無料枠で十分に運用可能です。
毎月のAppレビューBotのような月額課金の評価監視サービスを購入する必要はありません。安全性 :レビュー取得に使う証明書や鍵はすべてあなたのGithubプライベートリポジトリに安全に保管され、あなた以外はアクセスできません。
重要な証明書や鍵を第三者サービスにアップロードして漏洩リスクを負う必要はありません。ZReviewTender はオープンソースプロジェクトであり、すべての操作は公開検証に耐えられます。信頼性 : ZReviewTender は公式の最新APIを使って評価情報を取得するため、従来のRSSを利用したサービスより正確で安定し、信頼できます。
コーヒーを買ってください ❤️❤️❤️
</contact>{:target=”_blank”}
クイックスタート!🚀
すべての設定手順は約30分かかりますが、一度設定すれば証明書や鍵を変更しない限り、永久に無料で安定して動作します。 🚀🚀🚀🚀🚀
Step 1. Slackアプリの作成
もし組織内ですでに chat:write のようなメッセージ送信権限を持つSlack Appを作成している場合は、新しく作成せずにそのまま再利用できます。
右上の「Create New App」をクリックしてください。
選択:From scratch
アプリ名を入力:
ZReviewTenderまたはカスタムSlackアプリ名インストール先の Slack ワークスペースを選択してください:選択したワークスペースに Slack アプリを追加する権限があることを確認してください。
アプリを作成する
OAuth & Permissions スコープの追加:
Slackアプリを作成したら、まず「OAuth & Permissions」タブでスコープを設定します。
「OAuth & Permissions」を選択してください。
下にスクロールしてScopesセクションを見つけます。
ZReviewTender Slack App に必要な3つのスコープを順番に入力してください:
chat:write
chat:write.public
links:write
Install App
Install App タブに戻り、Slack App を Workspace にインストールします。
「Install App」を選択してください。
「Install to YOUR_WORKSPACE」をクリックしてください
「Allow」をクリックしてください
インストールが完了したら、Install App ページに戻ると Slack App Bot User OAuth Token が表示されます。「Copy」をクリックしてコピーし、後で設定に使うので必ず控えておいてください。
評価通知を受け取るチャンネルの作成:
サイドバー -> チャンネル -> 作成 -> チャンネルを作成
Name: 希望するチャンネル名を入力してください
可視性:
Public:すべての人に公開され、他の操作は不要です。
Private:プライベートチャンネル, ⭐️⭐️⭐️ 先ほど作成したSlackアプリを追加する必要があります:
Slack App チャンネル参加方法:
上部の #チャンネル名 をクリックしてください
「設定」をクリックしてください
「Add an App」をクリックしてください
作成したばかりの Slack アプリ名を検索する
「Add」をクリックしてください
参加に成功するとメッセージが表示されます。 ZReviewTender joined.
⭐️⭐️⭐️ここでSlackのバグを発見しました。Slack Appを作成した直後は検索できないことがあります。しばらく待つと表示されます。先にPublic Channelを使うこともできます。Public ChannelはSlack Appを追加しなくても使えます。
Channel IDの取得:
最後のステップで最も重要なのは、後で設定に使うためにChannel IDを取得することです。
上部の #チャンネル名 をクリックしてください
About の最下部に Channel ID 情報があります
Channel IDをメモして、後で設定に使用します
Slackのステップが完了しました。
— — —
その他の補足:
「Basic Information」->「Display Information」でSlackアプリの名前やアイコンを編集できます:
編集が完了したら、右下の「Save Changes」をクリックして保存してください。
OAuth & Permissions のスコープを追加した場合は、「reinstall your app」をクリックして再インストールする必要があります:
Step 2. Apple App Store Connect API と Google Play Android Developer API の認証情報を生成する
Apple App Store Connect API 身分証明書
iOSは比較的簡単で、App Store Connectから以下の4つの情報を取得するだけです:
Issuer ID:
App Store Connect -> Keys -> App Store Connect API
Issuer IDをメモしておき、後で設定に使用します
プライベートキーID & プライベートキー:
「+」ボタンをクリック:
名前:
ZReviewTenderアクセス:
App Manager
Key IDは後で設定に使用します「Download API Key」をクリックしてダウンロードした「
AuthKey_XXXXXXXXXX.p8」ファイルを保存し、後で設定に使用します。
App ID : (評価を取得する対象のApp ID)
App ID は App Store Connect -> App Store -> General -> App Information -> App ID で確認できます。
App IDをメモしておき、後で設定に使用します
Google Play Android Developer API 認証情報
Androidはやや複雑で、まずAppプロジェクトに紐づくGoogle Cloud ProjectでAPIを有効化し、サービスアカウントを作成し、そのサービスアカウントをGoogle Play Consoleに追加してAppの権限を付与する必要があります。
Appプロジェクトに所属するGoogle Cloudプロジェクトを選択するか、新しいプロジェクトを作成します。
「Android Developer API」を有効にする:
「Android Developer API」を検索してクリックしてください
「有効にする」を選択してください
[このステップは任意です] 同時に「Cloud Translation API」を有効にすることもできます:
有効化すると、同じサービスアカウントの認証情報を使って、レビューの自動翻訳機能と連携できます。
ご注意:Cloud Translation APIは無料ではありません。言語検出や翻訳には費用が発生します!
ご注意:Cloud Translation APIは無料ではなく、言語検出や翻訳には料金が発生します!
注意:Cloud Translation APIは無料ではなく、言語検出や翻訳には料金が発生します!
Service Account(サービスアカウント)の作成:
「IAM」を検索します。
「IAM & Admin」を選択してください。
「サービスアカウント (Service Account)」を選択してください
「サービスアカウントの作成」を選択してください
サービスアカウント名:任意に入力可能で、「
ZReviewTender」または「Google Play Review Bot」と入力しても構いませんサービスアカウントID:自動で入力されます。特別な要件がなければ変更不要です。これがあなたのサービスアカウントのメールアドレスにもなります。
「完了」をクリックしてください
このサービスアカウントのメールアドレスを控えてください:
リストページにも Service Account Email アドレスが表示されます
Service Account Emailをメモして、後で設定に使用します
サービスアカウントのキー証明書を作成:
リストページをリフレッシュし、先ほど作成したサービスアカウント Service Account をクリックしてください。
「新しいキーを追加」をクリックしてください
「新しいキーを作成」をクリックしてください
キータイプを「JSON」に選択してください
「作成」をクリックしてください
ダウンロードした「
XXXX-XXXX.json」ファイルを保存し、後で設定に使用します
Google Play Consoleにサービスアカウントを追加し、レビューを取得する対象アプリの権限を付与する:
Google Play Consoleの管理画面にログイン:
「Users and permissions」をクリックしてください
右側の「Invite new users」をクリックしてください
Emailアドレスに先ほど控えた
Service Account Emailを入力してくださいアプリの権限 -> アプリを追加
取得する評価の対象となるAppを追加する
「Invite user」をクリックするだけで招待が完了し、認証は不要です。
Google Play ConsoleのDeveloper ID、App ID、パッケージ名の取得方法:
クリックして評価を取得したい対象のAppのダッシュボードに入る
Package Nameをメモしてください。後で設定に使用します。
DashboardのURLをコピーし、URLから以下を見つけてください:
その中の /developers/
XXXがあなたのDeveloper IDです。この数字のDeveloper IDを控えて、後で設定に使用しますその中の /app/
XXXはあなたのApp IDです。この数字のApp IDを控えて、後で設定に使用します
身分証明書の設定が完了しました。
Step 3. Github Action のデプロイと設定ファイルの記入
嬉しいことに、面倒なGithubリポジトリやGithub Actionの設定手順をリポジトリテンプレートとMarketplaceのGithub Actionとしてまとめました。以下の数ステップで作業を完了できます。
移動先: ZReviewTender-deploy-with-github-action :
https://github.com/ZhgChgLi/ZReviewTender-deploy-with-github-action
Repository name:作成したいリポジトリ名を入力してください
Private :リポジトリにアクセスキーが保存されるため、必ずPrivateリポジトリに設定してください ⭐️⭐️⭐️
Private :リポジトリにアクセスキーを保存するため、必ずPrivateリポジトリに設定してください ⭐️⭐️⭐️
Private :リポジトリにアクセスキーを保存するため、必ずPrivateリポジトリに設定してください ⭐️⭐️⭐️
「Create repository」をクリックしてください
ZReviewTender の作者および貢献者である ZhgChgLi は、ZReviewTender の使用に起因するいかなる損害についても責任を負いません。
リポジトリの作成を待つ:
再度確認したのは Private リポジトリであること:
Private :リポジトリにアクセスキーを保存するため、必ずプライベートリポジトリに設定してください ⭐️⭐️⭐️
Private :リポジトリにアクセスキーを保存するため、必ずプライベートリポジトリに設定してください ⭐️⭐️⭐️
Private :リポジトリにアクセストークンを保存するため、必ずプライベートリポジトリに設定してください ⭐️⭐️⭐️
Github Actionsの権限を有効化する:
リポジトリを作成した後、Githubのセキュリティ設定により、まずリポジトリの設定でGithub Actionsの実行を許可する必要があります。
リポジトリ -> 設定
「Actions」 -> 「General」を選択してください。
Actions permissions で「Allow all actions and reusable workflows」を選択してください。
「保存」をクリックしてください。
Workflow permissions で「Read repository contents and packages permissions」を選択してください。
初回実行時、ZReviewTenderの初期化:
リポジトリ -> Actions
「Init ZReviewTender」を選択してください。
「Run workflow」を選択してください。
「Run workflow」をクリックしてください。
ページをリロードする
待機中 init ZReviewTender アクションの完了を待ちます:
もし❌ エラーが発生した場合:前述のGithub Actionsの権限設定が正しいか再度確認してください。
初期化に成功すると、リポジトリのトップページに2つの新しいディレクトリが表示されます:
アップロードが必要な証明書ファイル:
/configディレクトリに移動する右上の「Add file」-> 「Upload files」
Step 2. 保存したGCPサービスアカウントの
XXXX-XXXX.json(Android用)とApp Store Connectで保存したAuthKey_XXXXXXXXXX.p8(iOS用)を一緒にアップロードしてください。アップロードの完了を待ちます
「Commit directly to the main branch」を選択してください。
「Commit changes」をクリックしてください
Apple (iOS) の設定:
config/ディレクトリに入り、apple.ymlファイルをクリックしてください
- 右上の「🖊️編集」をクリックしてください
apple.yml を編集し、以下の内容を貼り付けて、前のステップで控えた情報を入力してください:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
platform: 'apple'
appStoreConnectP8PrivateKeyFilePath: './config/AuthKey_XXXXXXXXXX.p8' # APPLE STORE CONNECT API のプライベート .p8 キーファイルのパス
appStoreConnectP8PrivateKeyID: 'Private Key ID' # APPLE STORE CONNECT API のプライベートキーID
appStoreConnectIssueID: 'Issuer ID' # APPLE STORE CONNECT 発行者ID
appID: 'App ID' # アプリID
processors:
- SlackProcessor: # Slackプロセッサー、AppレビューをSlackに再送信します。
class: "SlackProcessor"
enable: true # 有効化
slackTimeZoneOffset: "+08:00" # レビュー作成日時のタイムゾーン
slackAttachmentGroupByNumber: "1" # 1〜100、1つのSlackメッセージに含めるレビュー数
slackBotToken: "Slack App Bot User OAuth Token" # Slack Botトークン、Slack Botを通じてメッセージを送信
slackBotTargetChannel: "Target Channel ID" # Slack Botトークン、Slack Botを通じてメッセージを送信する対象チャンネルID(推奨、優先度高)
slackInCommingWebHookURL: "" # SlackのIncoming WebHook URL、Incoming WebHook経由でメッセージ送信(非推奨、廃止予定)
appStoreConnectP8PrivateKeyFilePath:
./config/AuthKey_XXXXXXXXXX.p8を入力してください(ステップ2でApp Store Connectから保存したAuthKey_XXXXXXXXXX.p8ファイル名)appStoreConnectP8PrivateKeyID: ステップ2でApp Store Connectから記録したPrivate Key IDappStoreConnectIssueID: ステップ2でApp Store Connectから記録したIssuer IDappID: ステップ2でApp Store Connectからメモした対象のAppのApp IDslackBotToken: ステップ1で控えたSlack App Bot User OAuth Tokenを入力してくださいslackBotTargetChannel: ステップ1で控えた送信先のChannel IDを入力してください
編集が完了したら、右上の「Commit changes…」をクリックしてください。
「Commit directly to the main branch」を選択してください
「Commit changes」をクリックしてください
Androidの設定:
config/ディレクトリに入り、android.ymlファイルをクリックします
- 右上の「🖊️編集」をクリックしてください
android.yml を編集し、以下の内容を貼り付けて、前のステップでメモした情報を入力してください:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
platform: 'android'
packageName: 'Package Name' # Androidアプリのパッケージ名
keyFilePath: './config/XXXX-XXXX.json' # Google Android Publisher API サービスアカウント認証情報の.jsonファイルパス
playConsoleDeveloperAccountID: 'Developer ID' # Google Console開発者アカウントID
playConsoleAppID: 'App ID' # Google ConsoleアプリID
processors:
- SlackProcessor: # Slackプロセッサー、アプリレビューをSlackに再送信します。
class: "SlackProcessor"
enable: true # 有効化
slackTimeZoneOffset: "+08:00" # レビュー作成日時のタイムゾーン
slackAttachmentGroupByNumber: "1" # 1〜100、1つのSlackメッセージに含めるレビュー数
slackBotToken: "Slack App Bot User OAuth Token" # Slack Botトークン、Slack Bot経由でメッセージを送信
slackBotTargetChannel: "Target Channel ID" # Slack Botトークンを使ってメッセージを送信するSlackのチャンネルID(推奨、最優先)
slackInCommingWebHookURL: "" # Slack Incoming WebHook URL、Incoming WebHook経由でメッセージを送信(非推奨、廃止予定)
packageName: ステップ2でGoogle Play Consoleの管理画面から控えたPackage NamekeyFilePath:
./config/XXXX-XXXX.jsonを入力してください(ステップ2でGCP IAMから保存したXXXX-XXXX.jsonサービスアカウントキーのファイル名)playConsoleDeveloperAccountID: ステップ2でGoogle Play Consoleの管理画面からメモしたDeveloper IDplayConsoleAppID: ステップ2でGoogle Play Consoleの管理画面から控えたApp IDslackBotToken: ステップ1で控えたSlack App Bot User OAuth Tokenを入力してくださいslackBotTargetChannel: ステップ1でメモした送信先のChannel IDを入力してください
編集が完了したら、右上の「Commit changes…」をクリックしてください。
「Commit directly to the main branch」を選択してください。
「Commit changes」をクリックしてください
設定完了! 🚀🚀🚀🚀
設定が成功したか確認する:
手動で一度実行して、設定に誤りがないか確認できます。
リポジトリ -> Actions
「ZReviewTender」を選択します
「Run workflow」を選択してください。
「Run workflow」をクリックしてください
ページをリロードします
ReviewTender アクションの完了を待つ:
認証成功🎉🎉🎉🎉
❌ エラーが発生した場合やSlackチャンネルに起動メッセージが届かない場合は、以前の設定ファイルの内容が正しいか再度確認してください。
完了 🎉🎉🎉
今すぐこの無料で信頼できるApp評価ロボットを使って、ユーザーの最新レビューを常にチェックできます!
コーヒーを買ってください ❤️❤️❤️
</contact>{:target=”_blank”}
その他の設定
フィルター機能の追加
条件を満たすレビューのみを転送します。
1
2
3
4
5
6
- FilterProcessor:
class: "FilterProcessor"
enable: true # 有効にする
keywordsInclude: [] # フィルタリングしたいキーワード
ratingsInclude: [] # フィルタリングしたい評価
territoriesInclude: [] # フィルタリングしたい地域(Appleの場合の地域コード例:TWN)
/config/apple.ymlまたは/config/android.ymlのprocessorsセクションにFilterProcessorの設定を追加するだけです。
自動翻訳機能の追加
非ご使用の言語のレビューを自動的にGoogle Cloud Translation APIで翻訳します(費用がかかります)。
まず、Step 2. で作成した Service Account が所属する GCP プロジェクトで「Cloud Translation API」が有効になっていることを確認してください
apple.ymlとandroid.ymlの設定にはいくつか違いがあります
apple.yml:
1
2
3
4
5
6
- GoogleTranslateProcessor: # Google翻訳プロセッサー、レビュー本文をあなたの言語に翻訳します。不要な場合はこのブロック全体を削除してください。
class: "GoogleTranslateProcessor"
enable: true # 有効化
googleTranslateAPIKeyFilePath: './config/XXXX-XXXX.json' # Google翻訳APIサービスアカウント認証.jsonファイルのパス
googleTranslateTargetLang: 'zh-TW' # 翻訳先の言語
googleTranslateTerritoriesExclude: ["TWN","CHN"] # 翻訳したくないレビューの発信地域(Appleの場合の地域コード例:TWN)
./config/XXXX-XXXX.json(ステップ2. GCP IAMで保存したXXXX-XXXX.jsonサービスアカウントキーのファイル名)
android.yml:
1
2
3
4
5
6
- GoogleTranslateProcessor: # Google翻訳プロセッサー、レビューのテキストを指定言語に翻訳します。不必要な場合はこのブロック全体を削除してください。
class: "GoogleTranslateProcessor"
enable: true # 有効化
googleTranslateAPIKeyFilePath: './config/XXXX-XXXX.json' # Google翻訳APIサービスアカウント認証.jsonファイルのパス
googleTranslateTargetLang: 'zh-TW' # 翻訳先の言語
googleTranslateTerritoriesExclude: ["zh-Hant","zh-Hans"] # 翻訳しないレビューの元の言語(Androidの言語例:zh-Hant, en)
./config/XXXX-XXXX.json(ステップ2. GCP IAMで保存したXXXX-XXXX.jsonサービスアカウントキーのファイル名)
完全な組み合わせ例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
platform: 'android'
packageName: '' # Androidアプリのパッケージ名
keyFilePath: '' # Google Android Publisher API サービスアカウント認証情報の.jsonファイルパス
playConsoleDeveloperAccountID: '' # Googleコンソールの開発者アカウントID
playConsoleAppID: '' # GoogleコンソールのアプリID
processors:
- FilterProcessor:
class: "FilterProcessor"
enable: true # 有効化
keywordsInclude: [] # フィルタリングしたいキーワード
ratingsInclude: [] # フィルタリングしたい評価
territoriesInclude: [] # フィルタリングしたい地域(Appleの場合の地域例:TWN)
- GoogleTranslateProcessor: # Google翻訳プロセッサ。レビュー本文を指定言語に翻訳します。不要な場合はこのブロックを削除してください。
class: "GoogleTranslateProcessor"
enable: true # 有効化
googleTranslateAPIKeyFilePath: '' # Google翻訳APIサービスアカウント認証情報の.jsonファイルパス
googleTranslateTargetLang: 'zh-TW' # 翻訳先の言語
googleTranslateTerritoriesExclude: ["zh-Hant","zh-Hans"] # 翻訳したくないレビューの発信地域(言語)(Android例:zh-Hant, en)
- SlackProcessor: # Slackプロセッサ。AppレビューをSlackに送信します。
class: "SlackProcessor"
enable: true # 有効化
slackTimeZoneOffset: "+08:00" # レビュー作成日時のタイムゾーン
slackAttachmentGroupByNumber: "1" # 1~100、1つのSlackメッセージに含めるレビュー数
slackBotToken: "" # Slack Botトークン。Slack Bot経由でメッセージを送信します。
slackBotTargetChannel: "" # Slack Botトークン。Slack Bot経由でメッセージを送信するチャンネル(推奨、優先度高)
slackInCommingWebHookURL: "" # Slack Incoming WebHook URL。Incoming WebHook経由でメッセージを送信しますが非推奨です。
調整完了ら、以下の手順で .yml を保存してください:
編集が完了したら、右上の「Commit changes…」をクリックしてください。
「main ブランチに直接コミットする」を選択してください。
「Commit changes」をクリックしてください。
実行パラメータ設定
ZReviewTender.yml ファイルを編集して実行パラメータを設定できます。
リポジトリ -> Actions
「ZReviewTender」をクリックしてください
「
ZReviewTender.yml」をクリックしてください右上の「🖊️編集」をクリックしてください
1
2
3
4
5
6
7
8
9
10
11
12
13
14
name: ZReviewTender
on:
workflow_dispatch:
schedule:
- cron: "15 */6 * * *" # 6時間ごとに新しいレビューを確認します。
jobs:
ZReviewTender:
runs-on: ubuntu-latest
steps:
- name: ZReviewTender 自動ボット
uses: ZhgChgLi/ZReviewTender@main
with:
command: '-r'
チェック頻度の調整(どのくらいの間隔で新しい評価を取得して転送するか?)
cron: "15 */6 * * *" の設定値を調整してください。
パラメータはCrontab形式で指定します。以下のサイトを使って希望の設定パラメータを生成できます:こちら
実行スクリプトの調整
command: "-r" 内の設定値を調整してください。
-r: Android と Apple (iOS) のレビューを同時にチェックする-a: Apple(iOS)のレビュー確認を実行する-g: Androidのレビューのみをチェックする
調整完了:
編集が完了したら、右上の「Commit changes…」をクリックしてください。
「mainブランチに直接コミットする」を選択してください。
「Commit changes」をクリックしてください。
一時的にチェックを停止する
リポジトリ -> Actions
「ZReviewTender」を選択します
右側の「…」をクリックしてください
「Disable workflow」を選択してください。
問題報告と機能提案
もし機能の提案や質問、バグがありましたら、上記のGithubリポジトリでIssueを作成してご報告ください。よろしくお願いします。
高度な使用法と開発ストーリー
ご質問やご意見がございましたら、こちらからご連絡ください 。
Post MediumからZMediumToMarkdownによって変換されました。
本記事は Medium にて初公開されました(こちらからオリジナル版を確認)。ZMediumToMarkdown による自動変換・同期技術を使用しています。
































































