🥹

App Store Connect API で新バージョン作成 + アップデート文設定を自動化する

2023/12/07に公開

これは GENDA Advent Calendar 2023 の7日目の記事です。

https://qiita.com/advent-calendar/2023/genda

App StoreでiOSアプリのアップデートをする際、アップデート文をApp Store ConnectのWebサイトでの操作なしに自動で設定するしくみを作りました。

更新履歴

動機・課題

私の担当するiOSアプリではInstagram等にならい、アップデート文に基本的には毎回同じ文言を設定することにしました。自動アップデートの導入以降アップデート文をユーザーが目にすることは減り、毎回文章を凝る理由もなくなったと判断したためです。

文章作成のタスクはなくなり、アップデート申請時にはアップデート文をコピペ入力するだけでよくなりましたが[1]、その作業も面倒です。ローカライズ対応している言語が複数ある場合その数だけコピペを繰り返す必要があり、間違えないようにするにはけっこう神経を使います。

解法

煩雑さとミスをなくすべくApp Store Connect APIを利用したRubyスクリプトを作ってこの作業を自動化しました。

https://gist.github.com/oinariman/d63566eda7a8c7d8ce0c323e8b3a023d

このスクリプトは以下の二つのタスクを実行します。

  1. アプリの新バージョンを作成する
  2. 新バージョンのアップデート文を設定する

スクリプトの使い方

以下のように実行します。

$ ruby add_new_version.rb <アプリID> <APIキーID> <Issuer ID> \
<APIキーの秘密鍵ファイルのパス> [バージョン文字列]
引数 説明
<アプリID> App Store Connectのアプリページに「Apple ID」として記載されています。
<APIキーID>
<Issuer ID>
App Store Connect APIの接続のために必要な情報です。下記ページを参考にApp Store ConnectのWebサイトで作成・取得してください:
Creating API Keys for App Store Connect API
<APIキーの秘密鍵ファイルのパス> APIキーの秘密鍵ファイルはAPIキー作成時に一度だけダウンロードできます。ファイルを配置したパスを指定してください。
[バージョン文字列] 新バージョンのバージョン文字列です。(例: 1.0.1)

アップデート文は実行ディレクトリの./whats_new/以下にテキストファイルとして、各ローカライズ言語のロケール文字列名をつけたファイル名で置いておきます。

whats_new/
├─ en-US.txt
└─ ja.txt
en-US.txt
Fixed minor bugs.
ja.txt
軽微なバグを修正しました。

アプリに設定されているローカライズ言語のロケール文字列(jaen-US)を調べるには、スクリプトを[バージョン文字列]引数を省略して呼んでください。

$ ruby add_new_version.rb <アプリID> <APIキーID> <Issuer ID> \
<APIキーの秘密鍵ファイルのパス>

# 出力例:
Locales:
en-US
ja

スクリプトの作り方

1. JWTの作成

App Store Connect APIに接続するには、認証のためのJSON Web Token (JWT) が必要です。APIキー、Issuer IDをもとにJWTヘッダー、JWTペイロードを作成し、APIキーの秘密鍵で暗号化してトークンを作成します(Generating Tokens for API Requests)。JWT.ioにJWTの暗号化にに使えるライブラリの一覧がありますが、今回はその中の ruby-jwtを使って以下のような関数を作りました。

KEY_ID = 'APIキーのID'
ISSUER_ID = 'Issuer ID (App Store Connectの「ユーザとアクセス」に記載)'
AUTH_KEY_PATH = '秘密鍵ファイルのパス'
TOKEN_LIFETIME = 600 # JWTの生存時間。600秒 = 10分。最大20分まで設定できる。

def make_token
    header = {
        "alg": "ES256",
        "kid": KEY_ID,
        "typ": "JWT"
    }

    now = Time.now.to_i
    payload = {
        "iss": ISSUER_ID,
        "iat": now,
        "exp": now + TOKEN_LIFETIME,
        "aud": "appstoreconnect-v1"
    }

    ecdsa_key = OpenSSL::PKey::EC.new IO.read AUTH_KEY_PATH
    return JWT.encode payload, ecdsa_key, "ES256", header  
end

作成したトークンをHTTPリクエストヘッダーにAuthorization: Bearer [トークン]のようにして付与して使います。

2. アプリの新バージョンを作成する

使用API: Create an App Store Version | Apple Developer Documentation

リクエストのattribute以下(AppStoreVersionCreateRequest.Data.Attributes)の必須項目は”platform”と”versionString”だけなので、iOSアプリの新バージョンを作成する最小限のJSONはこうなります:

{
  "data": {
    "type": "appStoreVersions",
    "attributes": {
      "platform": "IOS",
      "versionString": "バージョン文字列"
    },
    "relationships": {
      "app": {
        "data": {
          "type": "apps",
          "id": "アプリID"
        }
      }
    }
  }
}

このAPIリクエストに成功するとアプリページで新規バージョンを作成する作業を行なったのと同じ状態になります。

3. 新バージョンのアップデート文を設定する

アプリのメタデータは下図のような階層構造になっています。各アプリに複数のバージョンが紐付き、各バージョンに複数のローカライズ情報が紐づきます。

アプリのメタデータの階層構造

アップデート文を更新するには各ローカライズ情報(図の右端の列)のIDを特定する必要があります。そのため以下の手順で順番にAPIにリクエストしていきます。

3.1 最新バージョンのバージョン情報を得る

使用API: List All App Store Versions for an App

このAPIにアプリIDを投げると対象アプリの全バージョンのリストを取得できます。その先頭=最新バージョンです。最新バージョンの情報は新バージョン作成APIのレスポンスからも得られますが、すでに新バージョンが作成されていて新バージョン作成リクエストがエラーになった場合は全バージョンリストから取り出します。

3.2 最新バージョンの全ローカライズ情報を得る

使用API: List All App Store Version Localizations for an App Store Version

このAPIにバージョンIDを投げてバージョンに紐づく全ローカライズ項目を取得します。これは対応ローカライズ言語の数だけ取得できます。

3.3 アップデート文の設定

使用API: Modify an App Store Version Localization

このAPIにローカライズIDとアップデート文のテキストを投げて設定することができます。今回のスクリプトでは./whats_new/ディレクトリ以下に各ローカライズ言語のテキストをロケール文字列のファイル名にして置いておくことにしました。

例(再掲)
whats_new/
├─ en-US.txt
└─ ja.txt

前項で取得した全ローカライズ項目リストの各項目について、ロケール文字列の一致するファイル名のテキストをAPIに投げる作業を繰り返してアップデート文言の設定を完遂できます。

リクエストのattributes以下(AppStoreVersionLocalizationUpdateRequest.Data.Attributes)のアップデート文にあたる項目は"whatsNew"なので、JSONはこうなります:

{
  "data": {
    "id": "ローカライズID",
    "type": "appStoreVersionLocalizations",
    "attributes": {
      "whatsNew": "アップデート文"
    }
  }
}

以上

脚注
  1. アップデート申請のためにApp Store Connectでアプリの新バージョンを作った際、申請に必要なアプリのメタデータのほとんどの項目は前バージョンと同じ内容であらかじめ埋められています。しかし「このバージョンの最新情報」(アップデート文)は空欄です。ここにも前バージョンと同じ内容が入ればコピペ作業すら省けるのですが、「最新情報」を書く欄ということなのでそうもいかないのでしょう。 ↩︎

Discussion