fastlane 2.221.1 → 2.223.0

Sign up to get free protection for your applications and to get access to all the features.
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