fastlane 2.221.1 → 2.223.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +98 -98
  3. data/deliver/lib/deliver/options.rb +1 -1
  4. data/deliver/lib/deliver/runner.rb +11 -2
  5. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +1 -1
  6. data/fastlane/lib/fastlane/actions/changelog_from_git_commits.rb +7 -3
  7. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +1 -0
  8. data/fastlane/lib/fastlane/actions/download_dsyms.rb +2 -2
  9. data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +16 -1
  10. data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +1 -1
  11. data/fastlane/lib/fastlane/actions/set_changelog.rb +3 -3
  12. data/fastlane/lib/fastlane/actions/slack.rb +9 -2
  13. data/fastlane/lib/fastlane/actions/testfairy.rb +9 -1
  14. data/fastlane/lib/fastlane/fast_file.rb +8 -2
  15. data/fastlane/lib/fastlane/helper/git_helper.rb +4 -2
  16. data/fastlane/lib/fastlane/notification/slack.rb +3 -2
  17. data/fastlane/lib/fastlane/version.rb +1 -1
  18. data/fastlane/swift/Deliverfile.swift +1 -1
  19. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  20. data/fastlane/swift/Fastlane.swift +81 -21
  21. data/fastlane/swift/Gymfile.swift +1 -1
  22. data/fastlane/swift/GymfileProtocol.swift +5 -1
  23. data/fastlane/swift/Matchfile.swift +1 -1
  24. data/fastlane/swift/MatchfileProtocol.swift +5 -1
  25. data/fastlane/swift/Precheckfile.swift +1 -1
  26. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  27. data/fastlane/swift/Scanfile.swift +1 -1
  28. data/fastlane/swift/ScanfileProtocol.swift +5 -1
  29. data/fastlane/swift/Screengrabfile.swift +1 -1
  30. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  31. data/fastlane/swift/Snapshotfile.swift +1 -1
  32. data/fastlane/swift/SnapshotfileProtocol.swift +5 -1
  33. data/fastlane/swift/formatting/Brewfile.lock.json +24 -19
  34. data/fastlane/swift/formatting/Rakefile +1 -0
  35. data/fastlane_core/lib/fastlane_core/project.rb +1 -0
  36. data/gym/lib/gym/generators/build_command_generator.rb +1 -1
  37. data/gym/lib/gym/options.rb +10 -1
  38. data/match/lib/match/change_password.rb +2 -1
  39. data/match/lib/match/encryption/encryption.rb +2 -2
  40. data/match/lib/match/encryption/openssl.rb +10 -5
  41. data/match/lib/match/importer.rb +2 -1
  42. data/match/lib/match/nuke.rb +2 -1
  43. data/match/lib/match/options.rb +5 -0
  44. data/match/lib/match/runner.rb +2 -1
  45. data/pilot/lib/pilot/build_manager.rb +9 -0
  46. data/scan/lib/scan/module.rb +1 -1
  47. data/scan/lib/scan/options.rb +10 -1
  48. data/snapshot/lib/snapshot/options.rb +9 -0
  49. data/spaceship/lib/spaceship/connect_api/models/app.rb +10 -0
  50. data/spaceship/lib/spaceship/connect_api/models/app_availability.rb +23 -0
  51. data/spaceship/lib/spaceship/connect_api/models/territory_availability.rb +62 -0
  52. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +9 -0
  53. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  54. data/spaceship/lib/spaceship/tunes/application.rb +1 -1
  55. data/spaceship/lib/spaceship/tunes/tunes_client.rb +2 -0
  56. data/trainer/lib/trainer/test_parser.rb +27 -2
  57. metadata +22 -20
@@ -235,6 +235,9 @@ public protocol ScanfileProtocol: AnyObject {
235
235
 
236
236
  /// Should this step stop the build if the tests fail? Set this to false if you're using trainer
237
237
  var failBuild: Bool { get }
238
+
239
+ /// Lets xcodebuild use a specified package authorization provider (keychain|netrc)
240
+ var packageAuthorizationProvider: String? { get }
238
241
  }
239
242
 
240
243
  public extension ScanfileProtocol {
@@ -316,8 +319,9 @@ public extension ScanfileProtocol {
316
319
  var useSystemScm: Bool { return false }
317
320
  var numberOfRetries: Int { return 0 }
318
321
  var failBuild: Bool { return true }
322
+ var packageAuthorizationProvider: String? { return nil }
319
323
  }
320
324
 
321
325
  // Please don't remove the lines below
322
326
  // They are used to detect outdated files
323
- // FastlaneRunnerAPIVersion [0.9.134]
327
+ // FastlaneRunnerAPIVersion [0.9.136]
@@ -17,4 +17,4 @@ public class Screengrabfile: ScreengrabfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.221.1
20
+ // Generated with fastlane 2.223.0
@@ -96,4 +96,4 @@ public extension ScreengrabfileProtocol {
96
96
 
97
97
  // Please don't remove the lines below
98
98
  // They are used to detect outdated files
99
- // FastlaneRunnerAPIVersion [0.9.124]
99
+ // FastlaneRunnerAPIVersion [0.9.126]
@@ -17,4 +17,4 @@ public class Snapshotfile: SnapshotfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.221.1
20
+ // Generated with fastlane 2.223.0
@@ -125,6 +125,9 @@ public protocol SnapshotfileProtocol: AnyObject {
125
125
  /// Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file
126
126
  var disablePackageAutomaticUpdates: Bool { get }
127
127
 
128
+ /// Lets xcodebuild use a specified package authorization provider (keychain|netrc)
129
+ var packageAuthorizationProvider: String? { get }
130
+
128
131
  /// The testplan associated with the scheme that should be used for testing
129
132
  var testplan: String? { get }
130
133
 
@@ -192,6 +195,7 @@ public extension SnapshotfileProtocol {
192
195
  var clonedSourcePackagesPath: String? { return nil }
193
196
  var skipPackageDependenciesResolution: Bool { return false }
194
197
  var disablePackageAutomaticUpdates: Bool { return false }
198
+ var packageAuthorizationProvider: String? { return nil }
195
199
  var testplan: String? { return nil }
196
200
  var onlyTesting: String? { return nil }
197
201
  var skipTesting: String? { return nil }
@@ -204,4 +208,4 @@ public extension SnapshotfileProtocol {
204
208
 
205
209
  // Please don't remove the lines below
206
210
  // They are used to detect outdated files
207
- // FastlaneRunnerAPIVersion [0.9.118]
211
+ // FastlaneRunnerAPIVersion [0.9.120]
@@ -2,45 +2,50 @@
2
2
  "entries": {
3
3
  "brew": {
4
4
  "swiftformat": {
5
- "version": "0.53.10",
5
+ "version": "0.54.5",
6
6
  "bottle": {
7
7
  "rebuild": 0,
8
8
  "root_url": "https://ghcr.io/v2/homebrew/core",
9
9
  "files": {
10
+ "arm64_sequoia": {
11
+ "cellar": ":any_skip_relocation",
12
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:3fc57cb9abcbfd64106a3b16f51c8851c9877327553ec5fd9b21683d42b3c18d",
13
+ "sha256": "3fc57cb9abcbfd64106a3b16f51c8851c9877327553ec5fd9b21683d42b3c18d"
14
+ },
10
15
  "arm64_sonoma": {
11
16
  "cellar": ":any_skip_relocation",
12
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:07a24ab550f0a4b26168b77c14b3b184e97552eb9071723af1103b1ff8d38bfd",
13
- "sha256": "07a24ab550f0a4b26168b77c14b3b184e97552eb9071723af1103b1ff8d38bfd"
17
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:4d1f7565498827bbc53230f01c2fca4a7d082f4ae16d32ae568ba633c090c6ee",
18
+ "sha256": "4d1f7565498827bbc53230f01c2fca4a7d082f4ae16d32ae568ba633c090c6ee"
14
19
  },
15
20
  "arm64_ventura": {
16
21
  "cellar": ":any_skip_relocation",
17
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:2781c7eb35cfe585ae8a5f41395694e67af26c5725d25d08530a4f6adb191842",
18
- "sha256": "2781c7eb35cfe585ae8a5f41395694e67af26c5725d25d08530a4f6adb191842"
22
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:416b54dc7938754980f9b2d732254ce7a36c401c2df3b68eba47f54db9bb956c",
23
+ "sha256": "416b54dc7938754980f9b2d732254ce7a36c401c2df3b68eba47f54db9bb956c"
19
24
  },
20
25
  "arm64_monterey": {
21
26
  "cellar": ":any_skip_relocation",
22
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:be39b5733c7a181931682200f3fbece32146b84b7098fec1d9f4d22d248a91e9",
23
- "sha256": "be39b5733c7a181931682200f3fbece32146b84b7098fec1d9f4d22d248a91e9"
27
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:3b14b0bacb0938c650e2d0d30d1f546ea7bac4feac510be16f09a89abd9f95d4",
28
+ "sha256": "3b14b0bacb0938c650e2d0d30d1f546ea7bac4feac510be16f09a89abd9f95d4"
24
29
  },
25
30
  "sonoma": {
26
31
  "cellar": ":any_skip_relocation",
27
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:a080392954a019c55552ca7c6ab56033e8ab6aa1a598a0015b80ee12c62a4414",
28
- "sha256": "a080392954a019c55552ca7c6ab56033e8ab6aa1a598a0015b80ee12c62a4414"
32
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:445a0e38bda1f1dbda7c34dbb75a1b4432c5f0de7f9fa8bd4e03a9220b9bda19",
33
+ "sha256": "445a0e38bda1f1dbda7c34dbb75a1b4432c5f0de7f9fa8bd4e03a9220b9bda19"
29
34
  },
30
35
  "ventura": {
31
36
  "cellar": ":any_skip_relocation",
32
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:7a5cc00008a574bcc3f94c8048fe058a4211a1f2952b65051a723212c07d8ce5",
33
- "sha256": "7a5cc00008a574bcc3f94c8048fe058a4211a1f2952b65051a723212c07d8ce5"
37
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:508b2e8000078773c7884e17b8d1ca711f4313ba14ff0000f7a28af68b02e71a",
38
+ "sha256": "508b2e8000078773c7884e17b8d1ca711f4313ba14ff0000f7a28af68b02e71a"
34
39
  },
35
40
  "monterey": {
36
41
  "cellar": ":any_skip_relocation",
37
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:60b9451e66902de3233febbf20cfa3df39304fb329eb478a8cab277874da7869",
38
- "sha256": "60b9451e66902de3233febbf20cfa3df39304fb329eb478a8cab277874da7869"
42
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:8c367a76ca05ba07ffc38a6bb2f5ee0231d363655ed982284afcb4d685fa524e",
43
+ "sha256": "8c367a76ca05ba07ffc38a6bb2f5ee0231d363655ed982284afcb4d685fa524e"
39
44
  },
40
45
  "x86_64_linux": {
41
46
  "cellar": "/home/linuxbrew/.linuxbrew/Cellar",
42
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:d4bacdce7d4de2ca8e026577a94e87828038d25c28235a96f740fee46c317798",
43
- "sha256": "d4bacdce7d4de2ca8e026577a94e87828038d25c28235a96f740fee46c317798"
47
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:8e8abc969e1b10e7411a92717703c8cd944c7a3f3fd04e2d232918971ae14662",
48
+ "sha256": "8e8abc969e1b10e7411a92717703c8cd944c7a3f3fd04e2d232918971ae14662"
44
49
  }
45
50
  }
46
51
  }
@@ -82,12 +87,12 @@
82
87
  "macOS": "13.6"
83
88
  },
84
89
  "sonoma": {
85
- "HOMEBREW_VERSION": "4.3.5",
90
+ "HOMEBREW_VERSION": "4.3.24",
86
91
  "HOMEBREW_PREFIX": "/opt/homebrew",
87
92
  "Homebrew/homebrew-core": "api",
88
- "CLT": "15.3.0.0.1.1708646388",
89
- "Xcode": "15.0.1",
90
- "macOS": "14.5"
93
+ "CLT": "16.0.0.0.1.1724870825",
94
+ "Xcode": "15.4",
95
+ "macOS": "14.6.1"
91
96
  }
92
97
  }
93
98
  }
@@ -8,6 +8,7 @@ task(:brew) do
8
8
  raise '`brew` is required. Please install brew. https://brew.sh/' unless system('which brew')
9
9
 
10
10
  puts('➡️ Brew')
11
+ sh('brew update')
11
12
  sh('brew bundle')
12
13
  end
13
14
 
@@ -341,6 +341,7 @@ module FastlaneCore
341
341
  proj << "-derivedDataPath #{options[:derived_data_path].shellescape}" if options[:derived_data_path]
342
342
  proj << "-xcconfig #{options[:xcconfig].shellescape}" if options[:xcconfig]
343
343
  proj << "-scmProvider system" if options[:use_system_scm]
344
+ proj << "-packageAuthorizationProvider #{options[:package_authorization_provider].shellescape}" if options[:package_authorization_provider]
344
345
 
345
346
  xcode_at_least_11 = FastlaneCore::Helper.xcode_at_least?('11.0')
346
347
  if xcode_at_least_11 && options[:cloned_source_packages_path]
@@ -184,7 +184,7 @@ module Gym
184
184
  def result_bundle_path
185
185
  unless Gym.cache[:result_bundle_path]
186
186
  path = Gym.config[:result_bundle_path]
187
- path ||= File.join(Gym.config[:output_directory], Gym.config[:output_name] + ".result")
187
+ path ||= File.join(Gym.config[:output_directory], Gym.config[:output_name] + ".xcresult")
188
188
  if File.directory?(path)
189
189
  FileUtils.remove_dir(path)
190
190
  end
@@ -320,7 +320,16 @@ module Gym
320
320
  description: "Lets xcodebuild use system's scm configuration",
321
321
  optional: true,
322
322
  type: Boolean,
323
- default_value: false)
323
+ default_value: false),
324
+ FastlaneCore::ConfigItem.new(key: :package_authorization_provider,
325
+ env_name: "GYM_PACKAGE_AUTHORIZATION_PROVIDER",
326
+ description: "Lets xcodebuild use a specified package authorization provider (keychain|netrc)",
327
+ optional: true,
328
+ type: String,
329
+ verify_block: proc do |value|
330
+ av = %w(netrc keychain)
331
+ UI.user_error!("Unsupported authorization provider '#{value}', must be: #{av}") unless av.include?(value)
332
+ end)
324
333
  ]
325
334
  end
326
335
  end
@@ -26,7 +26,8 @@ module Match
26
26
  git_url: params[:git_url],
27
27
  s3_bucket: params[:s3_bucket],
28
28
  s3_skip_encryption: params[:s3_skip_encryption],
29
- working_directory: storage.working_directory
29
+ working_directory: storage.working_directory,
30
+ force_legacy_encryption: params[:force_legacy_encryption]
30
31
  })
31
32
  encryption.decrypt_files
32
33
 
@@ -134,11 +134,11 @@ module Match
134
134
 
135
135
  # The methods of this class will encrypt or decrypt files in place, by default.
136
136
  class MatchFileEncryption
137
- def encrypt(file_path:, password:, output_path: nil)
137
+ def encrypt(file_path:, password:, output_path: nil, version: 2)
138
138
  output_path = file_path unless output_path
139
139
  data_to_encrypt = File.binread(file_path)
140
140
  e = MatchDataEncryption.new
141
- data = e.encrypt(data: data_to_encrypt, password: password)
141
+ data = e.encrypt(data: data_to_encrypt, password: password, version: version)
142
142
  File.write(output_path, data)
143
143
  end
144
144
 
@@ -14,18 +14,23 @@ module Match
14
14
 
15
15
  attr_accessor :working_directory
16
16
 
17
+ attr_accessor :force_legacy_encryption
18
+
17
19
  def self.configure(params)
18
20
  return self.new(
19
21
  keychain_name: params[:keychain_name],
20
- working_directory: params[:working_directory]
22
+ working_directory: params[:working_directory],
23
+ force_legacy_encryption: params[:force_legacy_encryption]
21
24
  )
22
25
  end
23
26
 
24
27
  # @param keychain_name: The identifier used to store the passphrase in the Keychain
25
28
  # @param working_directory: The path to where the certificates are stored
26
- def initialize(keychain_name: nil, working_directory: nil)
29
+ # @param force_legacy_encryption: Force use of legacy EncryptionV1 algorithm
30
+ def initialize(keychain_name: nil, working_directory: nil, force_legacy_encryption: false)
27
31
  self.keychain_name = keychain_name
28
32
  self.working_directory = working_directory
33
+ self.force_legacy_encryption = force_legacy_encryption
29
34
  end
30
35
 
31
36
  def encrypt_files(password: nil)
@@ -33,7 +38,7 @@ module Match
33
38
  password ||= fetch_password!
34
39
  iterate(self.working_directory) do |current|
35
40
  files << current
36
- encrypt_specific_file(path: current, password: password)
41
+ encrypt_specific_file(path: current, password: password, version: force_legacy_encryption ? 1 : 2)
37
42
  UI.success("🔒 Encrypted '#{File.basename(current)}'") if FastlaneCore::Globals.verbose?
38
43
  end
39
44
  UI.success("🔒 Successfully encrypted certificates repo")
@@ -109,10 +114,10 @@ module Match
109
114
  return password
110
115
  end
111
116
 
112
- def encrypt_specific_file(path: nil, password: nil)
117
+ def encrypt_specific_file(path: nil, password: nil, version: nil)
113
118
  UI.user_error!("No password supplied") if password.to_s.strip.length == 0
114
119
  e = MatchFileEncryption.new
115
- e.encrypt(file_path: path, password: password)
120
+ e.encrypt(file_path: path, password: password, version: version)
116
121
  rescue FastlaneCore::Interface::FastlaneError
117
122
  raise
118
123
  rescue => error
@@ -23,7 +23,8 @@ module Match
23
23
  git_url: params[:git_url],
24
24
  s3_bucket: params[:s3_bucket],
25
25
  s3_skip_encryption: params[:s3_skip_encryption],
26
- working_directory: storage.working_directory
26
+ working_directory: storage.working_directory,
27
+ force_legacy_encryption: params[:force_legacy_encryption]
27
28
  })
28
29
  encryption.decrypt_files if encryption
29
30
  UI.success("Repo is at: '#{storage.working_directory}'")
@@ -42,7 +42,8 @@ module Match
42
42
  git_url: params[:git_url],
43
43
  s3_bucket: params[:s3_bucket],
44
44
  s3_skip_encryption: params[:s3_skip_encryption],
45
- working_directory: storage.working_directory
45
+ working_directory: storage.working_directory,
46
+ force_legacy_encryption: params[:force_legacy_encryption]
46
47
  })
47
48
  self.encryption.decrypt_files if self.encryption
48
49
 
@@ -355,6 +355,11 @@ module Match
355
355
  description: "Skips setting the partition list (which can sometimes take a long time). Setting the partition list is usually needed to prevent Xcode from prompting to allow a cert to be used for signing",
356
356
  type: Boolean,
357
357
  default_value: false),
358
+ FastlaneCore::ConfigItem.new(key: :force_legacy_encryption,
359
+ env_name: "MATCH_FORCE_LEGACY_ENCRYPTION",
360
+ description: "Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions",
361
+ type: Boolean,
362
+ default_value: false),
358
363
 
359
364
  # other
360
365
  FastlaneCore::ConfigItem.new(key: :verbose,
@@ -49,7 +49,8 @@ module Match
49
49
  git_url: params[:git_url],
50
50
  s3_bucket: params[:s3_bucket],
51
51
  s3_skip_encryption: params[:s3_skip_encryption],
52
- working_directory: storage.working_directory
52
+ working_directory: storage.working_directory,
53
+ force_legacy_encryption: params[:force_legacy_encryption]
53
54
  })
54
55
  encryption.decrypt_files if encryption
55
56
 
@@ -391,6 +391,7 @@ module Pilot
391
391
  end
392
392
 
393
393
  # If App Store Connect API token, use token.
394
+ # If api_key is specified and it is an Individual API Key, don't use token but use username.
394
395
  # If itc_provider was explicitly specified, use it.
395
396
  # If there are multiple teams, infer the provider from the selected team name.
396
397
  # If there are fewer than two teams, don't infer the provider.
@@ -407,6 +408,14 @@ module Pilot
407
408
  api_key
408
409
  end
409
410
 
411
+ # Currently no kind of transporters accept an Individual API Key. Use username and app-specific password instead.
412
+ # See https://github.com/fastlane/fastlane/issues/22115
413
+ is_individual_key = !api_key.nil? && api_key[:issuer_id].nil?
414
+ if is_individual_key
415
+ api_key = nil
416
+ api_token = nil
417
+ end
418
+
410
419
  unless api_token.nil?
411
420
  api_token.refresh! if api_token.expired?
412
421
  return FastlaneCore::ItunesTransporter.new(nil, nil, false, nil, api_token.text, altool_compatible_command: true, api_key: api_key)
@@ -24,7 +24,7 @@ module Scan
24
24
 
25
25
  def building_mac_catalyst_for_mac?
26
26
  return false unless Scan.project
27
- Scan.project.supports_mac_catalyst? && Scan.config[:catalyst_platform] == "macos"
27
+ Scan.config[:catalyst_platform] == "macos" && Scan.project.supports_mac_catalyst?
28
28
  end
29
29
  end
30
30
 
@@ -537,7 +537,16 @@ module Scan
537
537
  env_name: "SCAN_FAIL_BUILD",
538
538
  description: "Should this step stop the build if the tests fail? Set this to false if you're using trainer",
539
539
  type: Boolean,
540
- default_value: true)
540
+ default_value: true),
541
+ FastlaneCore::ConfigItem.new(key: :package_authorization_provider,
542
+ env_name: "SCAN_PACKAGE_AUTHORIZATION_PROVIDER",
543
+ description: "Lets xcodebuild use a specified package authorization provider (keychain|netrc)",
544
+ optional: true,
545
+ type: String,
546
+ verify_block: proc do |value|
547
+ av = %w(netrc keychain)
548
+ UI.user_error!("Unsupported authorization provider '#{value}', must be: #{av}") unless av.include?(value)
549
+ end)
541
550
 
542
551
  ]
543
552
  end
@@ -267,6 +267,15 @@ module Snapshot
267
267
  description: "Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file",
268
268
  type: Boolean,
269
269
  default_value: false),
270
+ FastlaneCore::ConfigItem.new(key: :package_authorization_provider,
271
+ env_name: "SNAPSHOT_PACKAGE_AUTHORIZATION_PROVIDER",
272
+ description: "Lets xcodebuild use a specified package authorization provider (keychain|netrc)",
273
+ optional: true,
274
+ type: String,
275
+ verify_block: proc do |value|
276
+ av = %w(netrc keychain)
277
+ UI.user_error!("Unsupported authorization provider '#{value}', must be: #{av}") unless av.include?(value)
278
+ end),
270
279
  FastlaneCore::ConfigItem.new(key: :testplan,
271
280
  env_name: "SNAPSHOT_TESTPLAN",
272
281
  description: "The testplan associated with the scheme that should be used for testing",
@@ -148,6 +148,16 @@ module Spaceship
148
148
  return resp.to_models.first
149
149
  end
150
150
 
151
+ #
152
+ # App Availabilities
153
+ #
154
+
155
+ def get_app_availabilities(client: nil, filter: {}, includes: "territoryAvailabilities", limit: { "territoryAvailabilities": 200 })
156
+ client ||= Spaceship::ConnectAPI
157
+ resp = client.get_app_availabilities(app_id: id, filter: filter, includes: includes, limit: limit, sort: nil)
158
+ return resp.to_models.first
159
+ end
160
+
151
161
  #
152
162
  # Available Territories
153
163
  #
@@ -0,0 +1,23 @@
1
+ require_relative '../model'
2
+ module Spaceship
3
+ class ConnectAPI
4
+ class AppAvailability
5
+ include Spaceship::ConnectAPI::Model
6
+
7
+ attr_accessor :app
8
+ attr_accessor :available_in_new_territories
9
+
10
+ attr_accessor :territoryAvailabilities
11
+
12
+ attr_mapping({
13
+ app: 'app',
14
+ availableInNewTerritories: 'available_in_new_territories',
15
+ territoryAvailabilities: 'territory_availabilities'
16
+ })
17
+
18
+ def self.type
19
+ return 'appAvailabilities'
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,62 @@
1
+ require_relative '../model'
2
+ module Spaceship
3
+ class ConnectAPI
4
+ class TerritoryAvailability
5
+ include Spaceship::ConnectAPI::Model
6
+
7
+ attr_accessor :available
8
+ attr_accessor :content_statuses
9
+ attr_accessor :pre_order_enabled
10
+ attr_accessor :pre_order_publish_date
11
+ attr_accessor :release_date
12
+
13
+ module ContentStatus
14
+ AVAILABLE = "AVAILABLE"
15
+ AVAILABLE_FOR_PREORDER_ON_DATE = "AVAILABLE_FOR_PREORDER_ON_DATE"
16
+ PROCESSING_TO_NOT_AVAILABLE = "PROCESSING_TO_NOT_AVAILABLE"
17
+ PROCESSING_TO_AVAILABLE = "PROCESSING_TO_AVAILABLE"
18
+ PROCESSING_TO_PRE_ORDER = "PROCESSING_TO_PRE_ORDER"
19
+ AVAILABLE_FOR_SALE_UNRELEASED_APP = "AVAILABLE_FOR_SALE_UNRELEASED_APP"
20
+ PREORDER_ON_UNRELEASED_APP = "PREORDER_ON_UNRELEASED_APP"
21
+ AVAILABLE_FOR_PREORDER = "AVAILABLE_FOR_PREORDER"
22
+ MISSING_RATING = "MISSING_RATING"
23
+ CANNOT_SELL_RESTRICTED_RATING = "CANNOT_SELL_RESTRICTED_RATING"
24
+ BRAZIL_REQUIRED_TAX_ID = "BRAZIL_REQUIRED_TAX_ID"
25
+ MISSING_GRN = "MISSING_GRN"
26
+ UNVERIFIED_GRN = "UNVERIFIED_GRN"
27
+ CANNOT_SELL_SEVENTEEN_PLUS_APPS = "CANNOT_SELL_SEVENTEEN_PLUS_APPS"
28
+ CANNOT_SELL_SEXUALLY_EXPLICIT = "CANNOT_SELL_SEXUALLY_EXPLICIT"
29
+ CANNOT_SELL_NON_IOS_GAMES = "CANNOT_SELL_NON_IOS_GAMES"
30
+ CANNOT_SELL_SEVENTEEN_PLUS_GAMES = "CANNOT_SELL_SEVENTEEN_PLUS_GAMES"
31
+ CANNOT_SELL_FREQUENT_INTENSE_GAMBLING = "CANNOT_SELL_FREQUENT_INTENSE_GAMBLING"
32
+ CANNOT_SELL_CASINO = "CANNOT_SELL_CASINO"
33
+ CANNOT_SELL_CASINO_WITHOUT_GRAC = "CANNOT_SELL_CASINO_WITHOUT_GRAC"
34
+ CANNOT_SELL_CASINO_WITHOUT_AGE_VERIFICATION = "CANNOT_SELL_CASINO_WITHOUT_AGE_VERIFICATION"
35
+ CANNOT_SELL_FREQUENT_INTENSE_ALCOHOL_TOBACCO_DRUGS = "CANNOT_SELL_FREQUENT_INTENSE_ALCOHOL_TOBACCO_DRUGS"
36
+ CANNOT_SELL_FREQUENT_INTENSE_VIOLENCE = "CANNOT_SELL_FREQUENT_INTENSE_VIOLENCE"
37
+ CANNOT_SELL_FREQUENT_INTENSE_SEXUAL_CONTENT_NUDITY = "CANNOT_SELL_FREQUENT_INTENSE_SEXUAL_CONTENT_NUDITY"
38
+ CANNOT_SELL_INFREQUENT_MILD_ALCOHOL_TOBACCO_DRUGS = "CANNOT_SELL_INFREQUENT_MILD_ALCOHOL_TOBACCO_DRUGS"
39
+ CANNOT_SELL_INFREQUENT_MILD_SEXUAL_CONTENT_NUDITY = "CANNOT_SELL_INFREQUENT_MILD_SEXUAL_CONTENT_NUDITY"
40
+ CANNOT_SELL_ADULT_ONLY = "CANNOT_SELL_ADULT_ONLY"
41
+ CANNOT_SELL_FREQUENT_INTENSE = "CANNOT_SELL_FREQUENT_INTENSE"
42
+ CANNOT_SELL_FREQUENT_INTENSE_WITHOUT_GRAC = "CANNOT_SELL_FREQUENT_INTENSE_WITHOUT_GRAC"
43
+ CANNOT_SELL_GAMBLING_CONTESTS = "CANNOT_SELL_GAMBLING_CONTESTS"
44
+ CANNOT_SELL_GAMBLING = "CANNOT_SELL_GAMBLING"
45
+ CANNOT_SELL_CONTESTS = "CANNOT_SELL_CONTESTS"
46
+ CANNOT_SELL = "CANNOT_SELL"
47
+ end
48
+
49
+ attr_mapping({
50
+ available: 'available',
51
+ contentStatuses: 'content_statuses',
52
+ preOrderEnabled: 'pre_order_enabled',
53
+ preOrderPublishDate: 'pre_order_publish_date',
54
+ releaseDate: 'release_date'
55
+ })
56
+
57
+ def self.type
58
+ return 'territoryAvailabilities'
59
+ end
60
+ end
61
+ end
62
+ end
@@ -416,6 +416,15 @@ module Spaceship
416
416
  tunes_request_client.patch("#{Version::V1}/appPreviewSets/#{app_preview_set_id}/relationships/appPreviews", body)
417
417
  end
418
418
 
419
+ #
420
+ # appAvailabilities
421
+ #
422
+
423
+ def get_app_availabilities(app_id: nil, filter: nil, includes: nil, limit: nil, sort: nil)
424
+ params = tunes_request_client.build_params(filter: nil, includes: includes, limit: limit, sort: nil)
425
+ tunes_request_client.get("#{Version::V2}/appAvailabilities/#{app_id}", params)
426
+ end
427
+
419
428
  #
420
429
  # availableTerritories
421
430
  #
@@ -38,6 +38,8 @@ require 'spaceship/connect_api/models/custom_app_organization'
38
38
  require 'spaceship/connect_api/models/custom_app_user'
39
39
  require 'spaceship/connect_api/models/pre_release_version'
40
40
 
41
+ require 'spaceship/connect_api/models/app_availability'
42
+ require 'spaceship/connect_api/models/territory_availability'
41
43
  require 'spaceship/connect_api/models/app_data_usage'
42
44
  require 'spaceship/connect_api/models/app_data_usage_category'
43
45
  require 'spaceship/connect_api/models/app_data_usage_data_protection'
@@ -72,7 +72,7 @@ module Spaceship
72
72
  def find(identifier, mac: false)
73
73
  all.find do |app|
74
74
  ((app.apple_id && app.apple_id.casecmp(identifier.to_s) == 0) || (app.bundle_id && app.bundle_id.casecmp(identifier.to_s) == 0)) &&
75
- app.version_sets.any? { |v| (mac ? ["osx"] : ["ios", "appletvos"]).include?(v.platform) }
75
+ app.version_sets.any? { |v| (mac ? ["osx"] : ["ios", "xros", "appletvos"]).include?(v.platform) }
76
76
  end
77
77
  end
78
78
 
@@ -297,6 +297,8 @@ module Spaceship
297
297
  "appletvos"
298
298
  when "MAC_OS"
299
299
  "osx"
300
+ when "VISION_OS"
301
+ "xros"
300
302
  when "IOS"
301
303
  "ios"
302
304
  else
@@ -197,12 +197,37 @@ module Trainer
197
197
  return output
198
198
  end
199
199
 
200
+ # Hotfix: From Xcode 16 beta 3 'xcresulttool get --format json' has been deprecated;
201
+ # '--legacy' flag required to keep on using the command
202
+ def generate_cmd_parse_xcresult(path)
203
+ xcresulttool_cmd = %W(
204
+ xcrun
205
+ xcresulttool
206
+ get
207
+ --format
208
+ json
209
+ --path
210
+ #{path}
211
+ )
212
+
213
+ # e.g. DEVELOPER_DIR=/Applications/Xcode_16_beta_3.app
214
+ # xcresulttool version 23021, format version 3.53 (current)
215
+ match = `xcrun xcresulttool version`.match(/xcresulttool version (?<version>[\d.]+)/)
216
+ version = match[:version]
217
+ xcresulttool_cmd << '--legacy' if Gem::Version.new(version) >= Gem::Version.new(23_021)
218
+
219
+ xcresulttool_cmd.join(' ')
220
+ end
221
+
200
222
  def parse_xcresult(path, output_remove_retry_attempts: false)
201
223
  require 'shellwords'
202
224
  path = Shellwords.escape(path)
203
225
 
204
226
  # Executes xcresulttool to get JSON format of the result bundle object
205
- result_bundle_object_raw = execute_cmd("xcrun xcresulttool get --format json --path #{path}")
227
+ # Hotfix: From Xcode 16 beta 3 'xcresulttool get --format json' has been deprecated; '--legacy' flag required to keep on using the command
228
+ xcresulttool_cmd = generate_cmd_parse_xcresult(path)
229
+
230
+ result_bundle_object_raw = execute_cmd(xcresulttool_cmd)
206
231
  result_bundle_object = JSON.parse(result_bundle_object_raw)
207
232
 
208
233
  # Parses JSON into ActionsInvocationRecord to find a list of all ids for ActionTestPlanRunSummaries
@@ -215,7 +240,7 @@ module Trainer
215
240
  # Maps ids into ActionTestPlanRunSummaries by executing xcresulttool to get JSON
216
241
  # containing specific information for each test summary,
217
242
  summaries = ids.map do |id|
218
- raw = execute_cmd("xcrun xcresulttool get --format json --path #{path} --id #{id}")
243
+ raw = execute_cmd("#{xcresulttool_cmd} --id #{id}")
219
244
  json = JSON.parse(raw)
220
245
  Trainer::XCResult::ActionTestPlanRunSummaries.new(json)
221
246
  end