资讯动态

fastlane Spaceship App Store Connect API 完整实战指南:从登录鉴权到审核上架的自动化操作

发布时间:2026/9/10 3:40:20 来源:尧图企业网站定制
fastlane Spaceship App Store Connect API 完整实战指南从登录鉴权到审核上架的自动化操作【免费下载链接】fastlane The easiest way to automate building and releasing your iOS and Android apps项目地址: https://gitcode.com/GitHub_Trending/fa/fastlane本指南以 fastlane 仓库中 spaceship/docs/AppStoreConnect.md 为核心系统讲解 Spaceship 如何通过App Store Connect API以脚本方式完成应用管理、版本元数据修改、TestFlight 分发、审核提交、评分评论获取乃至 Bundle Id 能力配置与 Webhook 管理。读完本文你将掌握基于 API KeyAuth Key与 Apple ID 两套登录体系的全部常用操作并能将Spaceship::ConnectAPI的调用直接复用到自己的 CI/CD 流水线中。一、背景Spaceship 与两套 App Store 接口Spaceship 是 fastlane 体系与 Apple 开发者后台打交道的底层库仓库位置 spaceship/lib/spaceship。从文档可以明确看到Spaceship 实际封装了两代接口App Store Connect API新版所有模型类统一挂在Spaceship::ConnectAPI模块下例如Spaceship::ConnectAPI::App、Spaceship::ConnectAPI::Build、Spaceship::ConnectAPI::BundleId。它使用 Apple 提供的 API Key.p8文件签发 JWT 进行鉴权。Tunes旧版 Web 接口Tunes是 iTunes Connect 时代的命名遗存。当某些能力如改价格、拉取评分与评论、App Analytics尚未在新版 Connect API 中提供时仍需通过Spaceship::Tunes::Application配合 Apple ID 登录来操作。文档特别提醒如果你同时使用 Developer Portal 与 App Store Connect两处需要分别登录因为两者可能使用不同的用户凭证详见仓库内 spaceship/docs/Authentication.md。想快速体验在终端执行irb后输入require spaceship即可开始交互式探索。二、登录鉴权两种方式的核心用法2.1 API Key 方式Connect API 首选token Spaceship::ConnectAPI::Token.create( key_id: the-key-id, issuer_id: the-issuer-id, filepath: File.absolute_path(../AuthKey_the-key-id.p8) ) Spaceship::ConnectAPI.token token创建 token 后将其赋给Spaceship::ConnectAPI.token之后所有 ConnectAPI 调用都会自动携带该凭证。从源码 token.rb 可以看出几个值得注意的实现细节令牌时长Apple 支持的最大过期时间为 20 分钟源码中定义为MAX_TOKEN_DURATION 1200秒默认值DEFAULT_TOKEN_DURATION 500秒。可通过duration参数或环境变量SPACESHIP_CONNECT_API_TOKEN_DURATION调整。JWT 载荷使用 ES256 椭圆曲线签名payload 中aud根据团队类型取appstoreconnect-v1或apple-developer-enterprise-v1iat会刻意回拨 60 秒避免本机时钟略快于 Apple 服务器导致令牌被拒。环境变量注入key_id、issuer_id、filepath、key、duration、in_house均可通过SPACESHIP_CONNECT_API_KEY_ID、SPACESHIP_CONNECT_API_ISSUER_ID、SPACESHIP_CONNECT_API_KEY_FILEPATH、SPACESHIP_CONNECT_API_KEY、SPACESHIP_CONNECT_API_TOKEN_DURATION、SPACESHIP_CONNECT_API_IN_HOUSE等环境变量提供非常适合 CI 场景。JSON Key 文件除.p8路径外Token.from_json_file(filepath)还支持包含key_id与keybase64 的私钥内容的 JSON 文件缺失必填字段时会明确报错。2.2 Apple ID / 会话方式Tunes 旧接口旧版接口能力调价、评分评论、Analytics 等依赖 Apple ID 登录态。仓库提供了对应的 CLI 会话持久化工具运行spaceship login通过 commands_generator.rb即可复用 fastlane 的账号会话。两种方式务必按需选择切不可混用ConnectAPI模型与 Tunes 模型的鉴权上下文。三、应用Applications管理3.1 查询与遍历# Fetch all available applications all_apps Spaceship::ConnectAPI::App.all # Find a specific app based on the bundle identifier app Spaceship::ConnectAPI::App.find(com.krausefx.app) app Spaceship::ConnectAPI.get_app(app_id: 1013943394).first # Access information about the app app.id # 1013943394 app.name # Spaceship App app.bundle_id # com.krausefx.app app.sku # SpaceshipApp01 app.primary_locale # en-US # Show the names of all your apps Spaceship::ConnectAPI::App.all.collect do |app| app.name end对照模型 app.rb 可以看到App.all内部调用client.get_apps并自动翻页all_pages后flat_map(:to_models)默认携带ESSENTIAL_INCLUDES appStoreVersions。App.find(bundle_id)其实是先按bundleId过滤拉全量再做内存匹配因此参数就是 Bundle ID 字符串。响应解析由 model.rb 中的Models.parse完成它根据 JSON 中data的type查找对应模型类再依据attr_mapping表把 API 的驼峰字段如bundleId映射为 Ruby 的蛇形属性如bundle_id同时生成别名读写方法。3.2 创建新应用# Currently only works with Apple ID login (not API Key) app Spaceship::ConnectAPI::App.create(name: App Name, version_string: 1.0, # initial version sku: 123, primary_locale: en-us, bundle_id: com.krausefx.app, platforms: [IOS], company_name: krause inc)App.create最终路由到client.post_appapp.rb。文档明确标注该操作目前仅支持 Apple ID 登录不支持纯 API Key需注意鉴权方式的限制。3.3 修改非版本级信息与价格元数据App 名称、隐私政策 URL 等以及价格修改走 Tunes 旧接口app Spaceship::Tunes::Application.find(com.krausefx.app) details app.details details.name[en-US] App Name details.privacy_url[en-US] https://fastlane.tools details.save! # To change the price of the app (its not necessary to call save! when updating the price) app.update_price_tier!(3)注意这里取值是按语言代码的 hash 结构如details.name[en-US]改价格时文档特别注明无需调用save!update_price_tier!会直接提交。四、App 版本AppVersions与元数据修改4.1 同一时刻的多个版本状态同一时刻一个 App 最多存在 2 个 App Store 版本通常是已在商店上架的版本通过get_live_app_store_version获取和正在编辑、尚未上架的版本get_edit_app_store_version。生产版本部分字段如应用描述仍可修改但大多数选项已被锁定。app.get_live_app_store_version # the version thats currently available in the App Store app.get_edit_app_store_version # the version thats in Prepare for Submission, Metadata Rejected, Rejected, Developer Rejected, Waiting for Review, Invalid Binary mode app.get_latest_app_store_version # the version thats the latest one app.get_pending_release_app_store_version # the version thats in Pending Developer Release or Pending Apple Release mode app.get_in_review_app_store_version # the version that is in In Review mode上述方法定义位于 app.rb。除get_latest_app_store_version外其余默认都会带上AppStoreVersion::ESSENTIAL_INCLUDES关系文档中提到的各种 App Store 状态PREPARE_FOR_SUBMISSION、WAITING_FOR_REVIEW、IN_REVIEW、PENDING_DEVELOPER_RELEASE、READY_FOR_SALE等在 app_store_version.rb 的AppStoreState/AppVersionState常量中有完整枚举。4.2 读取与更新版本元数据v app.get_edit_app_store_version # Access information v.app_version_state # Waiting for Review v.version_string # 0.9.14 # Build is not always available in all app_version_state, e.g. not available in Prepare for Submission build_number v.build.nil? ? nil : v.build.version # Update app metadata copyright #{Time.now.year} Felix Krause v.update(attributes: { copyright: copyright })注意v.update的attributes会被 model.rb 中的reverse_attr_mapping反转为 API 所需的字段名蛇形转驼峰再执行 PATCH 请求因此你始终用 Ruby 侧命名写即可。4.3 本地化Localization内容# Get a list of available languages for this app version app.get_edit_app_store_version(includes: appStoreVersionSubmission,build,appStoreVersionLocalizations) localizations version.appStoreVersionLocalizations localization localizations.first localization.locale # en-GB localization.description # App description # Update localized app metadata localization.update(attributes: { description: New Description })把includes显式传成逗号分隔的关系列表如appStoreVersionSubmission,build,appStoreVersionLocalizations就能一次取回审核提交、构建与本地化条目从而省去多次往返。4.4 年龄分级Age Rating# fetch_age_rating_declaration with fetch_live_app_info or fetch_edit_app_info app_info app.fetch_edit_app_info declaration app_info.fetch_age_rating_declaration unless app_info.nil? # update age_rating_declaration declaration.update(attributes: { violenceCartoonOrFantasy: NONE, matureOrSuggestiveThemes: NONE, unrestrictedWebAccess: false })年龄分级声明的修改路径是AppInfo → AgeRatingDeclaration两级对象。可用的分级取值可参考仓库内的 deliver/assets/example_rating_config.json如各暴力/主题项的NONE/INFREQUENT/FREQUENT等级及布尔开关以及 deliver/Reference.md 中关于分级配置的完整说明。4.5 版本对象可用属性一览文档整理出的可访问字段可分为三层#### # General app store version metadata (app_store_version) #### attr_accessor :platform attr_accessor :version_string attr_accessor :app_store_state attr_accessor :app_version_state attr_accessor :store_icon attr_accessor :watch_store_icon attr_accessor :copyright attr_accessor :release_type attr_accessor :earliest_release_date attr_accessor :is_watch_only attr_accessor :downloadable attr_accessor :created_date attr_accessor :app_store_version_submission attr_accessor :app_store_version_phased_release attr_accessor :app_store_review_detail attr_accessor :app_store_version_localizations #### # App Review Information (app_store_review_detail) #### attr_accessor :contact_first_name attr_accessor :contact_last_name attr_accessor :contact_phone attr_accessor :contact_email attr_accessor :demo_account_name attr_accessor :demo_account_password attr_accessor :demo_account_required attr_accessor :notes attr_accessor :app_store_review_attachments #### # Localized values (app_store_version_localization) #### attr_accessor :description attr_accessor :locale attr_accessor :keywords attr_accessor :marketing_url attr_accessor :promotional_text attr_accessor :support_url attr_accessor :whats_new attr_accessor :app_screenshot_sets attr_accessor :app_preview_sets这些attr_accessor实际上由 model.rb 的attr_mapping根据模型内声明的映射表动态创建app_store_version.rb、app_store_review_detail.rb、app_store_version_localization.rb等模型文件均位于 spaceship/lib/spaceship/connect_api/models 下其中保留了每个属性的完整类型、描述与备注。五、完整审核生命周期选构建 → 提交 → 发布5.1 选择用于审核的构建version app.get_edit_app_store_version build Spaceship::ConnectAPI::Build.all(app_id: app.id, platform: platform).first version.select_build(build_id: build.id)select_build在 app_store_version.rb 中定义底层对应 Connect API 的版本关联构建操作。注意在Prepare for Submission状态下通常还没有可选构建需要先上传构建并处理完成后才能关联。5.2 提交审核version.create_app_store_version_submission提交动作会创建AppStoreVersionSubmission对应 app_store_version.rb。提交审核前需要把完整的审核信息联系信息、演示账号、审核备注、附件等即上文app_store_review_detail那组属性与所有本地化元数据准备齐全。完整可参考的实现范例在 deliver 的 submit_for_review.rbfastlane 的deliveraction对应测试 fastlane/spec/actions_specs/deliver_action_spec.rb也正是走这套逻辑完成准备提交 → 提交审核的端到端流程。5.3 发布已过审的构建当版本处于Pending Developer Release或Pending Apple Release由get_pending_release_app_store_version获取时可主动触发发布。文档给出两种等价写法version app.get_pending_release_app_store_version unless version.nil? Spaceship::ConnectAPI.post_app_store_version_release_request(app_store_version_id: version.id) end或直接调用模型实例方法version app.get_pending_release_app_store_version version.create_app_store_version_release_request unless version.nil?两种方式最终都会创建AppStoreVersionReleaseRequest模型见 app_store_version_release_request.rb适合人工点选过审后自动上架的自动化发布场景。六、Build Trains 与构建管理TestFlight6.1 理解版本号与构建号文档先用一张图澄清两个最易混淆的概念version number版本号由CFBundleShortVersionString决定是 App Store 上对用户展示的版本如0.9.21build number构建号由CFBundleVersion决定商店页面不可见上传新构建前必须递增如99993。Build Train构建序列指同一version number下的全部构建集合序列内部可以有n个构建每个构建拥有不同的build number。6.2 遍历 Build TrainsTunes 接口app Spaceship::Tunes::Application.find(com.krausefx.app) # Access all build trains for an app app.all_build_train_numbers # [0.9.21] # Access the build train via the version number train app.build_trains[0.9.21] # Access all builds for a given train train.count # 1 build train.first6.3 读取构建详情并提交 Beta 审核# Continue from the BuildTrains example build.build_version # 99993 (the build number) build.train_version # 0.9.21 (the version number) build.install_count # 1 build.crash_count # 0 build.internal_state # testflight.build.state.testing.ready build.external_state # testflight.build.state.submit.readybuild.internal_state/build.external_state分别表示内测/外测状态。在设置好全部必要的 TestFlight 元数据后可以直接把构建提交给外部 Beta 审核build.submit_for_testflight_review!构建的底层模型见 spaceship/lib/spaceship/connect_api/models/build.rb旧版接口实现在 test_flight/build.rb。关于 TestFlight 的深入用法Beta 组、构建状态流转等仓库内还有专门的 spaceship/docs/TestFlightTesting.md 可以参考。6.4 处理长期卡在 Processing 的构建当构建在 App Store Connect 端长时间停留在Processing状态时可通过 Connect API 主动轮询取出这些构建Spaceship::ConnectAPI::Build.all(app_id: app.id, processing_states: PROCESSING) # Array of processing builds for this application配合 CI 做上传后等待处理完成再提交审核时这个过滤条件非常实用。七、测试员Testers管理文档明确区分了三类测试员External testers外部测试员通常不属于你的团队最多可邀请 10000 名。向外部测试员分发构建前必须先提交 Beta 审核Internal testers内部测试员注册在 App Store Connect 团队中的员工无需等待审核即可访问所有构建Sandbox testers沙盒测试员用于在开发模式下测试应用内购买或 Apple Pay 的虚拟账号。# Find a tester based on the email address tester Spaceship::TestFlight::Tester.find(app_id: some_app_id, email: felixkrausefx.com) tester Spaceship::ConnectAPI::BetaTester.find(email: felixkrausefx.com) # Creating new testers Spaceship::TestFlight::Tester.create_app_level_tester( app_id: io.myapp, email: githubkrausefx.com, first_name: Felix, last_name: Krause )文档说明当前spaceship 尚不能修改或创建 internal testers。外部测试员既可用旧接口Spaceship::TestFlight::Tester也可用新版Spaceship::ConnectAPI::BetaTester模型见 beta_tester.rb。沙盒测试员的增删走 Connect API示例# Load all sandbox testers testers Spaceship::ConnectAPI::SandboxTester.all # Delete sandbox testers testers.each do |tester| if UI.confirm(Delete #{tester.email}?) tester.delete! end end # Create a sandbox tester Spaceship::ConnectAPI::SandboxTester.create( first_name: Test, # required last_name: Three, # required email: sandboxtest.com, # required password: Passwordtest1, # required. Must contain 8 characters, 1 uppercase, 1 lowercase, 1 numeric. confirm_password: Passwordtest1, # required secret_question: Question, # required. Must contain 6 characters secret_answer: Answer, # required. Must contain 6 characters birth_date: 1980-03-01, # required app_store_territory: USA # required )口令与密保的复杂度约束长度、大小写、数字文档均给出明确要求脚本化创建时应一并校验避免 API 报错。八、评分与评论Ratings Reviews评分评论能力走 Tunes 旧版接口Apple ID 鉴权app Spaceship::Tunes::Application.find(com.krausefx.app) # Get the rating summary for an application ratings app.ratings # Spaceship::Tunes::AppRatings # Get the number of 5 star ratings five_star_count ratings.five_star_rating_count # Find the average rating across all stores average_rating ratings.average_rating # Find the average rating for a given store front average_rating app.ratings(storefront: US).average_rating # Get reviews for a given store front reviews ratings.reviews(US) # Array of hashes representing review data可以通过storefront参数限定地区如US获取某商店前端的平均分与评论数组用于质量监控与舆情分析。九、App Analytics应用分析同样基于 Tunes 接口app.analytics返回Spaceship::Tunes::AppAnalytics默认覆盖最近 7 天可拉取下列全部指标返回值是逐日原始数据的日期数组app Spaceship::Tunes::Application.find(com.krausefx.app) analytics app.analytics # Spaceship::Tunes::AppAnalytics units analytics.app_units # App units下载单位 views analytics.app_views # App Store page views商店页浏览量 impressions analytics.app_impressions # Impressions曝光量 sales analytics.app_sales # App sales销售额 users analytics.paying_users # Paying users付费用户数 iap analytics.app_in_app_purchases # In app purchases内购数据 installs analytics.app_installs # App installs安装量 sessions analytics.app_sessions # App sessions会话数 devices analytics.app_active_devices # Active devices活跃设备数 crashes analytics.app_crashes # Crashes崩溃次数这套接口适合做发布后的数据看板脚本把这些日报数据按天落库即可生成自己的监控报表。十、Bundle Id 管理Auth Key 场景10.1 查询与创建 Bundle Identifier# Fetch all bundle identifiers all_identifiers Spaceship::ConnectAPI::BundleId.all # Find a specific identifier based on the bundle identifier bundle_id Spaceship::ConnectAPI::BundleId.find(com.krausefx.app) # Access information about the bundle identifier bundle_id.name bundle_id.platform bundle_id.identifier bundle_id.seed_id # Create a new identifier identifier Spaceship::ConnectAPI::BundleId.create(name: Description of the identifier, identifier: com.krausefx.app)该能力只走 API Key 鉴权因此标题标注 Auth Key。实现对应 bundle_id.rb。文档标注了一个平台相关的事实无论指定IOS还是MAC_OSplatform都会被设为UNIVERSAL若不指定seed_id默认取 team_id。编写依赖平台判断的脚本时务必留意这一行为。10.2 Bundle Id Capability能力配置# Fetch all capabilities for bundle identifier bundle_id Spaceship::ConnectAPI::BundleId.find(com.krausefx.app) capabilities bundle_id.get_capabilities # Create a new capability for bundle identifier bundle_id.create_capability(Spaceship::ConnectAPI::BundleIdCapability::Type::MAPS) # Create a new capability with known bundle identifier id bundle_id_capability Spaceship::ConnectAPI::BundleIdCapability.create(bundle_id_id: 123456789, capability_type: Spaceship::ConnectAPI::BundleIdCapability::Type::MAPS) # Delete an capability from bundle identifier capabilities.each do |capability| if capability.capability_type Spaceship::ConnectAPI::BundleIdCapability::Type::MAPS capability.delete! end end能力类型以常量枚举形式组织在 capabilities.rb 与 bundle_id_capability.rb 中如Type::MAPS。增删能力支持已知 bundle_id_id 直接创建与通过 BundleId 实例操作两种方式删除时先遍历匹配capability_type再调用delete!。十一、Webhook 管理Auth Key 场景通过 Connect API 可以对单个 App 注册、删除事件通知 Webhookapp Spaceship::ConnectAPI::App.find(com.krausefx.app) # Fetch all webhooks webhooks Spaceship::ConnectAPI::Webhook.all(app_id: app.id) # Create a new webhook new_webhook Spaceship::ConnectAPI::Webhook.create( app_id: app.id, event_types: [ Spaceship::ConnectAPI::Webhook::EventType::APP_STORE_VERSION_APP_VERSION_STATE_UPDATED, ], name: Webhook Name, secret: secret1234, url: https://webhook.example.com ) # Delete a webhook webhooks.first.delete! new_webhook.delete!事件类型EventType常量集中在 webhook.rb上例监听的是App Store 版本状态更新事件。典型的落地场景是提交审核后通过 Webhook 把IN_REVIEW、READY_FOR_SALE、REJECTED等状态变化实时推送到自己的服务替代 CI 里的轮询逻辑。回调 URL 需要支持 App Store Connect 的签名校验secret即用于验证消息来源。十二、许可证与使用边界仓库在文档末尾对 Spaceship 及整个 fastlane 生态作了如下澄清本项目与 fastlane 所有工具均与 Apple Inc. 无任何从属关系项目以 MIT 协议开源你拥有源码的完整访问权并可自行修改以适配需求所有 fastlane 工具运行在你自己的电脑或服务器上因此你的凭证或其他敏感信息永远不会离开你自己的机器——你对自己如何使用 fastlane 工具负责。延伸阅读若要继续深入仓库内的以下文档与源码与本篇主题直接相关可作为下一步阅读材料spaceship/docs/Authentication.md两种登录方式的细节与 2FA 处理spaceship/docs/DeveloperPortal.md开发者门户证书、描述文件侧的 APIspaceship/docs/TestFlightTesting.mdTestFlight 测试的专项指南spaceship/lib/spaceship/connect_api/models本篇涉及的全部 ConnectAPI 模型与属性定义deliver/lib/deliver/submit_for_review.rb把选构建 提交审核做成真实生产流程的完整实现范例deliver/assets/example_rating_config.json年龄分级等提交配置的合法取值示例。【免费下载链接】fastlane The easiest way to automate building and releasing your iOS and Android apps项目地址: https://gitcode.com/GitHub_Trending/fa/fastlane创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价