fastlane 2.176.0 → 2.180.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +97 -84
  4. data/cert/lib/cert/options.rb +1 -0
  5. data/cert/lib/cert/runner.rb +5 -1
  6. data/deliver/lib/deliver/app_screenshot.rb +6 -2
  7. data/deliver/lib/deliver/download_screenshots.rb +1 -2
  8. data/deliver/lib/deliver/options.rb +1 -0
  9. data/deliver/lib/deliver/runner.rb +11 -3
  10. data/deliver/lib/deliver/setup.rb +0 -1
  11. data/deliver/lib/deliver/upload_metadata.rb +5 -4
  12. data/deliver/lib/deliver/upload_screenshots.rb +10 -10
  13. data/fastlane/lib/fastlane/.fastlane_require.rb.swp +0 -0
  14. data/fastlane/lib/fastlane/actions/.cocoapods.rb.swp +0 -0
  15. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +6 -1
  16. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +8 -5
  17. data/fastlane/lib/fastlane/actions/appaloosa.rb +7 -2
  18. data/fastlane/lib/fastlane/actions/backup_file.rb +1 -1
  19. data/fastlane/lib/fastlane/actions/build_app.rb +4 -0
  20. data/fastlane/lib/fastlane/actions/check_app_store_metadata.rb +4 -0
  21. data/fastlane/lib/fastlane/actions/commit_github_file.rb +11 -1
  22. data/fastlane/lib/fastlane/actions/create_xcframework.rb +5 -0
  23. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +2 -1
  24. data/fastlane/lib/fastlane/actions/get_github_release.rb +11 -1
  25. data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +4 -0
  26. data/fastlane/lib/fastlane/actions/get_version_number.rb +17 -10
  27. data/fastlane/lib/fastlane/actions/git_branch.rb +4 -10
  28. data/fastlane/lib/fastlane/actions/git_tag_exists.rb +4 -0
  29. data/fastlane/lib/fastlane/actions/github_api.rb +2 -1
  30. data/fastlane/lib/fastlane/actions/increment_build_number.rb +8 -1
  31. data/fastlane/lib/fastlane/actions/install_provisioning_profile.rb +4 -0
  32. data/fastlane/lib/fastlane/actions/jira.rb +61 -14
  33. data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +1 -0
  34. data/fastlane/lib/fastlane/actions/match_nuke.rb +59 -0
  35. data/fastlane/lib/fastlane/actions/notarize.rb +98 -51
  36. data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +0 -1
  37. data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
  38. data/fastlane/lib/fastlane/actions/register_devices.rb +1 -1
  39. data/fastlane/lib/fastlane/actions/restore_file.rb +1 -1
  40. data/fastlane/lib/fastlane/actions/set_changelog.rb +1 -1
  41. data/fastlane/lib/fastlane/actions/sourcedocs.rb +164 -0
  42. data/fastlane/lib/fastlane/actions/spaceship_logs.rb +1 -1
  43. data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +1 -2
  44. data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +4 -5
  45. data/fastlane/lib/fastlane/erb_template_helper.rb +7 -1
  46. data/fastlane/lib/fastlane/fast_file.rb +9 -5
  47. data/fastlane/lib/fastlane/fastlane_require.rb +7 -1
  48. data/fastlane/lib/fastlane/helper/git_helper.rb +11 -7
  49. data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +1 -2
  50. data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +1 -2
  51. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +1 -2
  52. data/fastlane/lib/fastlane/setup/setup.rb +23 -10
  53. data/fastlane/lib/fastlane/swift_fastlane_function.rb +4 -0
  54. data/fastlane/lib/fastlane/swift_runner_upgrader.rb +2 -0
  55. data/fastlane/lib/fastlane/version.rb +1 -1
  56. data/fastlane/swift/Deliverfile.swift +1 -1
  57. data/fastlane/swift/DeliverfileProtocol.swift +3 -3
  58. data/fastlane/swift/Fastlane.swift +557 -326
  59. data/fastlane/swift/Gymfile.swift +1 -1
  60. data/fastlane/swift/GymfileProtocol.swift +1 -1
  61. data/fastlane/swift/LaneFileProtocol.swift +9 -3
  62. data/fastlane/swift/Matchfile.swift +1 -1
  63. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  64. data/fastlane/swift/Precheckfile.swift +1 -1
  65. data/fastlane/swift/PrecheckfileProtocol.swift +3 -3
  66. data/fastlane/swift/RubyCommand.swift +1 -1
  67. data/fastlane/swift/Scanfile.swift +1 -1
  68. data/fastlane/swift/ScanfileProtocol.swift +9 -1
  69. data/fastlane/swift/Screengrabfile.swift +1 -1
  70. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  71. data/fastlane/swift/Snapshotfile.swift +1 -1
  72. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  73. data/fastlane/swift/SocketClient.swift +2 -1
  74. data/fastlane/swift/SocketResponse.swift +4 -2
  75. data/fastlane/swift/formatting/Brewfile.lock.json +13 -13
  76. data/fastlane_core/lib/fastlane_core.rb +1 -0
  77. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +5 -3
  78. data/fastlane_core/lib/fastlane_core/helper.rb +24 -1
  79. data/fastlane_core/lib/fastlane_core/ipa_upload_package_builder.rb +3 -2
  80. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +14 -8
  81. data/fastlane_core/lib/fastlane_core/pkg_upload_package_builder.rb +3 -2
  82. data/fastlane_core/lib/fastlane_core/project.rb +3 -14
  83. data/{deliver/lib/deliver → fastlane_core/lib/fastlane_core}/queue_worker.rb +4 -4
  84. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +12 -1
  85. data/fastlane_core/lib/fastlane_core/ui/interface.rb +1 -1
  86. data/gym/lib/gym/generators/.package_command_generator_xcode7.rb.swp +0 -0
  87. data/gym/lib/gym/generators/package_command_generator.rb +4 -0
  88. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +13 -8
  89. data/gym/lib/gym/runner.rb +11 -4
  90. data/match/lib/match/change_password.rb +3 -3
  91. data/match/lib/match/encryption/interface.rb +1 -1
  92. data/match/lib/match/encryption/openssl.rb +2 -2
  93. data/match/lib/match/importer.rb +1 -1
  94. data/match/lib/match/migrate.rb +1 -1
  95. data/match/lib/match/module.rb +1 -0
  96. data/match/lib/match/nuke.rb +1 -1
  97. data/match/lib/match/runner.rb +1 -1
  98. data/match/lib/match/storage/google_cloud_storage.rb +1 -1
  99. data/match/lib/match/storage/s3_storage.rb +1 -1
  100. data/pilot/lib/pilot/build_manager.rb +18 -6
  101. data/pilot/lib/pilot/manager.rb +5 -1
  102. data/pilot/lib/pilot/options.rb +3 -2
  103. data/precheck/lib/precheck/options.rb +1 -0
  104. data/precheck/lib/precheck/runner.rb +5 -1
  105. data/scan/lib/scan/detect_values.rb +4 -1
  106. data/scan/lib/scan/options.rb +15 -5
  107. data/scan/lib/scan/runner.rb +52 -1
  108. data/scan/lib/scan/test_command_generator.rb +8 -8
  109. data/screengrab/lib/screengrab/android_environment.rb +6 -4
  110. data/screengrab/lib/screengrab/runner.rb +1 -1
  111. data/sigh/lib/sigh/download_all.rb +1 -1
  112. data/sigh/lib/sigh/options.rb +1 -0
  113. data/sigh/lib/sigh/runner.rb +5 -1
  114. data/snapshot/lib/assets/SnapshotHelper.swift +1 -1
  115. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +2 -1
  116. data/spaceship/lib/spaceship/client.rb +18 -17
  117. data/spaceship/lib/spaceship/connect_api/api_client.rb +24 -6
  118. data/spaceship/lib/spaceship/connect_api/models/app.rb +1 -1
  119. data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +5 -0
  120. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +1 -1
  121. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +5 -0
  122. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +6 -0
  123. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +5 -0
  124. data/spaceship/lib/spaceship/connect_api/models/build.rb +5 -0
  125. data/spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb +4 -0
  126. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +13 -0
  127. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +13 -0
  128. data/spaceship/lib/spaceship/connect_api/token.rb +8 -2
  129. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +15 -0
  130. metadata +28 -22
  131. data/pilot/lib/pilot/.build_manager.rb.swp +0 -0
@@ -32,6 +32,10 @@ module Precheck
32
32
  UI.message("Creating authorization token for App Store Connect API")
33
33
  Spaceship::ConnectAPI.token = api_token
34
34
  elsif Spaceship::Tunes.client.nil?
35
+ # Username is now optional since addition of App Store Connect API Key
36
+ # Force asking for username to prompt user if not already set
37
+ Precheck.config.fetch(:username, force_ask: true)
38
+
35
39
  # Team selection passed though FASTLANE_ITC_TEAM_ID and FASTLANE_ITC_TEAM_NAME environment variables
36
40
  # Prompts select team if multiple teams and none specified
37
41
  UI.message("Starting login with user '#{Precheck.config[:username]}'")
@@ -72,7 +76,7 @@ module Precheck
72
76
  end
73
77
 
74
78
  def api_token
75
- @api_token ||= Spaceship::ConnectAPI::Token.create(Precheck.config[:api_key]) if Precheck.config[:api_key]
79
+ @api_token ||= Spaceship::ConnectAPI::Token.create(**Precheck.config[:api_key]) if Precheck.config[:api_key]
76
80
  @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(Precheck.config[:api_key_path]) if Precheck.config[:api_key_path]
77
81
  return @api_token
78
82
  end
@@ -162,7 +162,10 @@ module Scan
162
162
  filter_simulators(simulators, :equal, version).tap(&potential_emptiness_error).select(&selector)
163
163
  end
164
164
  ).tap do |array|
165
- UI.error("Ignoring '#{device_string}', couldn’t find matching simulator") if array.empty?
165
+ if array.empty?
166
+ UI.test_failure!("No device found with name '#{device_string}'") if Scan.config[:ensure_devices_found]
167
+ UI.error("Ignoring '#{device_string}', couldn’t find matching simulator")
168
+ end
166
169
  end
167
170
  end
168
171
 
@@ -69,6 +69,11 @@ module Scan
69
69
  default_value: false,
70
70
  type: Boolean,
71
71
  optional: true),
72
+ FastlaneCore::ConfigItem.new(key: :ensure_devices_found,
73
+ description: "Should fail if devices not found",
74
+ default_value: false,
75
+ type: Boolean,
76
+ optional: true),
72
77
 
73
78
  # simulator management
74
79
  FastlaneCore::ConfigItem.new(key: :force_quit_simulator,
@@ -467,11 +472,16 @@ module Scan
467
472
  type: Boolean,
468
473
  default_value: false),
469
474
  FastlaneCore::ConfigItem.new(key: :use_system_scm,
470
- env_name: "SCAN_USE_SYSTEM_SCM",
471
- description: "Lets xcodebuild use system's scm configuration",
472
- optional: true,
473
- type: Boolean,
474
- default_value: false)
475
+ env_name: "SCAN_USE_SYSTEM_SCM",
476
+ description: "Lets xcodebuild use system's scm configuration",
477
+ optional: true,
478
+ type: Boolean,
479
+ default_value: false),
480
+ FastlaneCore::ConfigItem.new(key: :number_of_retries,
481
+ env_name: 'SCAN_NUMBER_OF_RETRIES',
482
+ description: "The number of times a test can fail before scan should stop retrying",
483
+ type: Integer,
484
+ default_value: 0)
475
485
 
476
486
  ]
477
487
  end
@@ -51,7 +51,12 @@ module Scan
51
51
  end
52
52
  end
53
53
 
54
+ execute(retries: Scan.config[:number_of_retries])
55
+ end
56
+
57
+ def execute(retries: 0)
54
58
  command = @test_command_generator.generate
59
+
55
60
  prefix_hash = [
56
61
  {
57
62
  prefix: "Running Tests: ",
@@ -71,7 +76,12 @@ module Scan
71
76
  error: proc do |error_output|
72
77
  begin
73
78
  exit_status = $?.exitstatus
74
- ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
79
+ if retries > 0
80
+ # If there are retries remaining, run the tests again
81
+ return retry_execute(retries: retries, error_output: error_output)
82
+ else
83
+ ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
84
+ end
75
85
  rescue => ex
76
86
  SlackPoster.new.run({
77
87
  build_errors: 1
@@ -79,9 +89,50 @@ module Scan
79
89
  raise ex
80
90
  end
81
91
  end)
92
+
82
93
  exit_status
83
94
  end
84
95
 
96
+ def retry_execute(retries:, error_output: "")
97
+ tests = retryable_tests(error_output)
98
+
99
+ if tests.empty?
100
+ UI.crash!("Failed to find failed tests to retry (could not parse error output)")
101
+ end
102
+
103
+ Scan.config[:only_testing] = tests
104
+ UI.important("Retrying tests: #{Scan.config[:only_testing].join(', ')}")
105
+
106
+ retries -= 1
107
+ UI.important("Number of retries remaining: #{retries}")
108
+
109
+ return execute(retries: retries)
110
+ end
111
+
112
+ def retryable_tests(input)
113
+ input = Helper.strip_ansi_colors(input)
114
+
115
+ retryable_tests = []
116
+
117
+ failing_tests = input.split("Failing tests:\n").fetch(1, [])
118
+ .split("\n\n").first
119
+
120
+ suites = failing_tests.split(/(?=\n\s+[\w\s]+:\n)/)
121
+
122
+ suites.each do |suite|
123
+ suite_name = suite.match(/\s*([\w\s]+):/).captures.first
124
+
125
+ test_cases = suite.split(":\n").fetch(1, []).split("\n").each
126
+ .select { |line| line.match?(/^\s+/) }
127
+ .map { |line| line.strip.gsub(".", "/").gsub("()", "") }
128
+ .map { |line| suite_name + "/" + line }
129
+
130
+ retryable_tests += test_cases
131
+ end
132
+
133
+ return retryable_tests.uniq
134
+ end
135
+
85
136
  def handle_results(tests_exit_status)
86
137
  if Scan.config[:disable_xcpretty]
87
138
  unless tests_exit_status == 0
@@ -162,16 +162,16 @@ module Scan
162
162
  Scan.cache[:build_path]
163
163
  end
164
164
 
165
+ # The path to the result bundle
165
166
  def result_bundle_path
166
- unless Scan.cache[:result_bundle_path]
167
- ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
168
- path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + ext
169
- if File.directory?(path)
170
- FileUtils.remove_dir(path)
171
- end
172
- Scan.cache[:result_bundle_path] = path
167
+ ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
168
+ path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + ext
169
+ if File.directory?(path)
170
+ FileUtils.remove_dir(path)
173
171
  end
174
- return Scan.cache[:result_bundle_path]
172
+ Scan.cache[:result_bundle_path] = path
173
+
174
+ return path
175
175
  end
176
176
  end
177
177
  end
@@ -34,22 +34,22 @@ module Screengrab
34
34
  def find_platform_tools(android_home)
35
35
  return nil unless android_home
36
36
 
37
- platform_tools_path = File.join(android_home, 'platform-tools')
37
+ platform_tools_path = Helper.localize_file_path(File.join(android_home, 'platform-tools'))
38
38
  File.directory?(platform_tools_path) ? platform_tools_path : nil
39
39
  end
40
40
 
41
41
  def find_build_tools(android_home, build_tools_version)
42
42
  return nil unless android_home
43
43
 
44
- build_tools_dir = File.join(android_home, 'build-tools')
44
+ build_tools_dir = Helper.localize_file_path(File.join(android_home, 'build-tools'))
45
45
 
46
46
  return nil unless build_tools_dir && File.directory?(build_tools_dir)
47
47
 
48
- return File.join(build_tools_dir, build_tools_version) if build_tools_version
48
+ return Helper.localize_file_path(File.join(build_tools_dir, build_tools_version)) if build_tools_version
49
49
 
50
50
  version = select_build_tools_version(build_tools_dir)
51
51
 
52
- return version ? File.join(build_tools_dir, version) : nil
52
+ return version ? Helper.localize_file_path(File.join(build_tools_dir, version)) : nil
53
53
  end
54
54
 
55
55
  def select_build_tools_version(build_tools_dir)
@@ -74,6 +74,7 @@ module Screengrab
74
74
  return FastlaneCore::CommandExecutor.which('adb') unless platform_tools_path
75
75
 
76
76
  adb_path = Helper.get_executable_path(File.join(platform_tools_path, 'adb'))
77
+ adb_path = Helper.localize_file_path(adb_path)
77
78
  return executable_command?(adb_path) ? adb_path : nil
78
79
  end
79
80
 
@@ -81,6 +82,7 @@ module Screengrab
81
82
  return FastlaneCore::CommandExecutor.which('aapt') unless build_tools_path
82
83
 
83
84
  aapt_path = Helper.get_executable_path(File.join(build_tools_path, 'aapt'))
85
+ aapt_path = Helper.localize_file_path(aapt_path)
84
86
  return executable_command?(aapt_path) ? aapt_path : nil
85
87
  end
86
88
 
@@ -308,7 +308,7 @@ module Screengrab
308
308
  if out =~ /Permission denied/
309
309
  dir = File.dirname(path)
310
310
  base = File.basename(path)
311
- run_adb_command("-s #{device_serial} shell run-as #{@config[:app_package_name]} 'tar -cC #{dir} #{base}' | tar -xvC #{tempdir}",
311
+ run_adb_command("-s #{device_serial} shell run-as #{@config[:app_package_name]} \"tar -cC #{dir} #{base}\" | tar -xv -f- -C #{tempdir}",
312
312
  print_all: false,
313
313
  print_command: true)
314
314
  end
@@ -60,7 +60,7 @@ module Sigh
60
60
  end
61
61
 
62
62
  def api_token
63
- api_token ||= Spaceship::ConnectAPI::Token.create(Sigh.config[:api_key]) if Sigh.config[:api_key]
63
+ api_token ||= Spaceship::ConnectAPI::Token.create(**Sigh.config[:api_key]) if Sigh.config[:api_key]
64
64
  api_token ||= Spaceship::ConnectAPI::Token.from_json_file(Sigh.config[:api_key_path]) if Sigh.config[:api_key_path]
65
65
  return api_token
66
66
  end
@@ -77,6 +77,7 @@ module Sigh
77
77
  short_option: "-u",
78
78
  env_name: "SIGH_USERNAME",
79
79
  description: "Your Apple ID Username",
80
+ optional: true,
80
81
  default_value: user,
81
82
  default_value_dynamic: true),
82
83
  FastlaneCore::ConfigItem.new(key: :team_id,
@@ -21,6 +21,10 @@ module Sigh
21
21
  UI.message("Creating authorization token for App Store Connect API")
22
22
  Spaceship::ConnectAPI.token = api_token
23
23
  else
24
+ # Username is now optional since addition of App Store Connect API Key
25
+ # Force asking for username to prompt user if not already set
26
+ Sigh.config.fetch(:username, force_ask: true)
27
+
24
28
  # Team selection passed though FASTLANE_ITC_TEAM_ID and FASTLANE_ITC_TEAM_NAME environment variables
25
29
  # Prompts select team if multiple teams and none specified
26
30
  UI.message("Starting login with user '#{Sigh.config[:username]}'")
@@ -60,7 +64,7 @@ module Sigh
60
64
  end
61
65
 
62
66
  def api_token
63
- @api_token ||= Spaceship::ConnectAPI::Token.create(Sigh.config[:api_key]) if Sigh.config[:api_key]
67
+ @api_token ||= Spaceship::ConnectAPI::Token.create(**Sigh.config[:api_key]) if Sigh.config[:api_key]
64
68
  @api_token ||= Spaceship::ConnectAPI::Token.from_json_file(Sigh.config[:api_key_path]) if Sigh.config[:api_key_path]
65
69
  return @api_token
66
70
  end
@@ -302,4 +302,4 @@ private extension CGFloat {
302
302
 
303
303
  // Please don't remove the lines below
304
304
  // They are used to detect outdated configuration files
305
- // SnapshotHelperVersion [1.24]
305
+ // SnapshotHelperVersion [1.25]
@@ -69,7 +69,8 @@ module Snapshot
69
69
  unless launcher_config.dark_mode.nil?
70
70
  interface_style(type, launcher_config.dark_mode)
71
71
  end
72
- elsif launcher_config.reinstall_app
72
+ end
73
+ if launcher_config.reinstall_app && !launcher_config.erase_simulator
73
74
  # no need to reinstall if device has been erased
74
75
  uninstall_app(type)
75
76
  end
@@ -134,7 +134,7 @@ module Spaceship
134
134
  if teams.count > 1
135
135
  puts("The current user is in #{teams.count} teams. Pass a team ID or call `select_team` to choose a team. Using the first one for now.")
136
136
  end
137
- @current_team_id ||= teams[0]['contentProvider']['contentProviderId']
137
+ @current_team_id ||= user_details_data['sessionToken']['contentProviderId']
138
138
  end
139
139
 
140
140
  # Set a new team ID which will be used from now on
@@ -171,6 +171,9 @@ module Spaceship
171
171
 
172
172
  handle_itc_response(response.body)
173
173
 
174
+ # clear user_details_data cache, as session switch will have changed sessionToken attribute
175
+ @_cached_user_details = nil
176
+
174
177
  @current_team_id = team_id
175
178
  end
176
179
 
@@ -880,10 +883,7 @@ module Spaceship
880
883
  response = @client.send(method, url_or_path, params, headers, &block)
881
884
  log_response(method, url_or_path, response, headers, &block)
882
885
 
883
- resp_hash = response.to_hash
884
- if resp_hash[:status] == 401
885
- handle_401(response)
886
- end
886
+ handle_error(response)
887
887
 
888
888
  if response.body.to_s.include?("<title>302 Found</title>")
889
889
  raise AppleTimeoutError.new, "Apple 302 detected - this might be temporary server error, check https://developer.apple.com/system-status/ to see if there is a known downtime"
@@ -893,22 +893,23 @@ module Spaceship
893
893
  raise BadGatewayError.new, "Apple 502 detected - this might be temporary server error, try again later"
894
894
  end
895
895
 
896
- if resp_hash[:status] == 403
897
- msg = "Access forbidden"
898
- logger.warn(msg)
899
- raise AccessForbiddenError.new, msg
900
- elsif resp_hash[:status] == 429
901
- raise TooManyRequestsError, resp_hash
902
- end
903
-
904
896
  return response
905
897
  end
906
898
  end
907
899
 
908
- def handle_401(response)
909
- msg = "Auth lost"
910
- logger.warn(msg)
911
- raise UnauthorizedAccessError.new, "Unauthorized Access"
900
+ def handle_error(response)
901
+ case response.status
902
+ when 401
903
+ msg = "Auth lost"
904
+ logger.warn(msg)
905
+ raise UnauthorizedAccessError.new, "Unauthorized Access"
906
+ when 403
907
+ msg = "Access forbidden"
908
+ logger.warn(msg)
909
+ raise AccessForbiddenError.new, msg
910
+ when 429
911
+ raise TooManyRequestsError, response.to_hash
912
+ end
912
913
  end
913
914
 
914
915
  def send_request_auto_paginate(method, url_or_path, params, headers, &block)
@@ -150,6 +150,12 @@ module Spaceship
150
150
 
151
151
  protected
152
152
 
153
+ class TimeoutRetryError < StandardError
154
+ def initialize(msg)
155
+ super
156
+ end
157
+ end
158
+
153
159
  def with_asc_retry(tries = 5, &_block)
154
160
  tries = 1 if Object.const_defined?("SpecHelper")
155
161
 
@@ -159,7 +165,7 @@ module Spaceship
159
165
 
160
166
  if [500, 504].include?(status)
161
167
  msg = "Timeout received! Retrying after 3 seconds (remaining: #{tries})..."
162
- raise msg
168
+ raise TimeoutRetryError, msg
163
169
  end
164
170
 
165
171
  return response
@@ -167,7 +173,7 @@ module Spaceship
167
173
  # Catch unathorized access and re-raising
168
174
  # There is no need to try again
169
175
  raise error
170
- rescue => error
176
+ rescue TimeoutRetryError => error
171
177
  tries -= 1
172
178
  puts(error) if Spaceship::Globals.verbose?
173
179
  if tries.zero?
@@ -190,7 +196,7 @@ module Spaceship
190
196
 
191
197
  raise UnexpectedResponse, response.body['error'] if response.body['error']
192
198
 
193
- raise UnexpectedResponse, handle_errors(response) if response.body['errors']
199
+ raise UnexpectedResponse, format_errors(response) if response.body['errors']
194
200
 
195
201
  raise UnexpectedResponse, "Temporary App Store Connect error: #{response.body}" if response.body['statusCode'] == 'ERROR'
196
202
 
@@ -199,11 +205,23 @@ module Spaceship
199
205
  return Spaceship::ConnectAPI::Response.new(body: response.body, status: response.status, headers: response.headers, client: self)
200
206
  end
201
207
 
202
- def handle_401(response)
203
- raise UnauthorizedAccessError, handle_errors(response) if response && (response.body || {})['errors']
208
+ # Overridden from Spaceship::Client
209
+ def handle_error(response)
210
+ case response.status.to_i
211
+ when 401
212
+ raise UnauthorizedAccessError, format_errors(response) if response && (response.body || {})['errors']
213
+ when 403
214
+ error = (response.body['errors'] || []).first || {}
215
+ error_code = error['code']
216
+ if error_code == "FORBIDDEN.REQUIRED_AGREEMENTS_MISSING_OR_EXPIRED"
217
+ raise ProgramLicenseAgreementUpdated, format_errors(response) if response && (response.body || {})['errors']
218
+ else
219
+ raise AccessForbiddenError, format_errors(response) if response && (response.body || {})['errors']
220
+ end
221
+ end
204
222
  end
205
223
 
206
- def handle_errors(response)
224
+ def format_errors(response)
207
225
  # Example error format
208
226
  # {
209
227
  # "errors":[
@@ -203,7 +203,7 @@ module Spaceship
203
203
  # @return (Bool) Was something changed?
204
204
  def ensure_version!(version_string, platform: nil, client: nil)
205
205
  client ||= Spaceship::ConnectAPI
206
- app_store_version = get_edit_app_store_version(platform: platform)
206
+ app_store_version = get_edit_app_store_version(client: client, platform: platform)
207
207
 
208
208
  if app_store_version
209
209
  if version_string != app_store_version.version_string
@@ -69,6 +69,11 @@ module Spaceship
69
69
  return client.get_app_preview_set(app_preview_set_id: app_preview_set_id, filter: nil, includes: includes, limit: nil, sort: nil).first
70
70
  end
71
71
 
72
+ def delete!(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
73
+ client ||= Spaceship::ConnectAPI
74
+ return client.delete_app_preview_set(app_preview_set_id: id)
75
+ end
76
+
72
77
  def upload_preview(client: nil, path: nil, wait_for_processing: true, position: nil, frame_time_code: nil)
73
78
  client ||= Spaceship::ConnectAPI
74
79
  # Upload preview
@@ -112,7 +112,7 @@ module Spaceship
112
112
  timeout_minutes = (ENV["SPACESHIP_SCREENSHOT_UPLOAD_TIMEOUT"] || 20).to_i
113
113
 
114
114
  loop do
115
- # This error handling needs to be revised since any error occured can reach here.
115
+ # This error handling needs to be revised since any error occurred can reach here.
116
116
  # It should handle errors based on what status code is.
117
117
  puts("Waiting for screenshots to appear before uploading. This is unlikely to be recovered unless it's 503 error. error=\"#{error}\"")
118
118
  sleep(30)