iOS 持续集成:更完备的 App Store Connect API

2166次阅读  |  发布于4年以前

引言

时隔两年 App Store Connect API 有了更新,WWDC 2018 推出了 App Store Connect API ,用于自动化一些 App Store Connect 后台操作。这次更新包含了 app 元数据相关的API,补上了原来缺失的重要一环, 使得几乎可以通过 App Store Connect API 完成 App Store Connect 上的所有操作。今后开发、证书配置、用户管理、测试、发布全流程都可以通过 API 完成。

需要注意的是, 配置应用内购买和 Game Center 还是需要通过App Store Connect 网站进行配置。

现有的解决方案

Fastlane 已经是一个完善的自动化工具,它提供了如 produce 等工具用于更新元数据。为啥还要关心 App Store Connect API 呢?

首先 App Store Connect API 是苹果官方提供的,适用于所有环境。Fastlane 基于 ruby 的,限制适用的技术栈。

其次 Fastlane 是通过 Spaceship 来访问 Apple Developer Center 和 App Store Connect 的。目前 Spaceship 是通过解析网页来实现自动处理的,会有以下几个问题:

  1. Apple Developer Center 和 App Store Connect 是两个不同的网站,因此需要两次认证,存两份cookie。
  2. 现在 Apple ID 强制开启了双重认证, 每次登录需要验证码,无法完全自动化。cookie 也只能保持 1 个月。
  3. Apple Developer Center 和 App Store Connect 如果有页面更新,Spaceship 就需要升级来适应变化。

如果都能够用 App Store Connect API 来实现,则这些问题就不存在了。

App Store Connect API 也有一些不完善的地方,例如 其 token 有效期只有 20 分钟,固然增强了安全性,但是如何签名产生这个 token,还需要总结出一个最佳实践。

瑕不掩瑜,业界对 App Store Connect API 还是蛮期待的。Fastlane 在 2.150.0 的分支中已经添加对新的 App Store Connect API 的支持。相关讨论 issue:Fastlane: Support new App Store Connect APIs[1]

App Store Connect API 的新内容

文档

这次新增了 200+ 的 RESTful endpoint, 和原来相比翻了一倍。苹果爸爸还将提供一个 openAPI 规范文件供您下载(OpenAPI Specification[2] 是流行的swagger格式的开放标准第三版)。可以在 swagger UI 中查看它,以获取快速的 API 参考。或者更好的方法是将其输入代码生成器中,以更快,更轻松地引导几乎所有语言的 API 集成。苹果爸爸还声称会添加了一些有关速率限制和文件上传等主题的新说明文章,提供可下载的示例代码,以演示重要的 API 概念,例如创建和签名身份验证令牌,与API响应进行交互以及使用新的资产上传 API。

。详情可以参考:App Store Connect API Resources[3]

应用元数据API (app metadata API)

Session Expanding automation with the App Store Connect API[4] 中 Geoff Coffey 是通过一个例子,贯穿讲解了 相关的 API,包括以下 5 个步骤:创建一个新版本,设置定价以更新应用程序元数据,将构建与该版本相关联,然后将该新版本提交给App Review 。本文就做一个简要的总结,不再一一列举了。

新API遵守原有的 App Store Connect API 的认证方式。可以参考文章 App Store Connect的新特性(WWDC 2018 session 301 & 303)[5], App Store Connect API[6]

基本规则

应用元数据的相关资源以及它们的关系如下图所示。

图中每个节点代表 restful api 中的一个资源,例如 /v1/apps。图中联线代表资源之间的关联,例如:一个 App 可以有多个 App Store Versions。每个资源的数据结构如下

data: {
    "type": 资源名,
    "id": 资源ID,
    "attributes": {
        资源自己的属性
    },
    relationship: {
        "关联资源名": {
            "data" : { "type": 资源名, "id": 资源ID }
        }
    }
}

查询资源

通过 GET 方法 请求资源路径就可以获得对应资源的元数据。

可以通过添加形如 filter[key]=value 的 query string 来过滤返回的结果。例如:

GET /v1/apps?filter[bundleID]=org.forestexplorer.ForestExplorer
GET /v1/builds?filter[app]=appid&filter[perReleaseVersion.version]=1.1&fileter[version]=3

此时返回结果 data 是一个数组。

可以通过指定资源的 ID,来确定的获得一个资源的数据。例如:

GET /v1/apps/资源ID

此时返回结果 data 是一个对象。

当然也可以获取一个确定资源的关联资源。例如:

GET /v1/appStoreVersions/资源ID/appStoreVersionLocalizations
GET /v1/appStoreVersionLocalizations/资源ID/appPreviewSets

可以通过添加include=关联资源名的 query string 来让返回结果同时包含关联资源, 例如:

GET /v1/apps/资源ID/prices?include=priceTier

修改资源

修改资源通过 http 的 patch 方法。路径需要指定对应的资源 ID。有意思的是,如果想要用一个原子操作,修改资源的同时为资源添加关联资源。而此时由于新添加的资源还没有创建,没有一个正式的资源 ID。可以通过 ${临时资源ID} 的方式由创建者临时指定一个资源 ID, 并在 data 的同级添加一个 included 其中包含临时资源 id。只要临时资源 ID 相同,就会关联并创建。在返回结果中会更正为真正的资源 ID。例如

PATCH /v1/apps/资源ID/
{
    "data": {
        "type": "apps",
        "id": 资源ID,
        "relationships": {
            "prices": {
                "data" : [{ "type": "appPrices", "id": "${tmpid}" }]
            }
        }
    },
    "included": [{
        "type": "appPrices",
        "id": "${tmpid}",
        "attributes": {
        },
        "relationships": {
            "priceTier": {
                "data": { "type": "priceTiers", "id": "0" }
            }
        }
}

当然也可以直接修改一个资源的关联资源,例如修改一个appStoreVersion 关联的build

PATCH /v1/appStoreVersions/资源ID/relationships/build

创建资源

一个典型的例子是在 AppStore 添加一个新的版本:

POST /v1/appStoreVersions

{
    "data": {
        "type": "appStoreVersions",
        "attributes": {
            "platform": "IOS",
            "versionString": "1.1"
        },
        "relationships": {
            "app": {
                "data": {"type" : "apps", "id" : "资源ID" }
            }
        }
    }
}

创建新资源不用添加"id"属性,创建成功后,ID会自动生成,并在结果中返回

appPreviewsappScreenshots 不仅仅包含元数据,还包含具体的图片、视频文件,这些怎么上传呢?图片、视频文件被统一叫做 asset,代表大数据文件。 在创建 appPreviewsappScreenshots 的元数据成功后,服务端会返回一个属性字段 "uploadOperations" 其中包含了上传 asset 的相关信息。例如 urlmethodoffsetlength,以及请求的headers。使用者还需要通过这些信息上传asset。

需要注意的是, "uploadOperations" 可能返回一个数组,这样可以将大文件分段上传。上传的顺序可以打乱,也可以并发上传,其中一块失败了只需要重传失败的块就行了。

当所有块都上传成功后,还需要更新一下 appPreviews 元数据的状态。标记 uploadedtrue 并且附上 sourceFileChecksum。app store connect 会对上传的asset再做处理。这个处理是异步的。需要通过查询 appPreview 的元数据来确认处理状态。

诊断数据API (Power and Performance Metrics and Diagnostics API)

诊断数据API获取的数据是显示在Xcode中的功能和性能视图(上图)中的数据。有另外一个session: Identify trends with the Power and Performance API[7] 详细讲解其中的具体数据内容。

诊断数据可以通过 app 或者 build 维度获取,具体路径形如:

GET /v1/apps/资源ID/perfPowerMetrics
GET /v1/builds/资源ID/perfPowerMetrics

这里由于返回的数据是苹果定制的格式,因此需要在请求头中添加accept类型如下:

accept: application/vnd.apple.xcode-metrics+json

特别指出,在磁盘写入时,会包含一些堆栈信息,因此还有一个diagnosticSignature的资源节点以及关联的logs资源节点

GET /v1/builds/资源ID/diagnosticSignatures
GET /v1/diagnosticSignatures/资源ID/logs

总结

新的 app metadata API 提供了一种官方支持的自动化发布app的方案。大家可以开动想象力,发挥它的潜力。例如,通过这些 API 一些面向企业的 APP 都可以高效的自动生成定制化版本。再结合苹果正在推广的 Apple Business Manager ,定向为企业发布定制化版本的app。或者未来会涌现出一些简化开发的平台,提供模板和上线服务。只要你有创意和资源,就可以一键在AppStore 上发布一个应用了。

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8