fastlane 2.135.2 → 2.140.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +64 -64
  3. data/deliver/lib/deliver/submit_for_review.rb +7 -1
  4. data/fastlane/lib/fastlane/action.rb +2 -2
  5. data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
  6. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  7. data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
  8. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +1 -1
  9. data/fastlane/lib/fastlane/actions/create_pull_request.rb +42 -2
  10. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +38 -4
  11. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +19 -0
  12. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +10 -0
  13. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +4 -2
  14. data/fastlane/lib/fastlane/actions/ensure_bundle_exec.rb +3 -3
  15. data/fastlane/lib/fastlane/actions/get_version_number.rb +7 -2
  16. data/fastlane/lib/fastlane/actions/gradle.rb +54 -3
  17. data/fastlane/lib/fastlane/actions/increment_version_number.rb +6 -3
  18. data/fastlane/lib/fastlane/actions/last_git_tag.rb +14 -5
  19. data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +2 -2
  20. data/fastlane/lib/fastlane/actions/register_devices.rb +5 -1
  21. data/fastlane/lib/fastlane/actions/ruby_version.rb +1 -1
  22. data/fastlane/lib/fastlane/actions/run_tests.rb +5 -22
  23. data/fastlane/lib/fastlane/actions/setup_ci.rb +14 -8
  24. data/fastlane/lib/fastlane/actions/testfairy.rb +8 -1
  25. data/fastlane/lib/fastlane/actions/upload_to_play_store_internal_app_sharing.rb +78 -0
  26. data/fastlane/lib/fastlane/actions/verify_build.rb +1 -1
  27. data/fastlane/lib/fastlane/actions/xcode_select.rb +6 -1
  28. data/fastlane/lib/fastlane/cli_tools_distributor.rb +2 -2
  29. data/fastlane/lib/fastlane/commands_generator.rb +1 -1
  30. data/fastlane/lib/fastlane/helper/adb_helper.rb +13 -4
  31. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -0
  32. data/fastlane/lib/fastlane/runner.rb +23 -18
  33. data/fastlane/lib/fastlane/swift_fastlane_function.rb +9 -0
  34. data/fastlane/lib/fastlane/version.rb +1 -1
  35. data/fastlane/swift/Deliverfile.swift +1 -1
  36. data/fastlane/swift/Fastlane.swift +130 -28
  37. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  38. data/fastlane/swift/Gymfile.swift +1 -1
  39. data/fastlane/swift/Matchfile.swift +1 -1
  40. data/fastlane/swift/MatchfileProtocol.swift +6 -2
  41. data/fastlane/swift/Precheckfile.swift +1 -1
  42. data/fastlane/swift/Scanfile.swift +1 -1
  43. data/fastlane/swift/ScanfileProtocol.swift +13 -1
  44. data/fastlane/swift/Screengrabfile.swift +1 -1
  45. data/fastlane/swift/ScreengrabfileProtocol.swift +14 -2
  46. data/fastlane/swift/Snapshotfile.swift +1 -1
  47. data/fastlane_core/lib/fastlane_core/.build_watcher.rb.swp +0 -0
  48. data/fastlane_core/lib/fastlane_core/build_watcher.rb +6 -2
  49. data/fastlane_core/lib/fastlane_core/device_manager.rb +20 -0
  50. data/fastlane_core/lib/fastlane_core/helper.rb +7 -1
  51. data/frameit/lib/frameit/editor.rb +3 -0
  52. data/gym/lib/gym/generators/build_command_generator.rb +1 -0
  53. data/gym/lib/gym/runner.rb +38 -19
  54. data/match/lib/match/options.rb +8 -0
  55. data/match/lib/match/runner.rb +1 -0
  56. data/match/lib/match/storage/git_storage.rb +7 -2
  57. data/pilot/lib/pilot/.manager.rb.swp +0 -0
  58. data/pilot/lib/pilot/build_manager.rb +46 -12
  59. data/pilot/lib/pilot/options.rb +3 -1
  60. data/scan/lib/scan/detect_values.rb +6 -1
  61. data/scan/lib/scan/manager.rb +18 -1
  62. data/scan/lib/scan/options.rb +17 -0
  63. data/scan/lib/scan/runner.rb +6 -0
  64. data/scan/lib/scan/slack_poster.rb +1 -1
  65. data/scan/lib/scan/test_command_generator.rb +1 -1
  66. data/screengrab/lib/screengrab/module.rb +2 -0
  67. data/screengrab/lib/screengrab/options.rb +24 -11
  68. data/screengrab/lib/screengrab/runner.rb +79 -42
  69. data/spaceship/lib/spaceship/client.rb +9 -4
  70. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  71. data/spaceship/lib/spaceship/connect_api/.DS_Store +0 -0
  72. data/spaceship/lib/spaceship/connect_api/models/app.rb +11 -0
  73. data/spaceship/lib/spaceship/connect_api/models/beta_feedback.rb +71 -0
  74. data/spaceship/lib/spaceship/connect_api/models/beta_screenshot.rb +18 -0
  75. data/spaceship/lib/spaceship/connect_api/models/build.rb +5 -0
  76. data/spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb +5 -0
  77. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +9 -0
  78. data/spaceship/lib/spaceship/portal/.certificate.rb.swp +0 -0
  79. data/spaceship/lib/spaceship/tunes/iap.rb +11 -11
  80. data/spaceship/lib/spaceship/tunes/iap_detail.rb +7 -3
  81. data/spaceship/lib/spaceship/tunes/iap_families.rb +12 -1
  82. data/spaceship/lib/spaceship/tunes/iap_family_details.rb +26 -17
  83. data/spaceship/lib/spaceship/tunes/tunes_client.rb +4 -7
  84. data/supply/lib/supply/client.rb +27 -0
  85. data/supply/lib/supply/options.rb +8 -2
  86. data/supply/lib/supply/uploader.rb +82 -33
  87. metadata +49 -26
  88. data/supply/lib/supply/.options.rb.swp +0 -0
  89. data/supply/lib/supply/.uploader.rb.swp +0 -0
@@ -563,10 +563,15 @@ module Spaceship
563
563
  #####################################################
564
564
 
565
565
  def load_session_from_file
566
- if File.exist?(persistent_cookie_path)
567
- puts("Loading session from '#{persistent_cookie_path}'") if Spaceship::Globals.verbose?
568
- @cookie.load(persistent_cookie_path)
569
- return true
566
+ begin
567
+ if File.exist?(persistent_cookie_path)
568
+ puts("Loading session from '#{persistent_cookie_path}'") if Spaceship::Globals.verbose?
569
+ @cookie.load(persistent_cookie_path)
570
+ return true
571
+ end
572
+ rescue => ex
573
+ puts(ex.to_s)
574
+ puts("Continuing with normal login.")
570
575
  end
571
576
  return false
572
577
  end
@@ -20,7 +20,9 @@ require 'spaceship/connect_api/models/beta_build_localization'
20
20
  require 'spaceship/connect_api/models/beta_build_metric'
21
21
  require 'spaceship/connect_api/models/beta_app_review_detail'
22
22
  require 'spaceship/connect_api/models/beta_app_review_submission'
23
+ require 'spaceship/connect_api/models/beta_feedback'
23
24
  require 'spaceship/connect_api/models/beta_group'
25
+ require 'spaceship/connect_api/models/beta_screenshot'
24
26
  require 'spaceship/connect_api/models/beta_tester'
25
27
  require 'spaceship/connect_api/models/beta_tester_metric'
26
28
  require 'spaceship/connect_api/models/build'
@@ -45,6 +45,17 @@ module Spaceship
45
45
  return Spaceship::ConnectAPI.get_app(app_id: app_id, includes: includes).first
46
46
  end
47
47
 
48
+ #
49
+ # Beta Feedback
50
+
51
+ def get_beta_feedback(filter: {}, includes: "tester,build,screenshots", limit: nil, sort: nil)
52
+ filter ||= {}
53
+ filter["build.app"] = id
54
+
55
+ resps = Spaceship::ConnectAPI.get_beta_feedback(filter: filter, includes: includes, limit: limit, sort: sort).all_pages
56
+ return resps.flat_map(&:to_models)
57
+ end
58
+
48
59
  #
49
60
  # Beta Testers
50
61
  #
@@ -0,0 +1,71 @@
1
+ require_relative '../model'
2
+ module Spaceship
3
+ class ConnectAPI
4
+ class BetaFeedback
5
+ include Spaceship::ConnectAPI::Model
6
+
7
+ attr_accessor :timestamp
8
+ attr_accessor :comment
9
+ attr_accessor :email_address
10
+ attr_accessor :device_model
11
+ attr_accessor :os_version
12
+ attr_accessor :bookmarked
13
+ attr_accessor :locale
14
+ attr_accessor :carrier
15
+ attr_accessor :timezone
16
+ attr_accessor :architecture
17
+ attr_accessor :connection_status
18
+ attr_accessor :paired_apple_watch
19
+ attr_accessor :app_up_time_millis
20
+ attr_accessor :available_disk_bytes
21
+ attr_accessor :total_disk_bytes
22
+ attr_accessor :network_type
23
+ attr_accessor :battery_percentage
24
+ attr_accessor :screen_width
25
+ attr_accessor :screen_height
26
+
27
+ attr_accessor :build
28
+ attr_accessor :tester
29
+ attr_accessor :screenshots
30
+
31
+ attr_mapping({
32
+ "timestamp" => "timestamp",
33
+ "comment" => "comment",
34
+ "emailAddress" => "email_address",
35
+ "contactEmail" => "contact_email",
36
+ "deviceModel" => "device_model",
37
+ "osVersion" => "os_version",
38
+ "bookmarked" => "bookmarked",
39
+ "locale" => "locale",
40
+ "carrier" => "carrier",
41
+ "timezone" => "timezone",
42
+ "architecture" => "architecture",
43
+ "connectionStatus" => "connection_status",
44
+ "pairedAppleWatch" => "paired_apple_watch",
45
+ "appUpTimeMillis" => "app_up_time_millis",
46
+ "availableDiskBytes" => "available_disk_bytes",
47
+ "totalDiskBytes" => "total_disk_bytes",
48
+ "networkType" => "network_type",
49
+ "batteryPercentage" => "battery_percentage",
50
+ "screenWidth" => "screen_width",
51
+ "screenHeight" => "screen_height",
52
+
53
+ "build" => "build",
54
+ "tester" => "tester",
55
+ "screenshots" => "screenshots"
56
+ })
57
+
58
+ def self.type
59
+ return "betaFeedbacks"
60
+ end
61
+
62
+ #
63
+ # API
64
+ #
65
+
66
+ def self.all(filter: {}, includes: "tester,build,screenshots", limit: nil, sort: nil)
67
+ return Spaceship::ConnectAPI.get_beta_feedback(filter: filter, includes: includes, limit: limit, sort: sort)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,18 @@
1
+ require_relative '../model'
2
+ module Spaceship
3
+ class ConnectAPI
4
+ class BetaScreenshot
5
+ include Spaceship::ConnectAPI::Model
6
+
7
+ attr_accessor :image_assets
8
+
9
+ attr_mapping({
10
+ "imageAssets" => "image_assets"
11
+ })
12
+
13
+ def self.type
14
+ return "betaScreenshots"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -78,6 +78,11 @@ module Spaceship
78
78
  return processing_state != ProcessingState::PROCESSING
79
79
  end
80
80
 
81
+ def ready_for_internal_testing?
82
+ raise "No build_beta_detail included" unless build_beta_detail
83
+ return build_beta_detail.ready_for_internal_testing?
84
+ end
85
+
81
86
  def ready_for_beta_submission?
82
87
  raise "No build_beta_detail included" unless build_beta_detail
83
88
  return build_beta_detail.ready_for_beta_submission?
@@ -10,6 +10,7 @@ module Spaceship
10
10
  attr_accessor :external_build_state
11
11
 
12
12
  module InternalState
13
+ PROCESSING = "PROCESSING"
13
14
  PROCESSING_EXCEPTION = "PROCESSING_EXCEPTION"
14
15
  MISSING_EXPORT_COMPLIANCE = "MISSING_EXPORT_COMPLIANCE"
15
16
  READY_FOR_BETA_TESTING = "READY_FOR_BETA_TESTING"
@@ -47,6 +48,10 @@ module Spaceship
47
48
  #
48
49
  # Helpers
49
50
  #
51
+ #
52
+ def ready_for_internal_testing?
53
+ return internal_build_state == InternalState::READY_FOR_BETA_TESTING
54
+ end
50
55
 
51
56
  def ready_for_beta_submission?
52
57
  return external_build_state == ExternalState::READY_FOR_BETA_SUBMISSION
@@ -317,6 +317,15 @@ module Spaceship
317
317
  params = Client.instance.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
318
318
  Client.instance.get("preReleaseVersions", params)
319
319
  end
320
+
321
+ #
322
+ # betaFeedbacks (private API as of end 2019)
323
+ #
324
+
325
+ def get_beta_feedback(filter: {}, includes: nil, limit: nil, sort: nil)
326
+ params = Client.instance.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
327
+ Client.instance.get("betaFeedbacks", params)
328
+ end
320
329
  end
321
330
  end
322
331
  end
@@ -105,17 +105,6 @@ module Spaceship
105
105
  end
106
106
  end
107
107
 
108
- # find a specific product
109
- # @param product_id (String) Product Id
110
- def find(product_id)
111
- all.each do |product|
112
- if product.product_id == product_id
113
- return product
114
- end
115
- end
116
- return nil
117
- end
118
-
119
108
  # return all available In-App-Purchase's of current app
120
109
  # this is not paged inside iTC-API so if you have a lot if IAP's (2k+)
121
110
  # it might take some time to load, same as it takes when you load the list via App Store Connect
@@ -132,6 +121,17 @@ module Spaceship
132
121
  return_iaps
133
122
  end
134
123
 
124
+ # find a specific product
125
+ # @param product_id (String) Product Id
126
+ def find(product_id)
127
+ all.each do |product|
128
+ if product.product_id == product_id
129
+ return product
130
+ end
131
+ end
132
+ return nil
133
+ end
134
+
135
135
  private
136
136
 
137
137
  def find_product_with_retries(product_id, max_tries)
@@ -80,7 +80,9 @@ module Spaceship
80
80
  language = localized_version["value"]["localeCode"]
81
81
  parsed_versions[language.to_sym] = {
82
82
  name: localized_version["value"]["name"]["value"],
83
- description: localized_version["value"]["description"]["value"]
83
+ description: localized_version["value"]["description"]["value"],
84
+ id: localized_version["value"]["id"],
85
+ status: localized_version["value"]["status"]
84
86
  }
85
87
  end
86
88
  return parsed_versions
@@ -98,7 +100,8 @@ module Spaceship
98
100
  "value" => {
99
101
  "name" => { "value" => current_version[:name] },
100
102
  "description" => { "value" => current_version[:description] },
101
- "localeCode" => language.to_s
103
+ "localeCode" => language.to_s,
104
+ "id" => current_version[:id]
102
105
  }
103
106
  }
104
107
  end
@@ -167,7 +170,8 @@ module Spaceship
167
170
  "value" => {
168
171
  "description" => { "value" => value[:description] },
169
172
  "name" => { "value" => value[:name] },
170
- "localeCode" => language.to_s
173
+ "localeCode" => language.to_s,
174
+ "id" => value[:id]
171
175
  }
172
176
  }
173
177
  end
@@ -40,7 +40,7 @@ module Spaceship
40
40
  client.create_iap_family(app_id: self.application.apple_id, name: name, product_id: product_id, reference_name: reference_name, versions: versions_array)
41
41
  end
42
42
 
43
- # returns a list of all families
43
+ # returns a list of all available subscription groups/families of the current In-App-Purchase
44
44
  def all
45
45
  r = client.iap_families(app_id: self.application.apple_id)
46
46
  return_families = []
@@ -52,6 +52,17 @@ module Spaceship
52
52
  end
53
53
  return_families
54
54
  end
55
+
56
+ # find a specific family
57
+ # @param family_id (String) Family Id
58
+ def find(family_id)
59
+ all.each do |family|
60
+ if family.family_id == family_id
61
+ return family
62
+ end
63
+ end
64
+ return nil
65
+ end
55
66
  end
56
67
  end
57
68
  end
@@ -18,13 +18,34 @@ module Spaceship
18
18
  # @return (Intger) amount of linked in-app purchases of this family (read-only)
19
19
  attr_accessor :iap_count
20
20
 
21
+ # @return (Array) of all in-app purchase family details
22
+ attr_accessor :family_details
23
+
21
24
  attr_mapping({
22
25
  'id' => :family_id,
23
26
  'name.value' => :name,
24
27
  'activeAddOns' => :linked_iaps,
25
- 'totalActiveAddOns' => :iap_count
28
+ 'totalActiveAddOns' => :iap_count,
29
+ 'details.value' => :family_details
26
30
  })
27
31
 
32
+ # @return (Hash) localized names
33
+ def versions
34
+ parsed_versions = {}
35
+ raw_versions = raw_data["details"]["value"]
36
+ raw_versions.each do |version|
37
+ language = version["value"]["localeCode"]["value"]
38
+ parsed_versions[language.to_sym] = {
39
+ subscription_name: version["value"]["subscriptionName"]["value"],
40
+ name: version["value"]["name"]["value"],
41
+ id: version["value"]["id"],
42
+ status: version["value"]["status"]
43
+ }
44
+ end
45
+ return parsed_versions
46
+ end
47
+
48
+ # transforms user-set versions to iTC ones
28
49
  def versions=(value = {})
29
50
  if value.kind_of?(Array)
30
51
  # input that comes from iTC api
@@ -36,7 +57,8 @@ module Spaceship
36
57
  "value" => {
37
58
  "subscriptionName" => { "value" => current_version[:subscription_name] },
38
59
  "name" => { "value" => current_version[:name] },
39
- "localeCode" => { "value" => language }
60
+ "localeCode" => { "value" => language },
61
+ "id" => current_version[:id]
40
62
  }
41
63
  }
42
64
  end
@@ -44,20 +66,6 @@ module Spaceship
44
66
  raw_data.set(["details"], { "value" => new_versions })
45
67
  end
46
68
 
47
- # @return (Hash) localized names
48
- def versions
49
- parsed_versions = {}
50
- raw_versions = raw_data["details"]["value"]
51
- raw_versions.each do |version|
52
- language = version["value"]["localeCode"]["value"]
53
- parsed_versions[language.to_sym] = {
54
- subscription_name: version["value"]["subscriptionName"]["value"],
55
- name: version["value"]["name"]["value"]
56
- }
57
- end
58
- return parsed_versions
59
- end
60
-
61
69
  # modify existing family
62
70
  def save!
63
71
  # Transform localization versions back to original format.
@@ -67,7 +75,8 @@ module Spaceship
67
75
  "value" => {
68
76
  "subscriptionName" => { "value" => value[:subscription_name] },
69
77
  "name" => { "value" => value[:name] },
70
- "localeCode" => { "value" => language_code.to_s }
78
+ "localeCode" => { "value" => language_code.to_s },
79
+ "id" => value[:id]
71
80
  }
72
81
  }
73
82
  end
@@ -400,7 +400,7 @@ module Spaceship
400
400
  rating_url << "sort=REVIEW_SORT_ORDER_MOST_RECENT"
401
401
  rating_url << "&index=#{index}"
402
402
  rating_url << "&storefront=#{storefront}" unless storefront.empty?
403
- rating_url << "&version_id=#{version_id}" unless version_id.empty?
403
+ rating_url << "&versionId=#{version_id}" unless version_id.empty?
404
404
 
405
405
  r = request(:get, rating_url)
406
406
  all_reviews.concat(parse_response(r, 'data')['reviews'])
@@ -627,7 +627,7 @@ module Spaceship
627
627
  handle_itc_response(r.body)
628
628
  end
629
629
 
630
- def transform_to_raw_pricing_intervals(app_id = nil, purchase_id = nil, pricing_intervals = nil, subscription_price_target = nil)
630
+ def transform_to_raw_pricing_intervals(app_id = nil, purchase_id = nil, pricing_intervals = 5, subscription_price_target = nil)
631
631
  intervals_array = []
632
632
  if pricing_intervals
633
633
  intervals_array = pricing_intervals.map do |interval|
@@ -784,11 +784,8 @@ module Spaceship
784
784
  end
785
785
 
786
786
  def available_languages
787
- r = request(:get, "ra/apps/storePreview/regionCountryLanguage")
788
- response = parse_response(r, 'data')
789
- response.flat_map { |region| region["storeFronts"] }
790
- .flat_map { |storefront| storefront["supportedLocaleCodes"] }
791
- .uniq
787
+ r = request(:get, "ra/ref")
788
+ parse_response(r, 'data')['detailLocales']
792
789
  end
793
790
 
794
791
  #####################################################
@@ -310,6 +310,19 @@ module Supply
310
310
  return result_upload.version_code
311
311
  end
312
312
 
313
+ def upload_apk_to_internal_app_sharing(package_name, path_to_apk)
314
+ # NOTE: This Google API is a little different. It doesn't require an active edit.
315
+ result_upload = call_google_api do
316
+ client.uploadapk_internalappsharingartifact(
317
+ package_name,
318
+ upload_source: path_to_apk,
319
+ content_type: "application/octet-stream"
320
+ )
321
+ end
322
+
323
+ return result_upload.download_url
324
+ end
325
+
313
326
  def upload_mapping(path_to_mapping, apk_version_code)
314
327
  ensure_active_edit!
315
328
 
@@ -340,11 +353,25 @@ module Supply
340
353
  return result_upload.version_code
341
354
  end
342
355
 
356
+ def upload_bundle_to_internal_app_sharing(package_name, path_to_aab)
357
+ # NOTE: This Google API is a little different. It doesn't require an active edit.
358
+ result_upload = call_google_api do
359
+ client.uploadbundle_internalappsharingartifact(
360
+ package_name,
361
+ upload_source: path_to_aab,
362
+ content_type: "application/octet-stream"
363
+ )
364
+ end
365
+
366
+ return result_upload.download_url
367
+ end
368
+
343
369
  # Get a list of all tracks - returns the list
344
370
  def tracks(*tracknames)
345
371
  ensure_active_edit!
346
372
 
347
373
  all_tracks = call_google_api { client.list_edit_tracks(current_package_name, current_edit.id) }.tracks
374
+ all_tracks = [] unless all_tracks
348
375
 
349
376
  if tracknames.length > 0
350
377
  all_tracks = all_tracks.select { |track| tracknames.include?(track.track) }
@@ -43,7 +43,10 @@ module Supply
43
43
  env_name: "SUPPLY_TRACK",
44
44
  description: "The track of the application to use. The default available tracks are: #{Supply::Tracks::DEFAULTS.join(', ')}",
45
45
  default_value: Supply::Tracks::DEFAULT,
46
- type: String),
46
+ type: String,
47
+ verify_block: proc do |value|
48
+ UI.user_error!("'rollout' is no longer a valid track name - please use 'production' instead") if value.casecmp('rollout').zero?
49
+ end),
47
50
  FastlaneCore::ConfigItem.new(key: :rollout,
48
51
  short_option: "-r",
49
52
  description: "The percentage of the user fraction when uploading to the rollout track",
@@ -208,7 +211,10 @@ module Supply
208
211
  FastlaneCore::ConfigItem.new(key: :track_promote_to,
209
212
  env_name: "SUPPLY_TRACK_PROMOTE_TO",
210
213
  optional: true,
211
- description: "The track to promote to. The default available tracks are: #{Supply::Tracks::DEFAULTS.join(', ')}"),
214
+ description: "The track to promote to. The default available tracks are: #{Supply::Tracks::DEFAULTS.join(', ')}",
215
+ verify_block: proc do |value|
216
+ UI.user_error!("'rollout' is no longer a valid track name - please use 'production' instead") if value.casecmp('rollout').zero?
217
+ end),
212
218
  FastlaneCore::ConfigItem.new(key: :validate_only,
213
219
  env_name: "SUPPLY_VALIDATE_ONLY",
214
220
  optional: true,