fastlane 2.198.0 → 2.201.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +88 -88
  4. data/deliver/lib/deliver/app_screenshot.rb +8 -0
  5. data/deliver/lib/deliver/app_screenshot_iterator.rb +1 -1
  6. data/fastlane/lib/.DS_Store +0 -0
  7. data/fastlane/lib/fastlane/.DS_Store +0 -0
  8. data/fastlane/lib/fastlane/actions/.DS_Store +0 -0
  9. data/fastlane/lib/fastlane/actions/download_dsyms.rb +26 -27
  10. data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +1 -1
  11. data/fastlane/lib/fastlane/actions/get_version_number.rb +1 -0
  12. data/fastlane/lib/fastlane/actions/trainer.rb +49 -0
  13. data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +18 -1
  14. data/fastlane/lib/fastlane/actions/xcversion.rb +18 -3
  15. data/fastlane/lib/fastlane/documentation/docs_generator.rb +17 -12
  16. data/fastlane/lib/fastlane/helper/xcodebuild_formatter_helper.rb +9 -0
  17. data/fastlane/lib/fastlane/tools.rb +2 -1
  18. data/fastlane/lib/fastlane/version.rb +1 -1
  19. data/fastlane/swift/Actions.swift +1 -1
  20. data/fastlane/swift/Appfile.swift +1 -1
  21. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  22. data/fastlane/swift/ControlCommand.swift +1 -1
  23. data/fastlane/swift/Deliverfile.swift +2 -2
  24. data/fastlane/swift/DeliverfileProtocol.swift +2 -2
  25. data/fastlane/swift/Fastlane.swift +44 -15
  26. data/fastlane/swift/Gymfile.swift +2 -2
  27. data/fastlane/swift/GymfileProtocol.swift +6 -2
  28. data/fastlane/swift/LaneFileProtocol.swift +1 -1
  29. data/fastlane/swift/MainProcess.swift +1 -1
  30. data/fastlane/swift/Matchfile.swift +2 -2
  31. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  32. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  33. data/fastlane/swift/Plugins.swift +1 -1
  34. data/fastlane/swift/Precheckfile.swift +2 -2
  35. data/fastlane/swift/PrecheckfileProtocol.swift +2 -2
  36. data/fastlane/swift/RubyCommand.swift +1 -1
  37. data/fastlane/swift/RubyCommandable.swift +1 -1
  38. data/fastlane/swift/Runner.swift +4 -8
  39. data/fastlane/swift/RunnerArgument.swift +1 -1
  40. data/fastlane/swift/Scanfile.swift +2 -2
  41. data/fastlane/swift/ScanfileProtocol.swift +4 -4
  42. data/fastlane/swift/Screengrabfile.swift +2 -2
  43. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  44. data/fastlane/swift/Snapshotfile.swift +2 -2
  45. data/fastlane/swift/SnapshotfileProtocol.swift +2 -2
  46. data/fastlane/swift/SocketClient.swift +1 -1
  47. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  48. data/fastlane/swift/SocketResponse.swift +1 -1
  49. data/fastlane/swift/formatting/Brewfile.lock.json +14 -14
  50. data/fastlane/swift/main.swift +1 -1
  51. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +10 -5
  52. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +15 -5
  53. data/gym/lib/gym/generators/build_command_generator.rb +69 -23
  54. data/gym/lib/gym/options.rb +23 -5
  55. data/scan/lib/scan/options.rb +27 -7
  56. data/scan/lib/scan/runner.rb +58 -15
  57. data/scan/lib/scan/test_command_generator.rb +54 -5
  58. data/snapshot/lib/snapshot/options.rb +23 -7
  59. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +1 -1
  60. data/snapshot/lib/snapshot/test_command_generator.rb +37 -2
  61. data/spaceship/lib/spaceship/client.rb +35 -15
  62. data/spaceship/lib/spaceship/commands_generator.rb +1 -1
  63. data/spaceship/lib/spaceship/connect_api/models/app.rb +43 -0
  64. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +1 -0
  65. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +2 -0
  66. data/spaceship/lib/spaceship/connect_api/models/review_submission.rb +73 -0
  67. data/spaceship/lib/spaceship/connect_api/models/review_submission_item.rb +40 -0
  68. data/spaceship/lib/spaceship/connect_api/response.rb +13 -0
  69. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +83 -0
  70. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  71. data/spaceship/lib/spaceship/globals.rb +9 -0
  72. data/spaceship/lib/spaceship/spaceauth_runner.rb +1 -1
  73. data/supply/lib/supply/options.rb +8 -0
  74. data/supply/lib/supply/uploader.rb +6 -2
  75. data/trainer/lib/.DS_Store +0 -0
  76. data/trainer/lib/assets/junit.xml.erb +20 -0
  77. data/trainer/lib/trainer/commands_generator.rb +51 -0
  78. data/trainer/lib/trainer/junit_generator.rb +31 -0
  79. data/trainer/lib/trainer/module.rb +10 -0
  80. data/trainer/lib/trainer/options.rb +55 -0
  81. data/trainer/lib/trainer/test_parser.rb +335 -0
  82. data/trainer/lib/trainer/xcresult.rb +403 -0
  83. data/trainer/lib/trainer.rb +7 -0
  84. metadata +38 -21
@@ -53,7 +53,7 @@ module Scan
53
53
  if config[:use_system_scm] && !options.include?("-scmProvider system")
54
54
  options << "-scmProvider system"
55
55
  end
56
- options << "-resultBundlePath '#{result_bundle_path}'" if config[:result_bundle]
56
+ options << "-resultBundlePath '#{result_bundle_path(config[:result_bundle])}'"
57
57
  if FastlaneCore::Helper.xcode_at_least?(10)
58
58
  options << "-parallel-testing-worker-count #{config[:concurrent_workers]}" if config[:concurrent_workers]
59
59
  options << "-maximum-concurrent-test-simulator-destinations #{config[:max_concurrent_simulators]}" if config[:max_concurrent_simulators]
@@ -72,6 +72,10 @@ module Scan
72
72
  end
73
73
  options << "-xctestrun '#{config[:xctestrun]}'" if config[:xctestrun]
74
74
  options << config[:xcargs] if config[:xcargs]
75
+ if config[:number_of_retries] >= 1 && FastlaneCore::Helper.xcode_at_least?(13)
76
+ options << "-retry-tests-on-failure"
77
+ options << "-test-iterations #{config[:number_of_retries]}"
78
+ end
75
79
 
76
80
  # detect_values will ensure that these values are present as Arrays if
77
81
  # they are present at all
@@ -107,12 +111,55 @@ module Scan
107
111
  def pipe
108
112
  pipe = ["| tee '#{xcodebuild_log_path}'"]
109
113
 
114
+ # disable_xcpretty is now deprecated and directs to use output_style of raw
110
115
  if Scan.config[:disable_xcpretty] || Scan.config[:output_style] == 'raw'
111
116
  return pipe
112
117
  end
113
118
 
119
+ formatter = Scan.config[:xcodebuild_formatter].chomp
120
+ options = legacy_xcpretty_options
121
+
122
+ if !options.empty?
123
+ UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
124
+ UI.important("Option(s) used: #{options.join(', ')}")
125
+ pipe << pipe_xcpretty
126
+ elsif formatter == 'xcpretty'
127
+ pipe << pipe_xcpretty
128
+ elsif formatter == 'xcbeautify'
129
+ pipe << pipe_xcbeautify
130
+ else
131
+ pipe << "| #{formatter}"
132
+ end
133
+
134
+ return pipe
135
+ end
136
+
137
+ def pipe_xcbeautify
138
+ formatter = ['| xcbeautify']
139
+
140
+ if FastlaneCore::Helper.colors_disabled?
141
+ formatter << '--disable-colored-output'
142
+ end
143
+
144
+ return formatter.join(' ')
145
+ end
146
+
147
+ def legacy_xcpretty_options
148
+ options = []
149
+
150
+ options << "formatter" if Scan.config[:formatter]
151
+ options << "xcpretty_formatter" if Scan.config[:xcpretty_formatter]
152
+ options << "output_style" if Scan.config[:output_style]
153
+ options << "output_files" if Scan.config[:output_files]
154
+ options << "output_types" if (Scan.config[:output_types] || "").include?("json-compilation-database")
155
+ options << "custom_report_file_name" if Scan.config[:custom_report_file_name]
156
+
157
+ return options
158
+ end
159
+
160
+ def pipe_xcpretty
114
161
  formatter = []
115
- if (custom_formatter = Scan.config[:formatter])
162
+ if (custom_formatter = Scan.config[:xcpretty_formatter] || Scan.config[:formatter])
116
163
  if custom_formatter.end_with?(".rb")
117
164
  formatter << "-f '#{custom_formatter}'"
118
165
  else
@@ -143,7 +190,7 @@ module Scan
143
190
  Scan.config[:xcpretty_args])
144
191
  reporter_options = @reporter_options_generator.generate_reporter_options
145
192
  reporter_xcpretty_args = @reporter_options_generator.generate_xcpretty_args_options
146
- return pipe << "| xcpretty #{formatter.join(' ')} #{reporter_options.join(' ')} #{reporter_xcpretty_args}"
193
+ return "| xcpretty #{formatter.join(' ')} #{reporter_options.join(' ')} #{reporter_xcpretty_args}"
147
194
  end
148
195
 
149
196
  # Store the raw file
@@ -183,11 +230,13 @@ module Scan
183
230
  end
184
231
 
185
232
  # The path to the result bundle
186
- def result_bundle_path
233
+ def result_bundle_path(use_output_directory)
234
+ root_dir = use_output_directory ? Scan.config[:output_directory] : Dir.mktmpdir
235
+
187
236
  retry_count = Scan.cache[:retry_attempt] || 0
188
237
  attempt = retry_count > 0 ? "-#{retry_count}" : ""
189
238
  ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
190
- path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + attempt + ext
239
+ path = File.join([root_dir, Scan.config[:scheme]].compact) + attempt + ext
191
240
 
192
241
  Scan.cache[:result_bundle_path] = path
193
242
 
@@ -1,5 +1,6 @@
1
1
  require 'fastlane_core/configuration/config_item'
2
2
  require 'fastlane_core/device_manager'
3
+ require 'fastlane/helper/xcodebuild_formatter_helper'
3
4
  require 'credentials_manager/appfile_config'
4
5
  require_relative 'module'
5
6
 
@@ -11,9 +12,13 @@ module Snapshot
11
12
  end
12
13
 
13
14
  def self.available_options
15
+ @options ||= plain_options
16
+ end
17
+
18
+ def self.plain_options
14
19
  output_directory = (File.directory?("fastlane") ? "fastlane/screenshots" : "screenshots")
15
20
 
16
- @options ||= [
21
+ [
17
22
  FastlaneCore::ConfigItem.new(key: :workspace,
18
23
  short_option: "-w",
19
24
  env_name: "SNAPSHOT_WORKSPACE",
@@ -194,12 +199,6 @@ module Snapshot
194
199
  description: "The configuration to use when building the app. Defaults to 'Release'",
195
200
  default_value_dynamic: true,
196
201
  optional: true),
197
- FastlaneCore::ConfigItem.new(key: :xcpretty_args,
198
- short_option: "-x",
199
- env_name: "SNAPSHOT_XCPRETTY_ARGS",
200
- description: "Additional xcpretty arguments",
201
- is_string: true,
202
- optional: true),
203
202
  FastlaneCore::ConfigItem.new(key: :sdk,
204
203
  short_option: "-k",
205
204
  env_name: "SNAPSHOT_SDK",
@@ -289,11 +288,28 @@ module Snapshot
289
288
  verify_block: proc do |value|
290
289
  verify_type('skip_testing', [Array, String], value)
291
290
  end),
291
+
292
+ FastlaneCore::ConfigItem.new(key: :xcodebuild_formatter,
293
+ env_names: ["SNAPSHOT_XCODEBUILD_FORMATTER", "FASTLANE_XCODEBUILD_FORMATTER"],
294
+ description: "xcodebuild formatter to use (ex: 'xcbeautify', 'xcbeautify --quieter', 'xcpretty', 'xcpretty -test')",
295
+ type: String,
296
+ default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
297
+ default_value_dynamic: true),
298
+
299
+ # xcpretty
300
+ FastlaneCore::ConfigItem.new(key: :xcpretty_args,
301
+ short_option: "-x",
302
+ env_name: "SNAPSHOT_XCPRETTY_ARGS",
303
+ deprecated: "Use `xcodebuild_formatter: ''` instead",
304
+ description: "Additional xcpretty arguments",
305
+ is_string: true,
306
+ optional: true),
292
307
  FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
293
308
  env_name: "SNAPSHOT_DISABLE_XCPRETTY",
294
309
  description: "Disable xcpretty formatting of build",
295
310
  type: Boolean,
296
311
  optional: true),
312
+
297
313
  FastlaneCore::ConfigItem.new(key: :suppress_xcode_output,
298
314
  env_name: "SNAPSHOT_SUPPRESS_XCODE_OUTPUT",
299
315
  description: "Suppress the output of xcodebuild to stdout. Output is still saved in buildlog_path",
@@ -123,7 +123,7 @@ module Snapshot
123
123
  # Simulator could stil be booting with Apple logo
124
124
  # Need to wait "some amount of time" until home screen shows
125
125
  boot_sleep = ENV["SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT"].to_i || 10
126
- UI.message("Waiting #{boot_sleep} seconds for device to fully boot before overriding status bar... Set 'SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT' environemnt variable to adjust timeout")
126
+ UI.message("Waiting #{boot_sleep} seconds for device to fully boot before overriding status bar... Set 'SNAPSHOT_SIMULATOR_WAIT_FOR_BOOT_TIMEOUT' environment variable to adjust timeout")
127
127
  sleep(boot_sleep) if boot_sleep > 0
128
128
 
129
129
  UI.message("Overriding Status Bar")
@@ -27,10 +27,45 @@ module Snapshot
27
27
  tee_command << log_path.shellescape if log_path
28
28
 
29
29
  pipe = ["| #{tee_command.join(' ')}"]
30
- if Snapshot.config[:disable_xcpretty]
31
- return pipe
30
+
31
+ formatter = Snapshot.config[:xcodebuild_formatter].chomp
32
+ options = legacy_xcpretty_options
33
+
34
+ if Snapshot.config[:disable_xcpretty] || formatter == ''
35
+ UI.verbose("Not using an xcodebuild formatter")
36
+ elsif !options.empty?
37
+ UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
38
+ UI.important("Option(s) used: #{options.join(', ')}")
39
+ pipe += pipe_xcpretty
40
+ elsif formatter == 'xcpretty'
41
+ pipe += pipe_xcpretty
42
+ elsif formatter == 'xcbeautify'
43
+ pipe += pipe_xcbeautify
44
+ else
45
+ pipe << "| #{formatter}"
46
+ end
47
+
48
+ pipe
49
+ end
50
+
51
+ def pipe_xcbeautify
52
+ pipe = ['| xcbeautify']
53
+
54
+ if FastlaneCore::Helper.colors_disabled?
55
+ pipe << '--disable-colored-output'
32
56
  end
33
57
 
58
+ return pipe
59
+ end
60
+
61
+ def legacy_xcpretty_options
62
+ options = []
63
+ options << "xcpretty_args" if Snapshot.config[:xcpretty_args]
64
+ return options
65
+ end
66
+
67
+ def pipe_xcpretty
68
+ pipe = []
34
69
  xcpretty = "xcpretty #{Snapshot.config[:xcpretty_args]}"
35
70
  xcpretty << "--no-color" if Helper.colors_disabled?
36
71
  pipe << "| #{xcpretty}"
@@ -391,10 +391,11 @@ module Spaceship
391
391
 
392
392
  keychain_entry = CredentialsManager::AccountManager.new(user: user, password: password)
393
393
  user ||= keychain_entry.user
394
- password = keychain_entry.password
394
+ password = keychain_entry.password(ask_if_missing: !Spaceship::Globals.check_session)
395
395
  end
396
396
 
397
397
  if user.to_s.strip.empty? || password.to_s.strip.empty?
398
+ exit_with_session_state(user, false) if Spaceship::Globals.check_session
398
399
  raise NoUserCredentialsError.new, "No login data provided"
399
400
  end
400
401
 
@@ -413,21 +414,16 @@ module Spaceship
413
414
  end
414
415
  end
415
416
 
416
- # This method is used for both the Apple Dev Portal and App Store Connect
417
- # This will also handle 2 step verification and 2 factor authentication
417
+ # Check if we have a cached/valid session
418
418
  #
419
- # It is called in `send_login_request` of sub classes (which the method `login`, above, transferred over to via `do_login`)
420
- # rubocop:disable Metrics/PerceivedComplexity
421
- def send_shared_login_request(user, password)
422
- # Check if we have a cached/valid session
423
- #
424
- # Background:
425
- # December 4th 2017 Apple introduced a rate limit - which is of course fine by itself -
426
- # but unfortunately also rate limits successful logins. If you call multiple tools in a
427
- # lane (e.g. call match 5 times), this would lock you out of the account for a while.
428
- # By loading existing sessions and checking if they're valid, we're sending less login requests.
429
- # More context on why this change was necessary https://github.com/fastlane/fastlane/pull/11108
430
- #
419
+ # Background:
420
+ # December 4th 2017 Apple introduced a rate limit - which is of course fine by itself -
421
+ # but unfortunately also rate limits successful logins. If you call multiple tools in a
422
+ # lane (e.g. call match 5 times), this would lock you out of the account for a while.
423
+ # By loading existing sessions and checking if they're valid, we're sending less login requests.
424
+ # More context on why this change was necessary https://github.com/fastlane/fastlane/pull/11108
425
+ #
426
+ def has_valid_session
431
427
  # If there was a successful manual login before, we have a session on disk
432
428
  if load_session_from_file
433
429
  # Check if the session is still valid here
@@ -462,6 +458,23 @@ module Spaceship
462
458
  #
463
459
  # After this point, we sure have no valid session any more and have to create a new one
464
460
  #
461
+ return false
462
+ end
463
+
464
+ # This method is used for both the Apple Dev Portal and App Store Connect
465
+ # This will also handle 2 step verification and 2 factor authentication
466
+ #
467
+ # It is called in `send_login_request` of sub classes (which the method `login`, above, transferred over to via `do_login`)
468
+ # rubocop:disable Metrics/PerceivedComplexity
469
+ def send_shared_login_request(user, password)
470
+ # Check if the cache or FASTLANE_SESSION is still valid
471
+ has_valid_session = self.has_valid_session
472
+
473
+ # Exit if `--check_session` flag was passed
474
+ exit_with_session_state(user, has_valid_session) if Spaceship::Globals.check_session
475
+
476
+ # If the session is valid no need to attempt to generate a new one.
477
+ return true if has_valid_session
465
478
 
466
479
  data = {
467
480
  accountName: user,
@@ -566,6 +579,13 @@ module Spaceship
566
579
  return false
567
580
  end
568
581
 
582
+ # This method is used to log if the session is valid or not and then exit
583
+ # It is called when the `--check_session` flag is passed
584
+ def exit_with_session_state(user, has_valid_session)
585
+ puts("#{has_valid_session ? 'Valid' : 'No valid'} session found (#{user}). Exiting.")
586
+ exit(has_valid_session)
587
+ end
588
+
569
589
  def itc_service_key
570
590
  return @service_key if @service_key
571
591
 
@@ -41,7 +41,7 @@ module Spaceship
41
41
  c.syntax = 'fastlane spaceship spaceauth'
42
42
  c.description = 'Authentication helper for spaceship/fastlane to work with Apple 2-Step/2FA'
43
43
  c.option('--copy_to_clipboard', 'Whether the session string should be copied to clipboard. For more info see https://docs.fastlane.tools/best-practices/continuous-integration/#storing-a-manually-verified-session-using-spaceauth`')
44
-
44
+ c.option('--check_session', 'Check to see if there is a valid session (either in the cache or via FASTLANE_SESSION). Sets the exit code to 0 if the session is valid or 1 if not.') { Spaceship::Globals.check_session = true }
45
45
  c.action do |args, options|
46
46
  Spaceship::SpaceauthRunner.new(username: options.user, copy_to_clipboard: options.copy_to_clipboard).run
47
47
  end
@@ -1,6 +1,7 @@
1
1
  require_relative '../model'
2
2
  require_relative './build'
3
3
 
4
+ # rubocop:disable Metrics/ClassLength
4
5
  module Spaceship
5
6
  class ConnectAPI
6
7
  class App
@@ -414,6 +415,47 @@ module Spaceship
414
415
  })
415
416
  end
416
417
 
418
+ #
419
+ # Review Submissions
420
+ #
421
+
422
+ def get_ready_review_submission(client: nil, platform:, includes: nil)
423
+ client ||= Spaceship::ConnectAPI
424
+ filter = {
425
+ state: [
426
+ Spaceship::ConnectAPI::ReviewSubmission::ReviewSubmissionState::READY_FOR_REVIEW
427
+ ].join(","),
428
+ platform: platform
429
+ }
430
+
431
+ return get_review_submissions(client: client, filter: filter, includes: includes).first
432
+ end
433
+
434
+ def get_in_progress_review_submission(client: nil, platform:, includes: nil)
435
+ client ||= Spaceship::ConnectAPI
436
+ filter = {
437
+ state: [
438
+ Spaceship::ConnectAPI::ReviewSubmission::ReviewSubmissionState::WAITING_FOR_REVIEW
439
+ ].join(","),
440
+ platform: platform
441
+ }
442
+
443
+ return get_review_submissions(client: client, filter: filter, includes: includes).first
444
+ end
445
+
446
+ # appStoreVersionForReview,items
447
+ def get_review_submissions(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
448
+ client ||= Spaceship::ConnectAPI
449
+ resps = client.get_review_submissions(app_id: id, filter: filter, includes: includes, limit: limit, sort: sort).all_pages
450
+ return resps.flat_map(&:to_models)
451
+ end
452
+
453
+ def create_review_submission(client: nil, platform:)
454
+ client ||= Spaceship::ConnectAPI
455
+ resp = client.post_review_submission(app_id: id, platform: platform)
456
+ return resp.to_models.first
457
+ end
458
+
417
459
  #
418
460
  # Users
419
461
  #
@@ -434,3 +476,4 @@ module Spaceship
434
476
  end
435
477
  end
436
478
  end
479
+ # rubocop:enable Metrics/ClassLength
@@ -25,6 +25,7 @@ module Spaceship
25
25
  WAITING_FOR_REVIEW = "WAITING_FOR_REVIEW"
26
26
  DEVELOPER_REJECTED = "DEVELOPER_REJECTED"
27
27
  DEVELOPER_REMOVED_FROM_SALE = "DEVELOPER_REMOVED_FROM_SALE"
28
+ READY_FOR_REVIEW = "READY_FOR_REVIEW"
28
29
  REJECTED = "REJECTED"
29
30
  PREPARE_FOR_SUBMISSION = "PREPARE_FOR_SUBMISSION"
30
31
  METADATA_REJECTED = "METADATA_REJECTED"
@@ -38,6 +38,7 @@ module Spaceship
38
38
 
39
39
  APP_WATCH_SERIES_3 = "APP_WATCH_SERIES_3"
40
40
  APP_WATCH_SERIES_4 = "APP_WATCH_SERIES_4"
41
+ APP_WATCH_SERIES_7 = "APP_WATCH_SERIES_7"
41
42
 
42
43
  APP_APPLE_TV = "APP_APPLE_TV"
43
44
 
@@ -85,6 +86,7 @@ module Spaceship
85
86
 
86
87
  APP_WATCH_SERIES_3,
87
88
  APP_WATCH_SERIES_4,
89
+ APP_WATCH_SERIES_7,
88
90
 
89
91
  APP_DESKTOP
90
92
  ]
@@ -0,0 +1,73 @@
1
+ require_relative '../model'
2
+ require_relative './review_submission_item'
3
+
4
+ module Spaceship
5
+ class ConnectAPI
6
+ class ReviewSubmission
7
+ include Spaceship::ConnectAPI::Model
8
+
9
+ attr_accessor :platform
10
+ attr_accessor :state
11
+ attr_accessor :submitted_date
12
+
13
+ attr_accessor :app_store_version_for_review
14
+ attr_accessor :items
15
+ attr_accessor :last_updated_by_actor
16
+ attr_accessor :submitted_by_actor
17
+
18
+ module ReviewSubmissionState
19
+ CANCELING = "CANCELING"
20
+ COMPLETE = "COMPLETE"
21
+ IN_REVIEW = "IN_REVIEW"
22
+ READY_FOR_REVIEW = "READY_FOR_REVIEW"
23
+ WAITING_FOR_REVIEW = "WAITING_FOR_REVIEW"
24
+ end
25
+
26
+ attr_mapping({
27
+ "platform" => "platform",
28
+ "state" => "state",
29
+ "submittedDate" => "submitted_date",
30
+
31
+ "appStoreVersionForReview" => "app_store_version_for_review",
32
+ "items" => "items",
33
+ "lastUpdatedByActor" => "last_updated_by_actor",
34
+ "submittedByActor" => "submitted_by_actor",
35
+ })
36
+
37
+ def self.type
38
+ return "reviewSubmissions"
39
+ end
40
+
41
+ #
42
+ # API
43
+ #
44
+
45
+ # appStoreVersionForReview,items,submittedByActor,lastUpdatedByActor
46
+ def self.get(client: nil, review_submission_id:, includes: nil)
47
+ client ||= Spaceship::ConnectAPI
48
+ resp = client.get_review_submission(review_submission_id: review_submission_id, includes: includes)
49
+ return resp.to_models.first
50
+ end
51
+
52
+ def submit_for_review(client: nil)
53
+ client ||= Spaceship::ConnectAPI
54
+ attributes = { submitted: true }
55
+ resp = client.patch_review_submission(review_submission_id: id, attributes: attributes)
56
+ return resp.to_models.first
57
+ end
58
+
59
+ def cancel_submission(client: nil)
60
+ client ||= Spaceship::ConnectAPI
61
+ attributes = { canceled: true }
62
+ resp = client.patch_review_submission(review_submission_id: id, attributes: attributes)
63
+ return resp.to_models.first
64
+ end
65
+
66
+ def add_app_store_version_to_review_items(client: nil, app_store_version_id:)
67
+ client ||= Spaceship::ConnectAPI
68
+ resp = client.post_review_submission_item(review_submission_id: id, app_store_version_id: app_store_version_id)
69
+ return resp.to_models.first
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,40 @@
1
+ require_relative '../model'
2
+
3
+ module Spaceship
4
+ class ConnectAPI
5
+ class ReviewSubmissionItem
6
+ include Spaceship::ConnectAPI::Model
7
+
8
+ attr_accessor :state
9
+
10
+ attr_accessor :app_store_version_experiment
11
+ attr_accessor :app_store_version
12
+ attr_accessor :app_store_product_page_version
13
+ attr_accessor :app_event
14
+
15
+ attr_mapping({
16
+ "state" => "state",
17
+
18
+ "appStoreVersionExperiment" => "app_store_version_experiment",
19
+ "appStoreVersion" => "app_store_version",
20
+ "appCustomProductPageVersion" => "app_store_product_page_version",
21
+ "appEvent" => "app_event",
22
+ })
23
+
24
+ def self.type
25
+ return "reviewSubmissionItems"
26
+ end
27
+
28
+ #
29
+ # API
30
+ #
31
+
32
+ # appCustomProductPageVersion,appEvent,appStoreVersion,appStoreVersionExperiment
33
+ def self.all(client: nil, review_submission_id:, includes: nil, limit: nil, sort: nil)
34
+ client ||= Spaceship::ConnectAPI
35
+ resps = client.get_review_submission_items(review_submission_id: review_submission_id, includes: includes, limit: limit, sort: sort).all_pages
36
+ return resps.flat_map(&:to_models)
37
+ end
38
+ end
39
+ end
40
+ end
@@ -64,6 +64,19 @@ module Spaceship
64
64
  yield(model)
65
65
  end
66
66
  end
67
+
68
+ def all_pages_each(&block)
69
+ to_models.each do |model|
70
+ yield(model)
71
+ end
72
+
73
+ resp = self
74
+ loop do
75
+ resp = resp.next_page
76
+ break if resp.nil?
77
+ resp.each(&block)
78
+ end
79
+ end
67
80
  end
68
81
  end
69
82
  end
@@ -1126,6 +1126,89 @@ module Spaceship
1126
1126
  tunes_request_client.delete("idfaDeclarations/#{idfa_declaration_id}", params)
1127
1127
  end
1128
1128
 
1129
+ #
1130
+ # reviewSubmissions
1131
+ #
1132
+
1133
+ def get_review_submissions(app_id:, filter: {}, includes: nil, limit: nil, sort: nil)
1134
+ params = tunes_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
1135
+ tunes_request_client.get("apps/#{app_id}/reviewSubmissions", params)
1136
+ end
1137
+
1138
+ def get_review_submission(review_submission_id:, filter: {}, includes: nil, limit: nil, sort: nil)
1139
+ params = tunes_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
1140
+ tunes_request_client.get("reviewSubmissions/#{review_submission_id}", params)
1141
+ end
1142
+
1143
+ def post_review_submission(app_id:, platform:)
1144
+ body = {
1145
+ data: {
1146
+ type: "reviewSubmissions",
1147
+ attributes: {
1148
+ platform: platform
1149
+ },
1150
+ relationships: {
1151
+ app: {
1152
+ data: {
1153
+ type: "apps",
1154
+ id: app_id
1155
+ }
1156
+ }
1157
+ }
1158
+ }
1159
+ }
1160
+
1161
+ tunes_request_client.post("reviewSubmissions", body)
1162
+ end
1163
+
1164
+ def patch_review_submission(review_submission_id:, attributes: nil)
1165
+ body = {
1166
+ data: {
1167
+ type: "reviewSubmissions",
1168
+ id: review_submission_id,
1169
+ attributes: attributes,
1170
+ }
1171
+ }
1172
+
1173
+ tunes_request_client.patch("reviewSubmissions/#{review_submission_id}", body)
1174
+ end
1175
+
1176
+ #
1177
+ # reviewSubmissionItems
1178
+ #
1179
+
1180
+ def get_review_submission_items(review_submission_id:, filter: {}, includes: nil, limit: nil, sort: nil)
1181
+ params = tunes_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
1182
+ tunes_request_client.get("reviewSubmissions/#{review_submission_id}/items", params)
1183
+ end
1184
+
1185
+ def post_review_submission_item(review_submission_id:, app_store_version_id: nil)
1186
+ body = {
1187
+ data: {
1188
+ type: "reviewSubmissionItems",
1189
+ relationships: {
1190
+ reviewSubmission: {
1191
+ data: {
1192
+ type: "reviewSubmissions",
1193
+ id: review_submission_id
1194
+ }
1195
+ }
1196
+ }
1197
+ }
1198
+ }
1199
+
1200
+ unless app_store_version_id.nil?
1201
+ body[:data][:relationships][:appStoreVersion] = {
1202
+ data: {
1203
+ type: "appStoreVersions",
1204
+ id: app_store_version_id
1205
+ }
1206
+ }
1207
+ end
1208
+
1209
+ tunes_request_client.post("reviewSubmissionItems", body)
1210
+ end
1211
+
1129
1212
  #
1130
1213
  # sandboxTesters
1131
1214
  #
@@ -62,6 +62,8 @@ require 'spaceship/connect_api/models/app_store_version_localization'
62
62
  require 'spaceship/connect_api/models/app_store_version_phased_release'
63
63
  require 'spaceship/connect_api/models/app_store_version'
64
64
  require 'spaceship/connect_api/models/idfa_declaration'
65
+ require 'spaceship/connect_api/models/review_submission'
66
+ require 'spaceship/connect_api/models/review_submission_item'
65
67
  require 'spaceship/connect_api/models/reset_ratings_request'
66
68
  require 'spaceship/connect_api/models/sandbox_tester'
67
69
  require 'spaceship/connect_api/models/territory'
@@ -1,5 +1,9 @@
1
1
  module Spaceship
2
2
  class Globals
3
+ class << self
4
+ attr_writer(:check_session)
5
+ end
6
+
3
7
  # if spaceship is run with a FastlaneCore available respect the global state there
4
8
  # otherwise fallback to $verbose
5
9
  def self.verbose?
@@ -8,5 +12,10 @@ module Spaceship
8
12
  end
9
13
  return $verbose
10
14
  end
15
+
16
+ # if spaceship is run with the --check_session flag this value will be set to true
17
+ def self.check_session
18
+ return @check_session
19
+ end
11
20
  end
12
21
  end
@@ -16,7 +16,7 @@ module Spaceship
16
16
 
17
17
  def run
18
18
  begin
19
- puts("Logging into to App Store Connect (#{@username})...")
19
+ puts("Logging into to App Store Connect (#{@username})...") unless Spaceship::Globals.check_session
20
20
  Spaceship::Tunes.login(@username)
21
21
  puts("Successfully logged in to App Store Connect".green)
22
22
  puts("")