但使书种多,会有岁稔时。这篇文章主要讲述Fastlane AppStore 执行流程分析相关的知识,希望能为你提供帮助。
文章图片
主要看 spaceship 和deliver 两个模块
spaceship 导出了 Apple Developer Center and the App Store Connect API 据说是 所有你能在浏览器端做的 它都可以做到
而 deliver 模块 则是 负责进行数据的上传和下载,根据 AppStore 上传的流程 跟以下 主要跟一下 deliver 的执行流程
我们在终端执行 fastlane deliver 的时候 fastlane 会根据加载的 Actions 列表里面匹配出 Deliver Action
之前的过程略过不讲 从 Deliver Run 讲起!
文章图片
每个Action 的 commands_generator 中,能够找到匹配的 command, 直接查看它的 run 流程,这里以 deliver 为例 生成命令的过程略过
1、 首先 根据配置项 从 Deliverfile 配置文件中读取配置 加载相关数据
2、如果配置加载失败 就 启动 Runner 登陆后台,拉取远程默认配置 启动Setup 创建默认配置文件
文章图片
这里可以看到 new出来的 Deliver::Runner 干了些啥事情呢 就是登陆 然后 检查数据 DetectValue
文章图片
DetectValue 找到 各个相关主要对象,包括本地配置和远程拉取数据。比如 App, AppID, AppVersion, 检查可用的语言版本等等。总而言之 这一切都是为了构造 option 这个数据结构 为了接下来的操作
文章图片
setup 就是检查 Fastlane 的配置文件系统 根据配置 如果没有就创建默认的
3、配置加载成功了 就启动 Deliver::Runner run 开始上传或者下载
看看 Deliver::Runner 的 run
def run verify_version if options[:app_version].to_s.length > 0 & & !options[:skip_app_version_update] upload_metadatahas_binary = (options[:ipa] || options[:pkg]) if !options[:skip_binary_upload] & & !options[:build_number] & & has_binary upload_binary endUI.success("Finished the upload to App Store Connect") unless options[:skip_binary_upload]reject_version_if_possible if options[:reject_if_possible]precheck_success = precheck_app submit_for_review if options[:submit_for_review] & & precheck_success end
上传metadata 上传二进制 binary 检查app 完了后提交
其中 upload_metadata 方法就是每个事情一个对象,代码很清晰。从本地加载后,开始 upload 。
def upload_metadata upload_metadata = https://www.songbingjia.com/android/UploadMetadata.new upload_screenshots = UploadScreenshots.new# First, collect all the things for the html Report screenshots = upload_screenshots.collect_screenshots(options) upload_metadata.load_from_filesystem(options)# Assign"default" values to all languages upload_metadata.assign_defaults(options)# Handle app icon / watch icon prepare_app_icons(options)# Validate validate_html(screenshots)# Commit upload_metadata.upload(options) upload_screenshots.upload(options, screenshots) UploadPriceTier.new.upload(options) end
着重看一下 UploadMetadata 的 upload 方法
def upload(options) return if options[:skip_metadata] require \'pp\'legacy_app = options[:app] app_id = legacy_app.apple_id app = Spaceship::ConnectAPI::App.get(app_id: app_id)platform = Spaceship::ConnectAPI::Platform.map(options[:platform])app_store_version_localizations = verify_available_languages!(options, app) unless options[:edit_live]if options[:edit_live] # not all values are editable when using live_version version = app.get_ready_for_sale_app_store_version(platform: platform) localised_options = LOCALISED_LIVE_VALUES non_localised_options = NON_LOCALISED_LIVE_VALUESif v.nil? UI.message("Couldn\'t find live version, editing the current version on App Store Connect instead") version = app.get_edit_app_store_version(platform: platform) # we don\'t want to update the localised_options and non_localised_options # as we also check for `options[:edit_live]` at other areas in the code # by not touching those 2 variables, deliver is more consistent with what the option says # in the documentation else UI.message("Found live version") end else version = app.get_edit_app_store_version(platform: platform) localised_options = (LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES) non_localised_options = NON_LOCALISED_VERSION_VALUES.keys category_options = NON_LOCALISED_APP_VALUES endUI.important("Will begin uploading metadata for \'#{version.version_string}\' on App Store Connect")localized_version_attributes_by_locale = {}individual = options[:individual_metadata_items] || [] localised_options.each do |key| current = options[key] next unless currentunless current.kind_of?(Hash) UI.error("Error with provided \'#{key}\'. Must be a hash, the key being the language.") next endcurrent.each do |language, value| next unless value.to_s.length > 0 strip_value = https://www.songbingjia.com/android/value.to_s.stripif LOCALISED_VERSION_VALUES.include?(key) & & !strip_value.empty? attribute_name = LOCALISED_VERSION_VALUES[key]localized_version_attributes_by_locale[language] ||= {} localized_version_attributes_by_locale[language][attribute_name] = strip_value endif LOCALISED_APP_VALUES.include?(key) # puts"LOCALISED_APP_VALUES: NEED TO SEND #{key} #{language}" # puts "\\t#{value}" endend endnon_localized_version_attributes = {} non_localised_options.each do |key| strip_value = https://www.songbingjia.com/android/options[key].to_s.strip next unless strip_value.to_s.length > 0if NON_LOCALISED_VERSION_VALUES.include?(key) & & !strip_value.empty? attribute_name = NON_LOCALISED_VERSION_VALUES[key] non_localized_version_attributes[attribute_name] = strip_value end endrelease_type = if options[:auto_release_date] non_localized_version_attributes[\'earliestReleaseDate\'] = options[:auto_release_date] Spaceship::ConnectAPI::AppStoreVersion::ReleaseType::SCHEDULED elsif options[:automatic_release] Spaceship::ConnectAPI::AppStoreVersion::ReleaseType::AFTER_APPROVAL else Spaceship::ConnectAPI::AppStoreVersion::ReleaseType::MANUAL end non_localized_version_attributes[\'releaseType\'] = release_type# Update app store version localizations app_store_version_localizations.each do |app_store_version_localization| attributes = localized_version_attributes_by_locale[app_store_version_localization.locale] if attributes UI.message("Uploading metadata to App Store Connect for localized version \'#{app_store_version_localization.locale}\'") app_store_version_localization.update(attributes: attributes) end end# Update app store version UI.message("Uploading metadata to App Store Connect for version") version.update(attributes: non_localized_version_attributes)# Update categories app_info = app.get_edit_app_info if app_info app_info.update_categories( primary_category_id: Spaceship::ConnectAPI::AppCategory.map_category_from_itc( options[:primary_category].to_s.strip ), secondary_category_id: Spaceship::ConnectAPI::AppCategory.map_category_from_itc( options[:secondary_category].to_s.strip ), primary_subcategory_one_id: Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc( options[:primary_first_sub_category].to_s.strip ), primary_subcategory_two_id: Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc( options[:primary_second_sub_category].to_s.strip ), secondary_subcategory_one_id: Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc( options[:secondary_first_sub_category].to_s.strip ), secondary_subcategory_two_id: Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc( options[:secondary_second_sub_category].to_s.strip ) ) end# Update phased release unless options[:phased_release].nil? phased_release = version.get_app_store_version_phased_release rescue nil # returns no data error so need to rescue if !!options[:phased_release] unless phased_release UI.message("Creating phased release on App Store Connect") version.create_app_store_version_phased_release(attributes: { phasedReleaseState: Spaceship::ConnectAPI::AppStoreVersionPhasedRelease::PhasedReleaseState::INACTIVE }) end elsif phased_release UI.message("Removing phased release on App Store Connect") phased_release.delete! end end# Update rating reset unless options[:reset_ratings].nil? reset_rating_request = version.get_reset_ratings_request rescue nil # returns no data error so need to rescue if !!options[:reset_ratings] unless reset_rating_request UI.message("Creating reset ratings request on App Store Connect") version.create_reset_ratings_request end elsif reset_rating_request UI.message("Removing reset ratings request on App Store Connect") reset_rating_request.delete! end endset_review_information(version, options) set_review_attachment_file(version, options)# set_app_rating(version, options) end
流程很清晰 针对AppStore 后台的各个模块 做了相应的操作!
前面 ItuneConnect 后台做了较大的改版 fastlane 也做了较大的更新 以前的接口会报 Potential Server Errors
https://github.com/fastlane/fastlane/blob/master/spaceship/docs/DeveloperPortal.md
这个接口文档 基本用不了了
新版 参考这里
Support new App Store Connect APIs【Fastlane AppStore 执行流程分析】https://github.com/fastlane/fastlane/pull/16640
推荐阅读
- uniapp调取摄像头扫码和生成二维码
- uniapp框架uView多平台快速开发的UI框架
- HBuilder打包Wap2App方法
- 解析 pid=`ps -ef | grep $APP_NAME | grep -v grep | awk '{print $2}' `
- uni-app项目开发方式及搭建
- 使用kubectl create 和 kubectl apply创建资源对象的区别
- Scala队列用法示例
- Scala Map用法示例
- Scala ListSet用法示例