NIKKEI TECHNOLOGY AND CAREER

Androidアプリのリリース状態通知による公開漏れの防止

アプリチームの郷治です。日経電子版・紙面ビューアーのAndroidアプリの開発をしています。 本記事では、リリースされたAndroidアプリの公開状況を把握しやすくすることで公開漏れの防止を行った話について紹介します。

日経電子版Androidチームでは日経電子版・紙面ビューアーという2つのアプリをそれぞれGoogle Play StoreとAmazon App Storeで公開しており、Google Play Storeで段階的リリースを行っています。 段階的リリースとはアプリのアップデートをリリースする際に公開を段階的に行うという機能です。任意の割合のユーザーを対象にアップデートを配信でき、アプリの挙動やサーバーへの影響などを加味してリリースを広げられるようになります。
段階的な公開を利用したアプリのアップデートのリリース - Play Console ヘルプ この機能を利用すると該当バージョンに予期せぬ問題があり公開を停止した場合に影響範囲を最小限に抑えることができます。弊チームでは100%展開する前の数日間は99.99%のユーザーに対してアプリをリリースをしておき、アプリの公開状態を変更できる期間を置いています。しかし、段階的リリースの途中で次のリリースを公開してしまうと新しいリリースが同一の集団に割り当てられるため、公開途中であったリリースを新規にインストールすることはできなくなってしまいます。そのため、意図して同じ集団に次のリリースを適用したい時以外は必ず100%展開した後に次のリリースを公開しなければなりません。
例えば、1.0.0が100%公開されている状態で新規機能を搭載したバージョン(2.0.0)を90%公開にし、次のリリース(2.0.1)を10%の段階的リリースにした場合、10%には 2.0.1、残りの90%には1.0.0が割当られます。これにより、既に2.0.0にアップデートしたユーザーがアプリをアンインストールした場合、1.0.0までバージョンが戻る可能性があります。この運用ミスは非常に怖いのですが段階リリース途中であってもコンソール上で警告を出してくれません。このミスを防ぐために次ような対応を考えましたがどれも長期的に見ると上手くいかなさそうでした。

  1. 1つ前のリリースが100%になっていることを必ずチェックする => これができたら良いができないので困っている
  2. 定期的にコンソールを見に行って今どのバージョンが何%公開なのかを確認する => いつかやらなくなる
  3. リリースしたら必ずリリース拡大のリマインダーをセットする => 毎回余裕のあるリリースとは限らずリマインダー設定を忘れてしまう またはリマインドされてもすぐに対応しないので忘れる

このように人間の努力に委ねた「気を付ける運用」を続けるといつか事故が起こってしまいます。

どのようにしたら人間が頑張らずにリリースの状態を把握できるのかをチームで議論したところ、botで毎朝決まった時間に日経アプリの公開状況をSlackに通知させようということになりました。毎朝1回であれば通知が届いたとしても鬱陶しいと感じることはなく、また1日見落としても毎日来るため「チーム全員がリリース状態を知らない」事態になる確率を大幅に減らすことができると思います。また、Amazonの方は段階的リリースを行っていませんがGoogleに公開しているアプリとAmazonに公開しているアプリそれぞれのリリース状態を把握するのは手間がかかる作業だったのでAmazon App Storeからもリリース状態を取得することにしました。

リリース状況を把握するための実装について

実装方針

GAE上でAPIを公開し、Google Schedulerで定時にAPIを叩いてSlackに通知します。非常に簡単にデータ取得と送信の流れを記すと以下のようになります。

  1. Google Play Developer Publishing API を叩いてGoogle Play Storeでの公開情報を取得する
  2. Amazon App Submission API を叩いてAmazon App Storeでの公開情報を取得する
  3. 1、2の情報をマージしてSlackに通知する

1、 2の順にAPIの叩き方や得られる情報について説明していきます。

Google Play Developer Publishing API

① 認証

Google APIを叩くためのサービスアカウントを発行する必要があります。adminでアカウントを発行し、権限を設定します。今回は閲覧だけなので閲覧権限のみを付与しました。 Google Play Developer Publishing API ドキュメント: 認証 を見ながら進めていきます。 アカウントを発行すると秘密鍵のコピーがダウンロードされるので任意のパスにファイルを置き、スコープを設定します。以下のコードでclientを生成します。

CREDENTIAL_FILE_PATH = "path"  # credential fineのpath
credentials = service_account.Credentials.from_service_account_file(CREDENTIAL_FILE_PATH)
credentials.with_scopes(
    [
        'https://www.googleapis.com/auth/androidpublisher'
    ]
)
client = discovery.build('androidpublisher', 'v3', credentials=credentials)

② リリースの編集をするidを取得する

状態の取得には、editを作成しそのidを利用して操作を行う必要があります。以下のようにinsertを呼び出し、指定したパッケージのeditIdを取得します Google Play Developer Publishing API: api reference 今回叩きたいのはedit APIなので

package_name = "package name"  # アプリのパッケージ名
res = client.edits().insert(packageName=package_name).execute()

以下のレスポンスが返るのでidを取得します。

{
  "id": string,
  "expiryTimeSeconds": string
}

③ リリース情報を取得する

得られたeditIdを使ってリリース情報を取得します。Tracks APIを使いたいので

track_name = "track name" # productionなど
res = client.edits().tracks().get(packageName=package_name, editId=edit_id, track=track_name).execute()

レスポンスは以下が返ります。

{
  "track": string,
  "releases": [
    {
      "name": string,
      "versionCodes": [
        string
      ],
      "releaseNotes": [
            略
      ],
      "status": enum (Status),
      "userFraction": number,
      "countryTargeting": {
        略
      },
    "inAppUpdatePriority": integer
    }
  ]
}

Statusのenumはこちらを参照してください。

レスポンスの releases[].versionCodes[], versionCodes[].status, versionCodes[].userFraction を使って以下のようなメッセージを作成しました。

日経電子版 :denshiba:    バージョン54300 (5.43.0)は段階的リリース中です    公開割合: 99.9%
紙面ビューアー :newspaper:    バージョン21601 (2.16.1)は段階的リリース中です    公開割合: 99.9%

Amazon App Submission API

次にAmazon App Submission APIについてです。 Amazon App Submission API ドキュメント こちらのドキュメントを見ながら進めていきます。

① 認証

Amazon APIのリクエストに設定するtokenを発行します。Amazon開発者コンソールに入ってセキュリティプロファイルを作成しアプリとの関連を設定するとclient_id、client_secretが発行されます。

以下のようにrequest bodyにclient_id、client_secret、scopeなどを指定してtoken APIにpostします。

headers = {
    "Content-Type": "application/x-www-form-urlencoded"
}
body = {
    "client_id": AMAZON_CLIENT_ID,
    "client_secret": AMAZON_CLIENT_SECRET,
    "grant_type": "client_credentials",
    "scope": "appstore::apps:readwrite"
}
AMAZON_TOKEN_URL = "https://api.amazon.com/auth/o2/token"
res = requests.post(AMAZON_TOKEN_URL, headers=headers, data=body)

レスポンスからaccess_tokenが取得できました。

{
  "access_token":"token",
  "scope":"appstore::apps:readwrite",
  "token_type":"bearer",
  "expires_in":3600
}

② editIdの取得

次はこちらのドキュメントを見ながら進めます。 Amazon App Submission API Swagger
Google APIと同様に edit APIを叩くのですが、Googleは新しい編集を作るとすでに作られているeditIdが自動で閉じられますがAmazonは一度作ったものは明示的に閉じるか開いているものがあればそれを使う、という仕様になっています。どちらも同時編集はできないということは同じです。今回はすでに開かれているものを取得するのでgetします。

package_id = "package ID"
headers = {
    "Authorization": "Bearer " + access_token
}
edit_url = AMAZON_APP_URL + package_id + "/edits"
edit_response = requests.get(edit_url, headers=headers)

レスポンスは下記です。

{
  "id": "string",
  "status": "string"
}

これでidを取得できました.

③ 最新バージョンのステータスを取得

AmazonにはGoogleのTracks APIのようなAPIが用意されておらず公開が終わったapk情報を取得できないため、公開中 or 審査中のみを取得します。 その旨がこちら に書かれています。

Google Play APIは、現時点でAmazonアプリストアがサポートしていないリソース(テスターやトラッキングなど)をサポートしています。

headers = {
    "Authorization": "Bearer " + access_token
}
apks_url = AMAZON_APP_URL + package_id + "/edits/" + edit_id + "/apks"
apk_response = requests.get(apks_url, headers=headers)

このリクエストで得られるレスポンスです。

{
    "versionCode": 0,
    "id": "string",
    "name": "string"
}

ただし、statusが全公開の場合は何も返らないので何もなければ全公開として通知します。

こちらでは以下のようなメッセージになりました。

:star: Kindle 日経電子版 :denshiba: の最新版が完全公開されています
:star: Kindle 紙面ビューアー :newspaper: の最新版が完全公開されています

公開して通知

生成されたメッセージをSlackに送信するためのAPIはGoogle App Engine上で公開しており、 Google Cloud Scheduler に定期的に叩くjobを設定しています。

schedulerの画面

レスポンスが変わったりして通知が来なくなることもありますが App EngineのError Reportingで通知をONにしておけば検知できます。

APIを叩くと以下のような通知がSlackに届きます。良さそうですね。
botの投稿

最後に

このbotが通知してくれるようになってから毎朝最新バージョンや段階的リリースの割合を一覧して確認する運用ができました。今後も「人が気を付ける運用」を減らす取り組みができたらと思っています。

郷治雅
ENGINEER郷治雅

Entry

各種エントリーはこちらから

キャリア採用
Entry
新卒採用
Entry
カジュアル面談
Entry