WWDC Quick Look 💓 By SwiftGGTeam
Expanding automation with the App Store Connect API

Expanding automation with the App Store Connect API

观看原视频

Highlight

App Store Connect API 在 2020 年新增 200 多个端点,把 App 版本元数据、截图和预览上传、审核提交,以及 Xcode Power and Performance 指标开放给自动化流程,但手动发布、内购和 Game Center 仍需在网页配置。


核心内容

App Store Connect API 最早解决的是重复性后台工作:管理团队用户、创建 provisioning profile、增删 beta tester、下载销售和财务报告。团队把这些步骤写进脚本后,发版准备会少很多手工操作。但还有一块重要流程留在网页里:创建新版本、维护 App Store 元数据、上传截图和预览、把版本送审。(00:35

2020 年的变化就是把这段发版链路补进 API。Apple 新增了 200 多个端点,数量超过原有 API 的一倍。App Metadata API 覆盖 App 分类、全球可用地区、主语言、许可协议、版本创建、平台添加、截图和 app preview 上传,以及名称、描述、关键词等本地化信息。完整范围从创建新版本一直到提交 App Review。(01:02

演示里的 Forest Explorer 是一个具体发版例子。它走了一次真实发版流程:先创建新版本,再改价格,接着更新元数据,关联已上传的 build,最后提交审核。这个顺序很适合放进 CI/CD 或发布脚本:每一步都能拿到明确的 HTTP 响应,失败时也能停在具体资源上。(03:17

同场还加入了 Power and Performance Metrics and Diagnostics API。它把 Xcode Organizer 里用来分析内存、启动时间、hang rate、磁盘写入和电量消耗的聚合数据开放出来。团队可以把线上性能趋势接进自己的 dashboard、bug 系统或回归检查流程。(22:39

边界也很清楚。手动发布仍要在 App Store Connect 网站或 iOS App 里完成,内购和 Game Center 配置也还在网页端。价格和可用地区变更会立刻影响线上 App,不能拿 live app 做实验。(02:0011:06


详细内容

创建 App Store 版本

04:16)创建版本的起点是 Apps 资源。每个 App 都有 App Store Versions 关系;每个版本有 platform 和 versionString。演示先用 bundle ID 查到 App ID,再创建 App Store Version。

GET /v1/apps?filter[bundleID]=com.example.ForestExplorer

200 OK
response data:
  app id: {appId}

关键点:

  • filter[bundleID] 来自演示,用来精确定位目标 App。
  • 响应里的 app id 也是文档里常见的 Apple ID,后续版本、价格和 build 关联都会用到它。
  • 这一步只读取资源,适合作为发布脚本的第一个校验点。
POST /v1/appStoreVersions

platform: IOS
versionString: 2.0
app relationship: {appId}

201 CREATED
response data:
  app store version id: {versionId}

关键点:

  • platformversionString 和 app relationship 是 transcript 明确点名的创建信息。
  • 201 CREATED 表示 App Store Connect 已经创建版本;登录网页后会在侧边栏看到它。
  • 响应返回的 version id 是后续本地化、build 关联和提交审核的主线资源。

用一次 PATCH 原子化修改价格计划

07:17)价格计划由 App Prices 和 Price Tier 组成。当前价格的 startDate 为 null;未来价格会带生效日期。演示先读取当前价格,并把相关的 priceTier 一起 include 进响应。

GET /v1/apps/{appId}/prices?include=priceTier

200 OK
response data:
  price startDate: null
  priceTier: Tier 1

关键点:

  • 当前价格用 startDate: null 表示正在生效。
  • priceTier 指向只读参考数据,和 App Store Connect 里的 All Prices and Currencies 页面一致。
  • include priceTier 后,脚本能在同一次响应里拿到价格层级关系。

08:24)如果要做一周免费促销,演示没有发三次创建请求,而是对 App 发一次 PATCH,把三个新价格作为同一个变更提交。

PATCH /v1/apps/{appId}

relationships.prices:
  - ${new-price-1}
  - ${new-price-2}
  - ${new-price-3}

included:
  - id: ${new-price-1}
    startDate: null
    priceTier: Tier 1
  - id: ${new-price-2}
    startDate: 2020-06-29
    priceTier: Tier 0
  - id: ${new-price-3}
    startDate: 2020-07-06
    priceTier: Tier 1

200 OK

关键点:

  • ${...} 是演示强调的临时 ID 语法,用来引用同一个请求里还没创建的资源。
  • included 里的三个资源会被 App Store Connect 创建、分配真实 ID,并链接到 App。
  • 价格和可用地区变更会马上上架生效,测试脚本时要避开已经发布的 live app。

上传 App Preview 的四步流程

13:33)元数据分成 App 级别和版本级别。本地化名称、subtitle、隐私政策在 App Info Localizations;截图、promotional text、关键词和 app preview 在 App Store Version Localization。演示以 US English 的 6.5 英寸 iPhone app preview 为例。

GET /v1/appStoreVersions/{versionId}/appStoreVersionLocalizations
GET {appPreviewSets relationship URL}

POST /v1/appPreviewSets
previewType: IPHONE_65
localization relationship: {localizationId}

关键点:

  • 每个版本至少有一个本地化,也就是主语言对应的 localization。
  • 如果 appPreviewSets 返回空数组,需要先创建 preview set。
  • IPHONE_65 是演示里的 previewType,代表 6.5 英寸 iPhone。

15:45)真正上传视频文件时,App Store Connect API 使用四步:创建 reservation、上传一个或多个 part、commit asset、检查错误。

POST /v1/appPreviews

file name: ForestExplorer.mov
file size in bytes: <bytes>
appPreviewSet relationship: {previewSetId}

response upload operations:
  method
  url
  length in bytes
  offset in bytes
  request headers

关键点:

  • 创建 reservation 时要告诉 App Store Connect 文件名和字节大小。
  • 响应会给出 upload operations;小文件可能只有一个操作,大文件可能有多个。
  • 客户端要按 lengthoffset 切分文件,并带上每个 operation 给出的 method、URL 和 headers。
for each upload operation:
  read bytes from offset with length
  upload that part with the provided method, URL, and headers
  retry only the failed part when a part upload fails

关键点:

  • 多个 part 的上传顺序不重要,也可以并行上传。
  • 单个 part 失败时只重试这一段,已经成功的 part 不需要重新上传。
  • 客户端要始终按多个 operation 设计,因为同一个资源今天可能一段上传,明天可能被拆成多段。
PATCH /v1/appPreviews/{previewId}

uploaded: true
source file MD5 checksum: <checksum>

关键点:

  • commit 阶段把 uploaded 设为 true,并提交原始文件的 MD5 checksum。
  • App Store Connect 会重新组装 asset、校验 checksum、检查文件完整性、视频长度、尺寸和音轨。
  • 处理是异步的;重新 fetch asset 后,state 变成 COMPLETE 才算成功,FAILED 时看 errors array 后删除、修复、重传。

关联 build 并提交审核

19:49)build 本身仍由 Xcode 或 Transporter 上传。API 负责查到 build id,然后把它挂到新版本。

GET /v1/builds

filters:
  app ID: {appId}
  pre-release version number: {preReleaseVersion}
  build version number: {buildNumber}

关键点:

  • 演示按 app ID、pre-release version number 和 build version number 三个条件定位 build。
  • 响应里的 build id 会用于版本关系更新。
  • 这一步适合检查 CI 刚上传的 build 是否已经进入 App Store Connect。
PATCH /v1/appStoreVersions/{versionId}/relationships/build

build id: {buildId}

204 NO CONTENT

关键点:

  • 204 NO CONTENT 表示关系更新成功,没有资源正文返回。
  • 这个响应能确认 build id 和 version id 都有效。
  • 元数据和 build 都准备好后,版本才具备送审条件。

21:00)App Review 仍然需要联系信息、demo account、备注和必要附件。API 里对应的是 App Review Details、App Review Attachments 和 App Store Version Submission。

POST /v1/appReviewDetails
version relationship: {versionId}

POST /v1/appStoreVersionSubmissions
version relationship: {versionId}

DELETE /v1/appStoreVersionSubmissions/{submissionId}

关键点:

  • Review details 可以在真正提交前多次 PATCH 修改。
  • 创建 App Store Version Submission 等同于点击 Submit for Review。
  • 如果发现错误,可以删除 submission 撤回;如果版本缺少截图等必要内容,创建 submission 会得到 400 和错误说明。

读取 Power and Performance 指标与诊断

23:21)Power and Performance API 读取的是 Xcode Power and Performance 视图背后的聚合数据。入口可以是 App,也可以是 build。

GET /v1/apps/{appId}/perfPowerMetrics
Accept: <Power and Performance custom media type>

GET /v1/builds/{buildId}/perfPowerMetrics
Accept: <Power and Performance custom media type>

关键点:

  • 从 App URL 的 perfPowerMetrics 关系读取最近版本的指标。
  • 从 build URL 的 perfPowerMetrics 关系读取某个 build 的指标。
  • transcript 明确提到返回里包含 HANG metrics,hang rate 的单位是 seconds per hour。

24:09)磁盘写入还有诊断签名和 log data。它们能把“写入量变高”推进到具体调用栈。

GET /v1/builds/{buildId}/diagnosticSignatures

response data:
  signature
  weight
  log data relationship

GET {log data relationship URL}
Accept: <Power and Performance custom media type>

关键点:

  • diagnostic signatures 按对总磁盘写入的贡献排序,最大贡献排在前面。
  • signature 标识运行时写入位置,weight 表示它对总写入的贡献。
  • log data 响应包含 app 信息、总磁盘写入和详细 call stack,可用来定位性能问题来源。

核心启发

  • 做什么:把发版草稿创建纳入 CI。 为什么值得做:本场演示的主链路从 app id 查询、版本创建、build 关联一直走到 App Review submission,适合把“准备发版”从网页点击改成可审计的脚本。 怎么开始:先实现 GET /v1/apps?filter[bundleID]=...POST /v1/appStoreVersions,把返回的 {versionId} 记录到发布流水线日志。

  • 做什么:做一个价格促销排期脚本。 为什么值得做:价格计划可以用一次 PATCH 原子化更新,避免半途只创建了部分价格节点。 怎么开始:先读取 /v1/apps/{appId}/prices?include=priceTier,再用临时 ID ${new-price-*} 生成完整促销周期;上线前加环境保护,禁止对 live app 运行测试 payload。

  • 做什么:把多语言元数据从仓库同步到 App Store Connect。 为什么值得做:App Info Localizations 和 App Store Version Localizations 覆盖名称、subtitle、privacy policy、截图、关键词和 promotional text,适合和本地化文件一起进入代码评审。 怎么开始:按 locale 读取 version localizations,先只同步一个市场的名称和关键词,确认审核流程无误后再接入截图和 preview set。

  • 做什么:实现可恢复的素材上传 worker。 为什么值得做:app preview、截图、App Review attachments 和 GeoJSON routing app coverage files 都走 reservation、part upload、commit、error check 这套流程。 怎么开始:把 upload operations 按 offsetlength 落成任务队列;单段失败只重试这一段;commit 后轮询 state,遇到 FAILED 时把 errors array 写进构建日志。

  • 做什么:把线上性能指标接进团队 dashboard。 为什么值得做perfPowerMetricsdiagnosticSignatures 能把 Xcode Organizer 的聚合数据放进自定义工具,hang rate、磁盘写入和调用栈可以进入回归告警。 怎么开始:先从 App 级 perfPowerMetrics 拉最近版本趋势,再对异常 build 请求 diagnosticSignatures 和 log data,把 signatureweight 和 call stack 关联到问题单。


关联 Session

评论

GitHub Issues · utterances