deliver/lib/deliver/submit_for_review.rb in fastlane-2.149.1 vs deliver/lib/deliver/submit_for_review.rb in fastlane-2.150.0.rc1

- old
+ new

@@ -1,132 +1,169 @@ require_relative 'module' +require 'fastlane_core/build_watcher' +require 'fastlane_core/ipa_file_analyser' +require 'fastlane_core/pkg_file_analyser' + module Deliver class SubmitForReview def submit!(options) - app = options[:app] - select_build(options) + legacy_app = options[:app] + app_id = legacy_app.apple_id + app = Spaceship::ConnectAPI::App.get(app_id: app_id) - UI.message("Submitting the app for review...") - submission = app.create_submission(platform: options[:platform]) + platform = Spaceship::ConnectAPI::Platform.map(options[:platform]) + version = app.get_edit_app_store_version(platform: platform) - # Set app submission information - # Default Values - submission.content_rights_contains_third_party_content = false - submission.content_rights_has_rights = true - submission.add_id_info_uses_idfa = false - - # User Values - if options[:submission_information] - options[:submission_information].each do |key, value| - UI.message("Setting '#{key}' to '#{value}'...") - submission.send("#{key}=", value) - end + unless version + UI.user_error!("Cannot submit for review - could not find an editable version for '#{platform}'") + return end - # Finalize app submission - submission.complete! + build = select_build(options, app, version, platform) + update_export_compliance(options, app, build) + update_idfa(options, app, version) + update_submission_information(options, app) + + version.create_app_store_version_submission + UI.success("Successfully submitted the app for review!") end - private def select_build(options) - app = options[:app] - app_version = options[:app_version] - v = app.edit_version(platform: options[:platform]) - + private def select_build(options, app, version, platform) if options[:build_number] && options[:build_number] != "latest" UI.message("Selecting existing build-number: #{options[:build_number]}") - if app_version - build = v.candidate_builds.detect { |a| a.build_version == options[:build_number] && a.train_version == app_version } - else - build = v.candidate_builds.detect { |a| a.build_version == options[:build_number] } - end + + build = Spaceship::ConnectAPI::Build.all( + app_id: app.id, + version: options[:app_version], + build_number: options[:build_number], + platform: platform + ).first + unless build UI.user_error!("Build number: #{options[:build_number]} does not exist") end else UI.message("Selecting the latest build...") - build = wait_for_build(app, app_version) + build = wait_for_build_processing_to_be_complete(app: app, platform: platform, options: options) end - UI.message("Selecting build #{app_version} (#{build.build_version})...") + UI.message("Selecting build #{build.app_version} (#{build.version})...") - v.select_build(build) - v.save! + version.select_build(build_id: build.id) UI.success("Successfully selected build") + + return build end - def wait_for_build(app, app_version) - UI.user_error!("Could not find app with app identifier") unless app + def update_export_compliance(options, app, build) + submission_information = options[:submission_information] || {} + uses_encryption = submission_information[:export_compliance_uses_encryption] - start = Time.now - build = nil + UI.verbose("Updating build for export compliance status of '#{uses_encryption}'") + if build.uses_non_exempt_encryption.nil? + build = build.update(attributes: { + usesNonExemptEncryption: uses_encryption + }) + end + UI.verbose("Updated build for export compliance status of '#{build.uses_non_exempt_encryption}'") + end - use_latest_version = app_version.nil? + def update_idfa(options, app, version) + submission_information = options[:submission_information] || {} + return unless submission_information.include?(:add_id_info_uses_idfa) - loop do - # Sometimes candidate_builds don't appear immediately after submission - # Wait for candidate_builds to appear on App Store Connect - # Issue https://github.com/fastlane/fastlane/issues/10411 - if use_latest_version - candidate_builds = app.latest_version.candidate_builds - else - candidate_builds = app.tunes_all_builds_for_train(train: app_version) + uses_idfa = submission_information[:add_id_info_uses_idfa] + idfa_declaration = begin + version.fetch_idfa_declaration + rescue + nil + end + + UI.verbose("Updating app store version for IDFA status of '#{uses_idfa}'") + version = version.update(attributes: { + usesIdfa: uses_idfa + }) + UI.verbose("Updated app store version for IDFA status of '#{version.uses_idfa}'") + + if uses_idfa == false + if idfa_declaration + UI.verbose("Deleting IDFA delcaration") + idfa_declaration.delete! + UI.verbose("Deleted IDFA delcaration") end - if (candidate_builds || []).count == 0 - UI.message("Waiting for candidate builds to appear...") - if (Time.now - start) > (60 * 5) - UI.user_error!("Could not find any available candidate builds on App Store Connect to submit") - else - sleep(30) - next - end + else + attributes = {} + if submission_information.include?(:add_id_info_limits_tracking) + attributes[:honorsLimitedAdTracking] = submission_information[:add_id_info_limits_tracking] end - latest_build = find_build(candidate_builds) + if submission_information.include?(:add_id_info_serves_ads) + attributes[:servesAds] = submission_information[:add_id_info_serves_ads] + end - # if the app version isn't present in the hash (could happen if we are waiting for submission, but didn't provide - # it explicitly and no ipa was passed to grab it from), then fall back to the best guess, which is the train_version - # of the most recently uploaded build - app_version ||= latest_build.train_version + if submission_information.include?(:add_id_info_tracks_install) + attributes[:attributesAppInstallationToPreviousAd] = submission_information[:add_id_info_tracks_install] + end - # Sometimes latest build will disappear and a different build would get selected - # Only set build if no latest build found or if same build versions as previously fetched build - # Issue: https://github.com/fastlane/fastlane/issues/10945 - if build.nil? || (latest_build && latest_build.build_version == build.build_version && latest_build.train_version == app_version) - build = latest_build + if submission_information.include?(:add_id_info_tracks_action) + attributes[:attributesActionWithPreviousAd] = submission_information[:add_id_info_tracks_action] end - return build if build && build.processing == false - - if build - UI.message("Waiting App Store Connect processing for build #{app_version} (#{build.build_version})... this might take a while...") + if idfa_declaration + UI.verbose("Updating IDFA delcaration") + idfa_declaration.update(attributes: attributes) + UI.verbose("Updated IDFA delcaration") else - UI.message("Waiting App Store Connect processing for build... this might take a while...") + UI.verbose("Creating IDFA delcaration") + version.create_idfa_declaration(attributes: attributes) + UI.verbose("Created IDFA delcaration") end - - if (Time.now - start) > (60 * 5) - UI.message("") - UI.message("You can tweet: \"App Store Connect #iosprocessingtime #{((Time.now - start) / 60).round} minutes\"") - end - sleep(30) end - nil + + UI.success("Successfully updated IDFA delcarations") end - def find_build(candidate_builds) - if (candidate_builds || []).count == 0 - UI.user_error!("Could not find any available candidate builds on App Store Connect to submit") + def update_submission_information(options, app) + submission_information = options[:submission_information] || {} + if submission_information.include?(:content_rights_contains_third_party_content) + value = if submission_information[:content_rights_contains_third_party_content] + Spaceship::ConnectAPI::App::ContentRightsDeclaration::USES_THIRD_PARTY_CONTENT + else + Spaceship::ConnectAPI::App::ContentRightsDeclaration::DOES_NOT_USE_THIRD_PARTY_CONTENT + end + + UI.success("Updating contents rights declaration on App Store Connect") + app.update(attributes: { + contentRightsDeclaration: value + }) end + end - build = candidate_builds.first - candidate_builds.each do |b| - if b.upload_date > build.upload_date - build = b - end + def wait_for_build_processing_to_be_complete(app: nil, platform: nil, options: nil) + app_version = options[:app_version] + app_version ||= FastlaneCore::IpaFileAnalyser.fetch_app_version(options[:ipa]) if options[:ipa] + app_version ||= FastlaneCore::PkgFileAnalyser.fetch_app_version(options[:pkg]) if options[:pkg] + + app_build ||= FastlaneCore::IpaFileAnalyser.fetch_app_build(options[:ipa]) if options[:ipa] + app_build ||= FastlaneCore::PkgFileAnalyser.fetch_app_build(options[:pkg]) if options[:pkg] + + latest_build = FastlaneCore::BuildWatcher.wait_for_build_processing_to_be_complete( + app_id: app.id, + platform: platform, + app_version: app_version, + build_version: app_build, + poll_interval: 15, + return_when_build_appears: false, + return_spaceship_testflight_build: false + ) + + unless latest_build.app_version == app_version && latest_build.version == app_build + UI.important("Uploaded app #{app_version} - #{app_build}, but received build #{latest_build.app_version} - #{latest_build.version}.") end - return build + return latest_build end end end