fastlane 2.199.0 → 2.201.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +92 -92
  4. data/deliver/lib/deliver/app_screenshot.rb +7 -0
  5. data/fastlane/lib/fastlane/.version.rb.swp +0 -0
  6. data/fastlane/lib/fastlane/actions/download_dsyms.rb +1 -1
  7. data/fastlane/lib/fastlane/actions/get_version_number.rb +1 -0
  8. data/fastlane/lib/fastlane/actions/trainer.rb +49 -0
  9. data/fastlane/lib/fastlane/helper/xcodebuild_formatter_helper.rb +9 -0
  10. data/fastlane/lib/fastlane/tools.rb +2 -1
  11. data/fastlane/lib/fastlane/version.rb +1 -1
  12. data/fastlane/swift/Actions.swift +1 -1
  13. data/fastlane/swift/Appfile.swift +1 -1
  14. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  15. data/fastlane/swift/ControlCommand.swift +1 -1
  16. data/fastlane/swift/Deliverfile.swift +2 -2
  17. data/fastlane/swift/DeliverfileProtocol.swift +2 -2
  18. data/fastlane/swift/Fastlane.swift +11 -3
  19. data/fastlane/swift/Gymfile.swift +2 -2
  20. data/fastlane/swift/GymfileProtocol.swift +2 -2
  21. data/fastlane/swift/LaneFileProtocol.swift +1 -1
  22. data/fastlane/swift/MainProcess.swift +1 -1
  23. data/fastlane/swift/Matchfile.swift +2 -2
  24. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  25. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  26. data/fastlane/swift/Plugins.swift +1 -1
  27. data/fastlane/swift/Precheckfile.swift +2 -2
  28. data/fastlane/swift/PrecheckfileProtocol.swift +2 -2
  29. data/fastlane/swift/RubyCommand.swift +1 -1
  30. data/fastlane/swift/RubyCommandable.swift +1 -1
  31. data/fastlane/swift/Runner.swift +1 -1
  32. data/fastlane/swift/RunnerArgument.swift +1 -1
  33. data/fastlane/swift/Scanfile.swift +2 -2
  34. data/fastlane/swift/ScanfileProtocol.swift +2 -2
  35. data/fastlane/swift/Screengrabfile.swift +2 -2
  36. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  37. data/fastlane/swift/Snapshotfile.swift +2 -2
  38. data/fastlane/swift/SnapshotfileProtocol.swift +2 -2
  39. data/fastlane/swift/SocketClient.swift +1 -1
  40. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  41. data/fastlane/swift/SocketResponse.swift +1 -1
  42. data/fastlane/swift/formatting/Brewfile.lock.json +3 -3
  43. data/fastlane/swift/main.swift +1 -1
  44. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +10 -5
  45. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +4 -1
  46. data/gym/lib/gym/generators/build_command_generator.rb +68 -22
  47. data/gym/lib/gym/options.rb +17 -5
  48. data/scan/lib/scan/.detect_values.rb.swp +0 -0
  49. data/scan/lib/scan/.options.rb.swp +0 -0
  50. data/scan/lib/scan/.runner.rb.swp +0 -0
  51. data/scan/lib/scan/options.rb +25 -5
  52. data/scan/lib/scan/runner.rb +115 -14
  53. data/scan/lib/scan/test_command_generator.rb +55 -5
  54. data/snapshot/lib/snapshot/.collector.rb.swp +0 -0
  55. data/snapshot/lib/snapshot/options.rb +23 -7
  56. data/snapshot/lib/snapshot/test_command_generator.rb +37 -2
  57. data/spaceship/lib/spaceship/connect_api/models/app.rb +43 -0
  58. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +1 -0
  59. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +2 -0
  60. data/spaceship/lib/spaceship/connect_api/models/review_submission.rb +73 -0
  61. data/spaceship/lib/spaceship/connect_api/models/review_submission_item.rb +40 -0
  62. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +83 -0
  63. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  64. data/supply/lib/supply/options.rb +8 -0
  65. data/supply/lib/supply/uploader.rb +6 -2
  66. data/trainer/lib/assets/.junit.xml.erb.swp +0 -0
  67. data/trainer/lib/assets/junit.xml.erb +20 -0
  68. data/trainer/lib/trainer/.junit_generator.rb.swp +0 -0
  69. data/trainer/lib/trainer/.test_parser.rb.swp +0 -0
  70. data/trainer/lib/trainer/commands_generator.rb +51 -0
  71. data/trainer/lib/trainer/junit_generator.rb +31 -0
  72. data/trainer/lib/trainer/module.rb +10 -0
  73. data/trainer/lib/trainer/options.rb +55 -0
  74. data/trainer/lib/trainer/test_parser.rb +352 -0
  75. data/trainer/lib/trainer/xcresult.rb +403 -0
  76. data/trainer/lib/trainer.rb +7 -0
  77. metadata +42 -22
@@ -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,56 @@ 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 formatter == ''
123
+ UI.verbose("Not using an xcodebuild formatter")
124
+ elsif !options.empty?
125
+ UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
126
+ UI.important("Option(s) used: #{options.join(', ')}")
127
+ pipe << pipe_xcpretty
128
+ elsif formatter == 'xcpretty'
129
+ pipe << pipe_xcpretty
130
+ elsif formatter == 'xcbeautify'
131
+ pipe << pipe_xcbeautify
132
+ else
133
+ pipe << "| #{formatter}"
134
+ end
135
+
136
+ return pipe
137
+ end
138
+
139
+ def pipe_xcbeautify
140
+ formatter = ['| xcbeautify']
141
+
142
+ if FastlaneCore::Helper.colors_disabled?
143
+ formatter << '--disable-colored-output'
144
+ end
145
+
146
+ return formatter.join(' ')
147
+ end
148
+
149
+ def legacy_xcpretty_options
150
+ options = []
151
+
152
+ options << "formatter" if Scan.config[:formatter]
153
+ options << "xcpretty_formatter" if Scan.config[:xcpretty_formatter]
154
+ options << "output_style" if Scan.config[:output_style]
155
+ options << "output_types" if (Scan.config[:output_types] || "").include?("json-compilation-database")
156
+ options << "custom_report_file_name" if Scan.config[:custom_report_file_name]
157
+
158
+ return options
159
+ end
160
+
161
+ def pipe_xcpretty
114
162
  formatter = []
115
- if (custom_formatter = Scan.config[:formatter])
163
+ if (custom_formatter = Scan.config[:xcpretty_formatter] || Scan.config[:formatter])
116
164
  if custom_formatter.end_with?(".rb")
117
165
  formatter << "-f '#{custom_formatter}'"
118
166
  else
@@ -143,7 +191,7 @@ module Scan
143
191
  Scan.config[:xcpretty_args])
144
192
  reporter_options = @reporter_options_generator.generate_reporter_options
145
193
  reporter_xcpretty_args = @reporter_options_generator.generate_xcpretty_args_options
146
- return pipe << "| xcpretty #{formatter.join(' ')} #{reporter_options.join(' ')} #{reporter_xcpretty_args}"
194
+ return "| xcpretty #{formatter.join(' ')} #{reporter_options.join(' ')} #{reporter_xcpretty_args}"
147
195
  end
148
196
 
149
197
  # Store the raw file
@@ -183,11 +231,13 @@ module Scan
183
231
  end
184
232
 
185
233
  # The path to the result bundle
186
- def result_bundle_path
234
+ def result_bundle_path(use_output_directory)
235
+ root_dir = use_output_directory ? Scan.config[:output_directory] : Dir.mktmpdir
236
+
187
237
  retry_count = Scan.cache[:retry_attempt] || 0
188
238
  attempt = retry_count > 0 ? "-#{retry_count}" : ""
189
239
  ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
190
- path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + attempt + ext
240
+ path = File.join([root_dir, Scan.config[:scheme]].compact) + attempt + ext
191
241
 
192
242
  Scan.cache[:result_bundle_path] = path
193
243
 
@@ -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'). Use empty string (ex: '') to disable any formatter",
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",
@@ -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}"
@@ -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
@@ -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'
@@ -217,6 +217,14 @@ module Supply
217
217
  verify_block: proc do |value|
218
218
  UI.user_error!("'rollout' is no longer a valid track name - please use 'production' instead") if value.casecmp('rollout').zero?
219
219
  end),
220
+ FastlaneCore::ConfigItem.new(key: :track_promote_release_status,
221
+ env_name: "SUPPLY_TRACK_PROMOTE_RELEASE_STATUS",
222
+ optional: true,
223
+ description: "Promoted track release status (used when promoting a track) - valid values are #{Supply::ReleaseStatus::ALL.join(', ')}",
224
+ default_value: Supply::ReleaseStatus::COMPLETED,
225
+ verify_block: proc do |value|
226
+ UI.user_error!("Value must be one of '#{Supply::RELEASE_STATUS}'") unless Supply::ReleaseStatus::ALL.include?(value)
227
+ end),
220
228
  FastlaneCore::ConfigItem.new(key: :validate_only,
221
229
  env_name: "SUPPLY_VALIDATE_ONLY",
222
230
  optional: true,
@@ -164,6 +164,10 @@ module Supply
164
164
  UI.user_error!(%(Cannot specify rollout percentage when the release status is set to 'draft'))
165
165
  end
166
166
 
167
+ if Supply.config[:track_promote_release_status] == Supply::ReleaseStatus::DRAFT && Supply.config[:rollout]
168
+ UI.user_error!(%(Cannot specify rollout percentage when the track promote release status is set to 'draft'))
169
+ end
170
+
167
171
  unless Supply.config[:version_codes_to_retain].nil?
168
172
  Supply.config[:version_codes_to_retain] = Supply.config[:version_codes_to_retain].map(&:to_i)
169
173
  end
@@ -182,7 +186,7 @@ module Supply
182
186
  end
183
187
  else
184
188
  releases = releases.select do |release|
185
- release.status == Supply::ReleaseStatus::COMPLETED
189
+ release.status == Supply.config[:release_status]
186
190
  end
187
191
  end
188
192
 
@@ -200,7 +204,7 @@ module Supply
200
204
  release.status = Supply::ReleaseStatus::IN_PROGRESS
201
205
  release.user_fraction = rollout
202
206
  else
203
- release.status = Supply::ReleaseStatus::COMPLETED
207
+ release.status = Supply.config[:track_promote_release_status]
204
208
  release.user_fraction = nil
205
209
  end
206
210
 
@@ -0,0 +1,20 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <% number_of_tests = 0 %>
3
+ <% number_of_failures = 0 %>
4
+ <% @results.each { |a| number_of_tests += a[:number_of_tests_excluding_retries] } %>
5
+ <% @results.each { |a| number_of_failures += a[:number_of_failures_excluding_retries] } %>
6
+
7
+ <testsuites tests="<%= number_of_tests %>" failures="<%= number_of_failures %>">
8
+ <% @results.each do |testsuite| %>
9
+ <testsuite name=<%= (testsuite[:target_name].nil? ? testsuite[:test_name] : testsuite[:target_name]).encode(:xml => :attr) %> tests="<%= testsuite[:number_of_tests_excluding_retries] %>" failures="<%= testsuite[:number_of_failures_excluding_retries] %>" time="<%= testsuite[:duration] %>">
10
+ <% testsuite[:tests].each do |test| %>
11
+ <testcase classname=<%= test[:test_group].encode(:xml => :attr) %> name=<%= test[:name].encode(:xml => :attr) %> time="<%= test[:duration] %>">
12
+ <% (test[:failures] || []).each do |failure| %>
13
+ <failure message=<%= failure[:failure_message].encode(:xml => :attr) %>>
14
+ </failure>
15
+ <% end %>
16
+ </testcase>
17
+ <% end %>
18
+ </testsuite>
19
+ <% end %>
20
+ </testsuites>
@@ -0,0 +1,51 @@
1
+ require 'commander'
2
+
3
+ require 'fastlane_core/configuration/configuration'
4
+ require 'fastlane_core/ui/help_formatter'
5
+
6
+ require_relative 'options'
7
+ require_relative 'test_parser'
8
+
9
+ require_relative 'module'
10
+
11
+ HighLine.track_eof = false
12
+
13
+ module Trainer
14
+ class CommandsGenerator
15
+ include Commander::Methods
16
+
17
+ def self.start
18
+ self.new.run
19
+ end
20
+
21
+ def run
22
+ program :version, Fastlane::VERSION
23
+ program :description, Trainer::DESCRIPTION
24
+ program :help, 'Author', 'Felix Krause <trainer@krausefx.com>'
25
+ program :help, 'Website', 'https://fastlane.tools'
26
+ program :help, 'GitHub', 'https://github.com/KrauseFx/trainer'
27
+ program :help_formatter, :compact
28
+
29
+ global_option('--verbose', 'Shows a more verbose output') { $verbose = true }
30
+
31
+ always_trace!
32
+
33
+ FastlaneCore::CommanderGenerator.new.generate(Trainer::Options.available_options)
34
+
35
+ command :run do |c|
36
+ c.syntax = 'trainer'
37
+ c.description = Trainer::DESCRIPTION
38
+
39
+ c.action do |args, options|
40
+ options = FastlaneCore::Configuration.create(Trainer::Options.available_options, options.__hash__)
41
+ FastlaneCore::PrintTable.print_values(config: options, title: "Summary for trainer #{Fastlane::VERSION}") if $verbose
42
+ Trainer::TestParser.auto_convert(options)
43
+ end
44
+ end
45
+
46
+ default_command(:run)
47
+
48
+ run!
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,31 @@
1
+ require_relative 'module'
2
+
3
+ module Trainer
4
+ class JunitGenerator
5
+ attr_accessor :results
6
+
7
+ def initialize(results)
8
+ self.results = results
9
+ end
10
+
11
+ def generate
12
+ # JUnit file documentation: http://llg.cubic.org/docs/junit/
13
+ # And http://nelsonwells.net/2012/09/how-jenkins-ci-parses-and-displays-junit-output/
14
+ # And http://windyroad.com.au/dl/Open%20Source/JUnit.xsd
15
+
16
+ lib_path = Trainer::ROOT
17
+ xml_path = File.join(lib_path, "lib/assets/junit.xml.erb")
18
+ xml = ERB.new(File.read(xml_path), nil, '<>').result(binding) # http://www.rrn.dk/rubys-erb-templating-system
19
+
20
+ xml = xml.gsub('system_', 'system-').delete("\e") # Jenkins can not parse 'ESC' symbol
21
+
22
+ # We have to manuall clear empty lines
23
+ # They may contain white spaces
24
+ clean_xml = []
25
+ xml.each_line do |row|
26
+ clean_xml << row.delete("\n") if row.strip.to_s.length > 0
27
+ end
28
+ return clean_xml.join("\n")
29
+ end
30
+ end
31
+ end