fastlane 2.211.0 → 2.212.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +96 -96
  3. data/deliver/lib/deliver/app_screenshot.rb +1 -0
  4. data/deliver/lib/deliver/runner.rb +2 -6
  5. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +19 -2
  6. data/fastlane/lib/fastlane/actions/pod_lib_lint.rb +1 -1
  7. data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +1 -1
  8. data/fastlane/lib/fastlane/actions/xcodes.rb +17 -2
  9. data/fastlane/lib/fastlane/fast_file.rb +18 -5
  10. data/fastlane/lib/fastlane/features.rb +3 -0
  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/Atomic.swift +1 -1
  16. data/fastlane/swift/ControlCommand.swift +1 -1
  17. data/fastlane/swift/Deliverfile.swift +2 -2
  18. data/fastlane/swift/DeliverfileProtocol.swift +2 -2
  19. data/fastlane/swift/Fastlane.swift +30 -6
  20. data/fastlane/swift/Gymfile.swift +2 -2
  21. data/fastlane/swift/GymfileProtocol.swift +6 -2
  22. data/fastlane/swift/LaneFileProtocol.swift +1 -1
  23. data/fastlane/swift/MainProcess.swift +1 -1
  24. data/fastlane/swift/Matchfile.swift +2 -2
  25. data/fastlane/swift/MatchfileProtocol.swift +3 -3
  26. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  27. data/fastlane/swift/Plugins.swift +1 -1
  28. data/fastlane/swift/Precheckfile.swift +2 -2
  29. data/fastlane/swift/PrecheckfileProtocol.swift +2 -2
  30. data/fastlane/swift/RubyCommand.swift +1 -1
  31. data/fastlane/swift/RubyCommandable.swift +1 -1
  32. data/fastlane/swift/Runner.swift +1 -1
  33. data/fastlane/swift/RunnerArgument.swift +1 -1
  34. data/fastlane/swift/Scanfile.swift +2 -2
  35. data/fastlane/swift/ScanfileProtocol.swift +6 -2
  36. data/fastlane/swift/Screengrabfile.swift +2 -2
  37. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  38. data/fastlane/swift/Snapshotfile.swift +2 -2
  39. data/fastlane/swift/SnapshotfileProtocol.swift +2 -2
  40. data/fastlane/swift/SocketClient.swift +1 -1
  41. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  42. data/fastlane/swift/SocketResponse.swift +1 -1
  43. data/fastlane/swift/formatting/Brewfile.lock.json +26 -18
  44. data/fastlane/swift/main.swift +1 -1
  45. data/fastlane_core/lib/fastlane_core/cert_checker.rb +9 -2
  46. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +4 -2
  47. data/gym/lib/gym/generators/build_command_generator.rb +1 -0
  48. data/gym/lib/gym/options.rb +7 -0
  49. data/match/lib/match/importer.rb +4 -0
  50. data/match/lib/match/module.rb +1 -1
  51. data/scan/lib/scan/options.rb +5 -0
  52. data/scan/lib/scan/test_command_generator.rb +6 -1
  53. data/spaceship/lib/spaceship/client.rb +23 -0
  54. data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +5 -0
  55. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +17 -0
  56. data/spaceship/lib/spaceship/connect_api/models/build_bundle.rb +9 -0
  57. data/spaceship/lib/spaceship/connect_api/models/build_bundle_file_sizes.rb +34 -0
  58. data/spaceship/lib/spaceship/connect_api/models/device.rb +44 -4
  59. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +19 -0
  60. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +9 -0
  61. data/spaceship/lib/spaceship/connect_api.rb +1 -0
  62. data/spaceship/lib/spaceship/errors.rb +34 -0
  63. data/spaceship/lib/spaceship/hashcash.rb +52 -0
  64. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +10 -2
  65. data/spaceship/lib/spaceship.rb +1 -0
  66. metadata +24 -22
@@ -1,6 +1,7 @@
1
1
  require 'tempfile'
2
2
  require 'openssl'
3
3
 
4
+ require_relative 'features'
4
5
  require_relative 'helper'
5
6
 
6
7
  # WWDR Intermediate Certificates in https://www.apple.com/certificateauthority/
@@ -155,11 +156,17 @@ module FastlaneCore
155
156
  keychain = wwdr_keychain
156
157
  keychain = "-k #{keychain.shellescape}" unless keychain.empty?
157
158
 
158
- require 'open3'
159
+ # Attempts to fix an issue installing WWDR cert tends to fail on CIs
160
+ # https://github.com/fastlane/fastlane/issues/20960
161
+ curl_extras = ""
162
+ if FastlaneCore::Feature.enabled?('FASTLANE_WWDR_USE_HTTP1_AND_RETRIES')
163
+ curl_extras = "--http1.1 --retry 3 --retry-all-errors "
164
+ end
159
165
 
160
- import_command = "curl -f -o #{filename} #{url} && security import #{filename} #{keychain}"
166
+ import_command = "curl #{curl_extras}-f -o #{filename} #{url} && security import #{filename} #{keychain}"
161
167
  UI.verbose("Installing WWDR Cert: #{import_command}")
162
168
 
169
+ require 'open3'
163
170
  stdout, stderr, status = Open3.capture3(import_command)
164
171
  if FastlaneCore::Globals.verbose?
165
172
  UI.command_output(stdout)
@@ -86,11 +86,13 @@ module FastlaneCore
86
86
 
87
87
  def header(message)
88
88
  format = format_string
89
- if message.length + 8 < TTY::Screen.width - format.length
89
+ # clamp to zero to prevent negative argument error below
90
+ available_width = [0, TTY::Screen.width - format.length].max
91
+ if message.length + 8 < available_width
90
92
  message = "--- #{message} ---"
91
93
  i = message.length
92
94
  else
93
- i = TTY::Screen.width - format.length
95
+ i = available_width
94
96
  end
95
97
  success("-" * i)
96
98
  success(message)
@@ -39,6 +39,7 @@ module Gym
39
39
  options << "-destination '#{config[:destination]}'" if config[:destination]
40
40
  options << "-archivePath #{archive_path.shellescape}" unless config[:skip_archive]
41
41
  options << "-resultBundlePath '#{result_bundle_path}'" if config[:result_bundle]
42
+ options << "-showBuildTimingSummary" if config[:build_timing_summary]
42
43
  if config[:use_system_scm] && !options.include?("-scmProvider system")
43
44
  options << "-scmProvider system"
44
45
  end
@@ -239,6 +239,13 @@ module Gym
239
239
  default_value: Fastlane::Helper::XcodebuildFormatterHelper.xcbeautify_installed? ? 'xcbeautify' : 'xcpretty',
240
240
  default_value_dynamic: true),
241
241
 
242
+ FastlaneCore::ConfigItem.new(key: :build_timing_summary,
243
+ env_name: "GYM_BUILD_TIMING_SUMMARY",
244
+ description: "Create a build timing summary",
245
+ type: Boolean,
246
+ default_value: false,
247
+ optional: true),
248
+
242
249
  # xcpretty
243
250
  FastlaneCore::ConfigItem.new(key: :disable_xcpretty,
244
251
  env_name: "DISABLE_XCPRETTY",
@@ -80,6 +80,10 @@ module Match
80
80
  certificate_type = [
81
81
  Spaceship::ConnectAPI::Certificate::CertificateType::MAC_INSTALLER_DISTRIBUTION
82
82
  ].join(',')
83
+ when :developer_id_installer
84
+ certificate_type = [
85
+ Spaceship::ConnectAPI::Certificate::CertificateType::DEVELOPER_ID_INSTALLER
86
+ ].join(',')
83
87
  else
84
88
  UI.user_error!("Cert type '#{cert_type}' is not supported")
85
89
  end
@@ -11,7 +11,7 @@ module Match
11
11
  DESCRIPTION = "Easily sync your certificates and profiles across your team"
12
12
 
13
13
  def self.environments
14
- return %w(appstore adhoc development enterprise developer_id mac_installer_distribution)
14
+ return %w(appstore adhoc development enterprise developer_id mac_installer_distribution developer_id_installer)
15
15
  end
16
16
 
17
17
  def self.storage_modes
@@ -315,6 +315,11 @@ module Scan
315
315
  env_name: "SCAN_OUTPUT_XCTESTRUN",
316
316
  description: "Should provide additional copy of .xctestrun file (settings.xctestrun) and place in output path?",
317
317
  default_value: false),
318
+ FastlaneCore::ConfigItem.new(key: :result_bundle_path,
319
+ env_name: "SCAN_RESULT_BUNDLE_PATH",
320
+ description: "Custom path for the result bundle, overrides result_bundle",
321
+ type: String,
322
+ optional: true),
318
323
  FastlaneCore::ConfigItem.new(key: :result_bundle,
319
324
  short_option: "-z",
320
325
  env_name: "SCAN_RESULT_BUNDLE",
@@ -53,7 +53,12 @@ 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(true)}'" if config[:result_bundle]
56
+ if config[:result_bundle_path]
57
+ options << "-resultBundlePath '#{config[:result_bundle_path].shellescape}'"
58
+ Scan.cache[:result_bundle_path] = config[:result_bundle_path]
59
+ elsif config[:result_bundle]
60
+ options << "-resultBundlePath '#{result_bundle_path(true)}'"
61
+ end
57
62
  if FastlaneCore::Helper.xcode_at_least?(10)
58
63
  options << "-parallel-testing-enabled #{config[:parallel_testing] ? 'YES' : 'NO'}" unless config[:parallel_testing].nil?
59
64
  options << "-parallel-testing-worker-count #{config[:concurrent_workers]}" if config[:concurrent_workers]
@@ -18,6 +18,7 @@ require_relative 'tunes/errors'
18
18
  require_relative 'globals'
19
19
  require_relative 'provider'
20
20
  require_relative 'stats_middleware'
21
+ require_relative 'hashcash'
21
22
 
22
23
  Faraday::Utils.default_params_encoder = Faraday::FlatParamsEncoder
23
24
 
@@ -490,6 +491,12 @@ module Spaceship
490
491
  modified_cookie.gsub!(unescaped_important_cookie, escaped_important_cookie)
491
492
  end
492
493
 
494
+ # Fixes issue https://github.com/fastlane/fastlane/issues/21071
495
+ # On 2023-02-23, Apple added a custom implementation
496
+ # of hashcash to their auth flow
497
+ # hashcash = nil
498
+ hashcash = self.fetch_hashcash
499
+
493
500
  response = request(:post) do |req|
494
501
  req.url("https://idmsa.apple.com/appleauth/auth/signin")
495
502
  req.body = data.to_json
@@ -498,6 +505,7 @@ module Spaceship
498
505
  req.headers['X-Apple-Widget-Key'] = self.itc_service_key
499
506
  req.headers['Accept'] = 'application/json, text/javascript'
500
507
  req.headers["Cookie"] = modified_cookie if modified_cookie
508
+ req.headers["X-Apple-HC"] = hashcash if hashcash
501
509
  end
502
510
  rescue UnauthorizedAccessError
503
511
  raise InvalidUserCredentialsError.new, "Invalid username and password combination. Used '#{user}' as the username."
@@ -545,6 +553,21 @@ module Spaceship
545
553
  end
546
554
  # rubocop:enable Metrics/PerceivedComplexity
547
555
 
556
+ def fetch_hashcash
557
+ response = request(:get, "https://idmsa.apple.com/appleauth/auth/signin?widgetKey=#{self.itc_service_key}")
558
+ headers = response.headers
559
+
560
+ bits = headers["X-Apple-HC-Bits"]
561
+ challenge = headers["X-Apple-HC-Challenge"]
562
+
563
+ if bits.nil? || challenge.nil?
564
+ puts("Unable to find 'X-Apple-HC-Bits' and 'X-Apple-HC-Challenge' to make hashcash")
565
+ return nil
566
+ end
567
+
568
+ return Spaceship::Hashcash.make(bits: bits, challenge: challenge)
569
+ end
570
+
548
571
  # Get the `itctx` from the new (22nd May 2017) API endpoint "olympus"
549
572
  # Update (29th March 2019) olympus migrates to new appstoreconnect API
550
573
  def fetch_olympus_session
@@ -1,4 +1,5 @@
1
1
  require_relative '../model'
2
+ require_relative '../../errors'
2
3
  module Spaceship
3
4
  class ConnectAPI
4
5
  class AppInfoLocalization
@@ -32,11 +33,15 @@ module Spaceship
32
33
  client ||= Spaceship::ConnectAPI
33
34
  attributes = reverse_attr_mapping(attributes)
34
35
  client.patch_app_info_localization(app_info_localization_id: id, attributes: attributes)
36
+ rescue
37
+ raise Spaceship::AppStoreLocalizationError, @locale
35
38
  end
36
39
 
37
40
  def delete!(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
38
41
  client ||= Spaceship::ConnectAPI
39
42
  client.delete_app_info_localization(app_info_localization_id: id)
43
+ rescue
44
+ raise Spaceship::AppStoreLocalizationError, @locale
40
45
  end
41
46
  end
42
47
  end
@@ -1,6 +1,7 @@
1
1
  require_relative '../model'
2
2
  require_relative './app_preview_set'
3
3
  require_relative './app_screenshot_set'
4
+ require_relative '../../errors'
4
5
 
5
6
  module Spaceship
6
7
  class ConnectAPI
@@ -43,23 +44,31 @@ module Spaceship
43
44
  client ||= Spaceship::ConnectAPI
44
45
  resp = client.get_app_store_version_localization(app_store_version_localization_id: app_store_version_localization_id, filter: filter, includes: includes, limit: limit, sort: sort)
45
46
  return resp.to_models
47
+ rescue
48
+ raise Spaceship::AppStoreLocalizationError, @locale
46
49
  end
47
50
 
48
51
  def self.all(client: nil, app_store_version_id: nil, filter: {}, includes: nil, limit: nil, sort: nil)
49
52
  client ||= Spaceship::ConnectAPI
50
53
  resp = client.get_app_store_version_localizations(app_store_version_id: app_store_version_id, filter: filter, includes: includes, limit: limit, sort: sort)
51
54
  return resp.to_models
55
+ rescue
56
+ raise Spaceship::AppStoreLocalizationError, @locale
52
57
  end
53
58
 
54
59
  def update(client: nil, attributes: nil)
55
60
  client ||= Spaceship::ConnectAPI
56
61
  attributes = reverse_attr_mapping(attributes)
57
62
  client.patch_app_store_version_localization(app_store_version_localization_id: id, attributes: attributes)
63
+ rescue
64
+ raise Spaceship::AppStoreLocalizationError, @locale
58
65
  end
59
66
 
60
67
  def delete!(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
61
68
  client ||= Spaceship::ConnectAPI
62
69
  client.delete_app_store_version_localization(app_store_version_localization_id: id)
70
+ rescue
71
+ raise Spaceship::AppStoreLocalizationError, @locale
63
72
  end
64
73
 
65
74
  #
@@ -71,12 +80,16 @@ module Spaceship
71
80
  filter ||= {}
72
81
  filter["appStoreVersionLocalization"] = id
73
82
  return Spaceship::ConnectAPI::AppPreviewSet.all(client: client, filter: filter, includes: includes, limit: limit, sort: sort)
83
+ rescue
84
+ raise Spaceship::AppStoreAppPreviewError, @locale
74
85
  end
75
86
 
76
87
  def create_app_preview_set(client: nil, attributes: nil)
77
88
  client ||= Spaceship::ConnectAPI
78
89
  resp = client.post_app_preview_set(app_store_version_localization_id: id, attributes: attributes)
79
90
  return resp.to_models.first
91
+ rescue
92
+ raise Spaceship::AppStoreAppPreviewError, @locale
80
93
  end
81
94
 
82
95
  #
@@ -86,12 +99,16 @@ module Spaceship
86
99
  def get_app_screenshot_sets(client: nil, filter: {}, includes: "appScreenshots", limit: nil, sort: nil)
87
100
  client ||= Spaceship::ConnectAPI
88
101
  return Spaceship::ConnectAPI::AppScreenshotSet.all(client: client, app_store_version_localization_id: id, filter: filter, includes: includes, limit: limit, sort: sort)
102
+ rescue
103
+ raise Spaceship::AppStoreScreenshotError, @locale
89
104
  end
90
105
 
91
106
  def create_app_screenshot_set(client: nil, attributes: nil)
92
107
  client ||= Spaceship::ConnectAPI
93
108
  resp = client.post_app_screenshot_set(app_store_version_localization_id: id, attributes: attributes)
94
109
  return resp.to_models.first
110
+ rescue
111
+ raise Spaceship::AppStoreScreenshotError, @locale
95
112
  end
96
113
  end
97
114
  end
@@ -1,4 +1,5 @@
1
1
  require_relative '../model'
2
+ require_relative './build_bundle_file_sizes'
2
3
  module Spaceship
3
4
  class ConnectAPI
4
5
  class BuildBundle
@@ -54,6 +55,14 @@ module Spaceship
54
55
  def self.type
55
56
  return "buildBundles"
56
57
  end
58
+
59
+ #
60
+ # API
61
+ #
62
+
63
+ def build_bundle_file_sizes(client: nil)
64
+ @build_bundle_file_sizes ||= BuildBundleFileSizes.all(client: client, build_bundle_id: id)
65
+ end
57
66
  end
58
67
  end
59
68
  end
@@ -0,0 +1,34 @@
1
+ require_relative '../model'
2
+ module Spaceship
3
+ class ConnectAPI
4
+ class BuildBundleFileSizes
5
+ include Spaceship::ConnectAPI::Model
6
+
7
+ attr_accessor :device_model
8
+ attr_accessor :os_version
9
+ attr_accessor :download_bytes
10
+ attr_accessor :install_bytes
11
+
12
+ attr_mapping({
13
+ "deviceModel" => "device_model",
14
+ "osVersion" => "os_version",
15
+ "downloadBytes" => "download_bytes",
16
+ "installBytes" => "install_bytes"
17
+ })
18
+
19
+ def self.type
20
+ return "buildBundleFileSizes"
21
+ end
22
+
23
+ #
24
+ # API
25
+ #
26
+
27
+ def self.all(client: nil, build_bundle_id: nil, limit: 30)
28
+ client ||= Spaceship::ConnectAPI
29
+ resps = client.get_build_bundles_build_bundle_file_sizes(build_bundle_id: build_bundle_id).all_pages
30
+ resps.flat_map(&:to_models)
31
+ end
32
+ end
33
+ end
34
+ end
@@ -61,7 +61,7 @@ module Spaceship
61
61
  # @param platform [String] The platform of the device.
62
62
  # @param include_disabled [Bool] Whether to include disable devices. false by default.
63
63
  # @return (Device) Find a device based on the UDID of the device. nil if no device was found.
64
- def self.find_by_udid(device_udid, client: nil, platform: nil, include_disabled: false)
64
+ def self.find_by_udid(device_udid, client: nil, include_disabled: false)
65
65
  self.all(client: client).find do |device|
66
66
  device.udid.casecmp(device_udid) == 0 && (include_disabled ? true : device.enabled?)
67
67
  end
@@ -70,10 +70,9 @@ module Spaceship
70
70
  # @param client [ConnectAPI] ConnectAPI client.
71
71
  # @param name [String] The name to be assigned to the device, if it needs to be created.
72
72
  # @param platform [String] The platform of the device.
73
- # @param include_disabled [Bool] Whether to include disable devices. false by default.
74
73
  # @return (Device) Find a device based on the UDID of the device. If no device was found, nil if no device was found.
75
- def self.find_or_create(device_udid, client: nil, name: nil, platform: nil, include_disabled: false)
76
- existing = self.find_by_udid(device_udid, client: client, platform: platform)
74
+ def self.find_or_create(device_udid, client: nil, name: nil, platform: nil)
75
+ existing = self.find_by_udid(device_udid, client: client)
77
76
  return existing if existing
78
77
  return self.create(client: client, name: name, platform: platform, udid: device_udid)
79
78
  end
@@ -88,6 +87,47 @@ module Spaceship
88
87
  resp = client.post_device(name: name, platform: platform, udid: udid)
89
88
  return resp.to_models.first
90
89
  end
90
+
91
+ # @param device_udid [String] Device Provisioning UDID that needs to be modified.
92
+ # @param client [ConnectAPI] ConnectAPI client.
93
+ # @param enabled [Boolean] New enabled value. true - if device must be enabled, `false` - to disable device. nil if no status change needed.
94
+ # @param new_name [String] A new name for the device. nil if no name change needed.
95
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
96
+ def self.modify(device_udid, client: nil, enabled: nil, new_name: nil)
97
+ client ||= Spaceship::ConnectAPI
98
+ existing = self.find_by_udid(device_udid, client: client, include_disabled: true)
99
+ return nil if existing.nil?
100
+
101
+ enabled = existing.enabled? if enabled.nil?
102
+ new_name ||= existing.name
103
+ return existing if existing.name == new_name && existing.enabled? == enabled
104
+ new_status = enabled ? Status::ENABLED : Status::DISABLED
105
+
106
+ resp = client.patch_device(id: existing.id, new_name: new_name, status: new_status)
107
+ return resp.to_models.first
108
+ end
109
+
110
+ # @param device_udid [String] Device Provisioning UDID that needs to be enabled.
111
+ # @param client [ConnectAPI] ConnectAPI client.
112
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
113
+ def self.enable(device_udid, client: nil)
114
+ self.modify(device_udid, client: client, enabled: true)
115
+ end
116
+
117
+ # @param device_udid [String] Device Provisioning UDID that needs to be disabled.
118
+ # @param client [ConnectAPI] ConnectAPI client.
119
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
120
+ def self.disable(device_udid, client: nil)
121
+ self.modify(device_udid, client: client, enabled: false)
122
+ end
123
+
124
+ # @param device_udid [String] Device Provisioning UDID that needs to be renamed.
125
+ # @param new_name [String] A new name for the device.
126
+ # @param client [ConnectAPI] ConnectAPI client.
127
+ # @return (Device) Modified device based on the UDID of the device. nil if no device was found.
128
+ def self.rename(device_udid, new_name, client: nil)
129
+ self.modify(device_udid, client: client, new_name: new_name)
130
+ end
91
131
  end
92
132
  end
93
133
  end
@@ -190,6 +190,25 @@ module Spaceship
190
190
  provisioning_request_client.post("devices", body)
191
191
  end
192
192
 
193
+ def patch_device(id: nil, status: nil, new_name: nil)
194
+ raise "Device id is nil" if id.nil?
195
+
196
+ attributes = {
197
+ name: new_name,
198
+ status: status
199
+ }
200
+
201
+ body = {
202
+ data: {
203
+ attributes: attributes,
204
+ id: id,
205
+ type: "devices"
206
+ }
207
+ }
208
+
209
+ provisioning_request_client.patch("devices/#{id}", body)
210
+ end
211
+
193
212
  #
194
213
  # profiles
195
214
  #
@@ -412,6 +412,15 @@ module Spaceship
412
412
  test_flight_request_client.get("betaTesterMetrics", params)
413
413
  end
414
414
 
415
+ #
416
+ # buildBundles
417
+ #
418
+
419
+ def get_build_bundles_build_bundle_file_sizes(build_bundle_id:, limit: nil)
420
+ params = test_flight_request_client.build_params(filter: nil, includes: nil, limit: limit, sort: nil, cursor: nil)
421
+ test_flight_request_client.get("buildBundles/#{build_bundle_id}/buildBundleFileSizes", params)
422
+ end
423
+
415
424
  #
416
425
  # builds
417
426
  #
@@ -33,6 +33,7 @@ require 'spaceship/connect_api/models/build'
33
33
  require 'spaceship/connect_api/models/build_delivery'
34
34
  require 'spaceship/connect_api/models/build_beta_detail'
35
35
  require 'spaceship/connect_api/models/build_bundle'
36
+ require 'spaceship/connect_api/models/build_bundle_file_sizes'
36
37
  require 'spaceship/connect_api/models/custom_app_organization'
37
38
  require 'spaceship/connect_api/models/custom_app_user'
38
39
  require 'spaceship/connect_api/models/pre_release_version'
@@ -98,4 +98,38 @@ module Spaceship
98
98
 
99
99
  # Raised when 403 is received from portal request
100
100
  class AccessForbiddenError < BasicPreferredInfoError; end
101
+
102
+ # Base class for errors coming from App Store Connect locale changes
103
+ class AppStoreLocaleError < BasicPreferredInfoError
104
+ def initialize(msg)
105
+ @message = (msg ? "An exception occurred for locale: #{msg}." : nil)
106
+ super
107
+ end
108
+
109
+ # no need to search github issues since the error is specific
110
+ def show_github_issues
111
+ false
112
+ end
113
+ end
114
+
115
+ # Raised for localized text errors from App Store Connect
116
+ class AppStoreLocalizationError < AppStoreLocaleError
117
+ def preferred_error_info
118
+ "#{@message} Check the localization requirements here: https://help.apple.com/app-store-connect/en.lproj/static.html#dev354659071"
119
+ end
120
+ end
121
+
122
+ # Raised for localized screenshots errors from App Store Connect
123
+ class AppStoreScreenshotError < AppStoreLocaleError
124
+ def preferred_error_info
125
+ "#{@message} Check the screenshot requirements here: https://help.apple.com/app-store-connect/en.lproj/static.html#devd274dd925"
126
+ end
127
+ end
128
+
129
+ # Raised for localized app preview errors from App Store Connect
130
+ class AppStoreAppPreviewError < AppStoreLocaleError
131
+ def preferred_error_info
132
+ "#{@message} Check the app preview requirements here: https://help.apple.com/app-store-connect/en.lproj/static.html#dev4e413fcb8"
133
+ end
134
+ end
101
135
  end
@@ -0,0 +1,52 @@
1
+ require 'digest'
2
+
3
+ module Spaceship
4
+ module Hashcash
5
+ # This App Store Connect hashcash spec was generously donated by...
6
+ #
7
+ # __ _
8
+ # __ _ _ __ _ __ / _|(_) __ _ _ _ _ __ ___ ___
9
+ # / _` || '_ \ | '_ \ | |_ | | / _` || | | || '__|/ _ \/ __|
10
+ # | (_| || |_) || |_) || _|| || (_| || |_| || | | __/\__ \
11
+ # \__,_|| .__/ | .__/ |_| |_| \__, | \__,_||_| \___||___/
12
+ # |_| |_| |___/
13
+ #
14
+ #
15
+ # <summary>
16
+ # 1:11:20230223170600:4d74fb15eb23f465f1f6fcbf534e5877::6373
17
+ # X-APPLE-HC: 1:11:20230223170600:4d74fb15eb23f465f1f6fcbf534e5877::6373
18
+ # ^ ^ ^ ^ ^
19
+ # | | | | +-- Counter
20
+ # | | | +-- Resource
21
+ # | | +-- Date YYMMDD[hhmm[ss]]
22
+ # | +-- Bits (number of leading zeros)
23
+ # +-- Version
24
+ #
25
+ # We can't use an off-the-shelf Hashcash because Apple's implementation is not quite the same as the spec/convention.
26
+ # 1. The spec calls for a nonce called "Rand" to be inserted between the Ext and Counter. They don't do that at all.
27
+ # 2. The Counter conventionally encoded as base-64 but Apple just uses the decimal number's string representation.
28
+ #
29
+ # Iterate from Counter=0 to Counter=N finding an N that makes the SHA1(X-APPLE-HC) lead with Bits leading zero bits
30
+ #
31
+ #
32
+ # We get the "Resource" from the X-Apple-HC-Challenge header and Bits from X-Apple-HC-Bits
33
+ #
34
+ # </summary>
35
+ def self.make(bits:, challenge:)
36
+ version = 1
37
+ date = Time.now.strftime("%Y%m%d%H%M%S")
38
+
39
+ counter = 0
40
+ loop do
41
+ hc = [
42
+ version, bits, date, challenge, ":#{counter}"
43
+ ].join(":")
44
+
45
+ if Digest::SHA1.digest(hc).unpack1('B*')[0, bits.to_i].to_i == 0
46
+ return hc
47
+ end
48
+ counter += 1
49
+ end
50
+ end
51
+ end
52
+ end
@@ -61,9 +61,17 @@ module Spaceship
61
61
 
62
62
  # Send token to server to get a valid session
63
63
  r = request(:post) do |req|
64
- req.url("https://idmsa.apple.com/appleauth/auth/verify/device/#{device_id}/securitycode")
64
+ req.url("https://idmsa.apple.com/appleauth/auth/verify/phone/securitycode")
65
65
  req.headers['Content-Type'] = 'application/json'
66
- req.body = { "code" => code.to_s }.to_json
66
+ req.body = {
67
+ "phoneNumber": {
68
+ "id": device_id
69
+ },
70
+ "securityCode": {
71
+ "code" => code.to_s
72
+ },
73
+ "mode": "sms"
74
+ }.to_json
67
75
  update_request_headers(req)
68
76
  end
69
77
 
@@ -3,6 +3,7 @@ require_relative 'spaceship/base'
3
3
  require_relative 'spaceship/client'
4
4
  require_relative 'spaceship/provider'
5
5
  require_relative 'spaceship/launcher'
6
+ require_relative 'spaceship/hashcash'
6
7
 
7
8
  # Middleware
8
9
  require_relative 'spaceship/stats_middleware'
metadata CHANGED
@@ -1,39 +1,39 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.211.0
4
+ version: 2.212.1
5
5
  platform: ruby
6
6
  authors:
7
- - Josh Holtz
8
- - Łukasz Grabowski
7
+ - Roger Oba
8
+ - Manish Rathi
9
+ - Helmut Januschka
9
10
  - Stefan Natchev
10
- - Jimmy Dee
11
- - Jérôme Lacoste
12
- - Daniel Jankowski
13
- - Aaron Brager
14
- - Matthew Ellis
11
+ - Joshua Liebowitz
15
12
  - Kohki Miki
16
- - Iulian Onofrei
17
- - Roger Oba
13
+ - Jimmy Dee
14
+ - Jorge Revuelta H
18
15
  - Andrew McBurney
19
- - Luka Mirosevic
20
- - Joshua Liebowitz
16
+ - Satoshi Namai
17
+ - Josh Holtz
18
+ - Fumiya Nakamura
21
19
  - Danielle Tomlinson
22
- - Maksym Grebenets
23
- - Helmut Januschka
24
- - Manu Wallner
20
+ - Łukasz Grabowski
21
+ - Luka Mirosevic
22
+ - Felix Krause
23
+ - Jérôme Lacoste
25
24
  - Max Ott
26
- - Jan Piotrowski
27
- - Fumiya Nakamura
28
- - Satoshi Namai
25
+ - Manu Wallner
26
+ - Aaron Brager
27
+ - Maksym Grebenets
28
+ - Daniel Jankowski
29
29
  - Olivier Halligon
30
- - Felix Krause
31
- - Jorge Revuelta H
32
- - Manish Rathi
30
+ - Iulian Onofrei
31
+ - Matthew Ellis
32
+ - Jan Piotrowski
33
33
  autorequire:
34
34
  bindir: bin
35
35
  cert_chain: []
36
- date: 2022-11-12 00:00:00.000000000 Z
36
+ date: 2023-02-24 00:00:00.000000000 Z
37
37
  dependencies:
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: xcodeproj
@@ -1702,6 +1702,7 @@ files:
1702
1702
  - spaceship/lib/spaceship/connect_api/models/build.rb
1703
1703
  - spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb
1704
1704
  - spaceship/lib/spaceship/connect_api/models/build_bundle.rb
1705
+ - spaceship/lib/spaceship/connect_api/models/build_bundle_file_sizes.rb
1705
1706
  - spaceship/lib/spaceship/connect_api/models/build_delivery.rb
1706
1707
  - spaceship/lib/spaceship/connect_api/models/bundle_id.rb
1707
1708
  - spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb
@@ -1740,6 +1741,7 @@ files:
1740
1741
  - spaceship/lib/spaceship/du/utilities.rb
1741
1742
  - spaceship/lib/spaceship/errors.rb
1742
1743
  - spaceship/lib/spaceship/globals.rb
1744
+ - spaceship/lib/spaceship/hashcash.rb
1743
1745
  - spaceship/lib/spaceship/helper/net_http_generic_request.rb
1744
1746
  - spaceship/lib/spaceship/helper/plist_middleware.rb
1745
1747
  - spaceship/lib/spaceship/helper/rels_middleware.rb