fastlane 2.230.0 → 2.231.1

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 (52) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +94 -94
  3. data/fastlane/lib/fastlane/actions/docs/create_app_online.md +4 -2
  4. data/fastlane/lib/fastlane/actions/get_version_number.rb +1 -1
  5. data/fastlane/lib/fastlane/actions/increment_build_number.rb +1 -1
  6. data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +1 -1
  7. data/fastlane/lib/fastlane/cli_tools_distributor.rb +9 -0
  8. data/fastlane/lib/fastlane/version.rb +2 -1
  9. data/fastlane/swift/Actions.swift +1 -1
  10. data/fastlane/swift/Appfile.swift +1 -1
  11. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  12. data/fastlane/swift/Atomic.swift +1 -1
  13. data/fastlane/swift/ControlCommand.swift +1 -1
  14. data/fastlane/swift/Deliverfile.swift +2 -2
  15. data/fastlane/swift/DeliverfileProtocol.swift +2 -2
  16. data/fastlane/swift/Fastlane.swift +2 -60
  17. data/fastlane/swift/Gymfile.swift +2 -2
  18. data/fastlane/swift/GymfileProtocol.swift +2 -2
  19. data/fastlane/swift/LaneFileProtocol.swift +1 -1
  20. data/fastlane/swift/MainProcess.swift +1 -1
  21. data/fastlane/swift/Matchfile.swift +2 -2
  22. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  23. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  24. data/fastlane/swift/Plugins.swift +1 -1
  25. data/fastlane/swift/Precheckfile.swift +2 -2
  26. data/fastlane/swift/PrecheckfileProtocol.swift +2 -2
  27. data/fastlane/swift/RubyCommand.swift +1 -1
  28. data/fastlane/swift/RubyCommandable.swift +1 -1
  29. data/fastlane/swift/Runner.swift +1 -1
  30. data/fastlane/swift/RunnerArgument.swift +1 -1
  31. data/fastlane/swift/Scanfile.swift +2 -2
  32. data/fastlane/swift/ScanfileProtocol.swift +2 -2
  33. data/fastlane/swift/Screengrabfile.swift +2 -2
  34. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  35. data/fastlane/swift/Snapshotfile.swift +2 -2
  36. data/fastlane/swift/SnapshotfileProtocol.swift +2 -2
  37. data/fastlane/swift/SocketClient.swift +1 -1
  38. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  39. data/fastlane/swift/SocketResponse.swift +1 -1
  40. data/fastlane/swift/main.swift +1 -1
  41. data/produce/lib/produce/commands_generator.rb +2 -0
  42. data/scan/lib/scan/error_handler.rb +5 -0
  43. data/snapshot/lib/snapshot/detect_values.rb +1 -1
  44. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +4 -2
  45. data/spaceship/lib/spaceship/client.rb +32 -2
  46. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +32 -2
  47. data/spaceship/lib/spaceship/connect_api/models/webhook.rb +62 -0
  48. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +38 -0
  49. data/spaceship/lib/spaceship/connect_api.rb +1 -0
  50. data/spaceship/lib/spaceship/portal/key.rb +22 -3
  51. data/spaceship/lib/spaceship/portal/portal_client.rb +29 -2
  52. metadata +53 -24
@@ -1,5 +1,5 @@
1
1
  // PrecheckfileProtocol.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  public protocol PrecheckfileProtocol: AnyObject {
5
5
  /// Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file)
@@ -52,4 +52,4 @@ public extension PrecheckfileProtocol {
52
52
 
53
53
  // Please don't remove the lines below
54
54
  // They are used to detect outdated files
55
- // FastlaneRunnerAPIVersion [0.9.135]
55
+ // FastlaneRunnerAPIVersion [0.9.137]
@@ -1,5 +1,5 @@
1
1
  // RubyCommand.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -1,5 +1,5 @@
1
1
  // RubyCommandable.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -1,5 +1,5 @@
1
1
  // Runner.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -1,5 +1,5 @@
1
1
  // RunnerArgument.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -1,5 +1,5 @@
1
1
  // Scanfile.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  // This class is automatically included in FastlaneRunner during build
5
5
 
@@ -17,4 +17,4 @@ public class Scanfile: ScanfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.230.0
20
+ // Generated with fastlane 2.231.1
@@ -1,5 +1,5 @@
1
1
  // ScanfileProtocol.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  public protocol ScanfileProtocol: AnyObject {
5
5
  /// Path to the workspace file
@@ -328,4 +328,4 @@ public extension ScanfileProtocol {
328
328
 
329
329
  // Please don't remove the lines below
330
330
  // They are used to detect outdated files
331
- // FastlaneRunnerAPIVersion [0.9.147]
331
+ // FastlaneRunnerAPIVersion [0.9.149]
@@ -1,5 +1,5 @@
1
1
  // Screengrabfile.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  // This class is automatically included in FastlaneRunner during build
5
5
 
@@ -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.230.0
20
+ // Generated with fastlane 2.231.1
@@ -1,5 +1,5 @@
1
1
  // ScreengrabfileProtocol.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  public protocol ScreengrabfileProtocol: AnyObject {
5
5
  /// Path to the root of your Android SDK installation, e.g. ~/tools/android-sdk-macosx
@@ -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.137]
99
+ // FastlaneRunnerAPIVersion [0.9.139]
@@ -1,5 +1,5 @@
1
1
  // Snapshotfile.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  // This class is automatically included in FastlaneRunner during build
5
5
 
@@ -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.230.0
20
+ // Generated with fastlane 2.231.1
@@ -1,5 +1,5 @@
1
1
  // SnapshotfileProtocol.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  public protocol SnapshotfileProtocol: AnyObject {
5
5
  /// Path to the workspace file
@@ -212,4 +212,4 @@ public extension SnapshotfileProtocol {
212
212
 
213
213
  // Please don't remove the lines below
214
214
  // They are used to detect outdated files
215
- // FastlaneRunnerAPIVersion [0.9.131]
215
+ // FastlaneRunnerAPIVersion [0.9.133]
@@ -1,5 +1,5 @@
1
1
  // SocketClient.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -1,5 +1,5 @@
1
1
  // SocketClientDelegateProtocol.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -1,5 +1,5 @@
1
1
  // SocketResponse.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -1,5 +1,5 @@
1
1
  // main.swift
2
- // Copyright (c) 2025 FastlaneTools
2
+ // Copyright (c) 2026 FastlaneTools
3
3
 
4
4
  //
5
5
  // ** NOTE **
@@ -62,6 +62,7 @@ module Produce
62
62
  c.option('--file-provider-testing-mode', 'Enable File Provider Testing Mode')
63
63
  c.option('--fonts', 'Enable Fonts')
64
64
  c.option('--extended-virtual-address-space', 'Enable Extended Virtual Address Space')
65
+ c.option('--declared-age-range', 'Enable Declared Age Range capability')
65
66
  c.option('--game-center STRING', String, 'Enable Game Center, suitable values are "ios" and "macos"')
66
67
  c.option('--health-kit', 'Enable Health Kit')
67
68
  c.option('--hls-interstitial-preview', 'Enable Hls Interstitial Preview')
@@ -136,6 +137,7 @@ module Produce
136
137
  c.option('--custom-network-protocol', 'Disable Custom Network Protocol')
137
138
  c.option('--data-protection', 'Disable Data Protection')
138
139
  c.option('--extended-virtual-address-space', 'Disable Extended Virtual Address Space')
140
+ c.option('--declared-age-range', 'Disable Declared Age Range capability')
139
141
  c.option('--family-controls', 'Disable Family Controls')
140
142
  c.option('--file-provider-testing-mode', 'Disable File Provider Testing Mode')
141
143
  c.option('--fonts', 'Disable Fonts')
@@ -38,6 +38,11 @@ module Scan
38
38
  return
39
39
  when /Testing failed/
40
40
  UI.build_failure!("Error building the application. #{details}")
41
+ when /Testing started.*\*\* TEST FAILED \*\*/m, /Testing started.*\*\* TEST EXECUTE FAILED \*\*/m
42
+ # Xcode 26+: If we see both "Testing started" and "** TEST FAILED **"
43
+ # or "** TEST EXECUTE FAILED **" (test-without-building), then tests
44
+ # were executed but failed.
45
+ return
41
46
  when /Executed/, /Failing tests:/
42
47
  # this is *really* important:
43
48
  # we don't want to raise an exception here
@@ -66,7 +66,7 @@ module Snapshot
66
66
 
67
67
  config[:devices] << sim.name
68
68
  end
69
- elsif Snapshot.project.mac?
69
+ elsif config[:devices].nil? && Snapshot.project.mac?
70
70
  config[:devices] = ["Mac"]
71
71
  end
72
72
  end
@@ -133,12 +133,14 @@ module Snapshot
133
133
  UI.message("Overriding Status Bar")
134
134
 
135
135
  if arguments.nil? || arguments.empty?
136
- # The time needs to be passed as ISO8601 so the simulator formats it correctly
136
+ # The time must be passed as HH:MM format (e.g., "09:41")
137
+ # Note: Despite the simctl manual stating ISO date strings are supported, only HH:MM format actually works
137
138
  time = Time.new(2007, 1, 9, 9, 41, 0)
139
+ time_str = time.strftime("%H:%M")
138
140
 
139
141
  # If you don't override the operator name, you'll get "Carrier" in the status bar on no-notch devices such as iPhone 8. Pass an empty string to blank it out.
140
142
 
141
- arguments = "--time #{time.iso8601} --dataNetwork wifi --wifiMode active --wifiBars 3 --cellularMode active --operatorName '' --cellularBars 4 --batteryState charged --batteryLevel 100"
143
+ arguments = "--time #{time_str} --dataNetwork wifi --wifiMode active --wifiBars 3 --cellularMode active --operatorName '' --cellularBars 4 --batteryState charged --batteryLevel 100"
142
144
  end
143
145
 
144
146
  Helper.backticks("xcrun simctl status_bar #{device_udid} override #{arguments} &> /dev/null")
@@ -476,13 +476,22 @@ module Spaceship
476
476
  puts("Received SIRP signin init response: #{response.body}") if Spaceship::Globals.verbose?
477
477
 
478
478
  body = response.body
479
+ unless body.kind_of?(Hash)
480
+ raise UnexpectedResponse, "Expected JSON response, but got #{body.class}: #{body.to_s[0..1000]}"
481
+ end
482
+
483
+ if body["serviceErrors"]
484
+ raise UnexpectedResponse, body
485
+ end
486
+
479
487
  iterations = body["iteration"]
480
488
  salt = Base64.strict_decode64(body["salt"])
481
489
  b = Base64.strict_decode64(body["b"])
482
490
  c = body["c"]
491
+ protocol = body["protocol"]
483
492
 
484
493
  key_length = 32
485
- encrypted_password = pbkdf2(password, salt, iterations, key_length)
494
+ encrypted_password = pbkdf2(password, salt, iterations, key_length, protocol)
486
495
 
487
496
  m1 = client.process_challenge(
488
497
  user,
@@ -524,9 +533,20 @@ module Spaceship
524
533
  return response
525
534
  end
526
535
 
527
- def pbkdf2(password, salt, iterations, key_length, digest = OpenSSL::Digest::SHA256.new)
536
+ def pbkdf2(password, salt, iterations, key_length, protocol, digest = OpenSSL::Digest::SHA256.new)
528
537
  require 'openssl'
538
+
539
+ unless %w[s2k s2k_fo].include?(protocol)
540
+ raise SIRPAuthenticationError, "Unsupported protocol '#{protocol}' for pbkdf2"
541
+ end
542
+
529
543
  password = OpenSSL::Digest::SHA256.digest(password)
544
+
545
+ if protocol == 's2k_fo'
546
+ puts("Using legacy s2k_fo protocol for password digest") if Spaceship::Globals.verbose?
547
+ password = to_hex(password)
548
+ end
549
+
530
550
  OpenSSL::PKCS5.pbkdf2_hmac(password, salt, iterations, key_length, digest)
531
551
  end
532
552
 
@@ -1040,6 +1060,10 @@ module Spaceship
1040
1060
  raise BadGatewayError.new, "Apple 502 detected - this might be temporary server error, try again later"
1041
1061
  end
1042
1062
 
1063
+ if response.body.to_s.include?("<title>503 Service Temporarily Unavailable</title>") || response.body.to_s.include?("<h1>503 Service Temporarily Unavailable</h1>")
1064
+ raise AppleTimeoutError.new, "Apple 503 detected - this might be temporary server error, check https://developer.apple.com/system-status/ to see if there is a known downtime"
1065
+ end
1066
+
1043
1067
  return response
1044
1068
  end
1045
1069
  end
@@ -1056,6 +1080,12 @@ module Spaceship
1056
1080
  raise AccessForbiddenError.new, msg
1057
1081
  when 429
1058
1082
  raise TooManyRequestsError, response.to_hash
1083
+ when 502
1084
+ raise BadGatewayError.new, "Apple 502 detected - this might be temporary server error, try again later"
1085
+ when 503
1086
+ raise AppleTimeoutError.new, "Apple 503 detected - this might be temporary server error, check https://developer.apple.com/system-status/ to see if there is a known downtime"
1087
+ when 504
1088
+ raise GatewayTimeoutError.new, "Apple 504 detected - this might be temporary server error, try again later"
1059
1089
  end
1060
1090
  end
1061
1091
 
@@ -80,10 +80,40 @@ module Spaceship
80
80
  # API
81
81
  #
82
82
 
83
+ # Certificate types not supported by the App Store Connect API.
84
+ # https://api.appstoreconnect.apple.com/v1/certificates?filter[certificateType]=DEVELOPER_ID_APPLICATION_G2
85
+ # Radar: FB21181137.
86
+ UNSUPPORTED_CERTIFICATE_TYPE_FILTERS = [
87
+ CertificateType::DEVELOPER_ID_APPLICATION_G2
88
+ ]
89
+
83
90
  def self.all(client: nil, filter: {}, includes: nil, fields: nil, limit: Spaceship::ConnectAPI::MAX_OBJECTS_PER_PAGE_LIMIT, sort: nil)
84
91
  client ||= Spaceship::ConnectAPI
85
- resps = client.get_certificates(filter: filter, includes: includes, fields: fields, limit: limit, sort: sort).all_pages
86
- return resps.flat_map(&:to_models)
92
+
93
+ new_filter = filter.dup
94
+
95
+ has_unsupported_cert_types_filter = filter[:certificateType] && UNSUPPORTED_CERTIFICATE_TYPE_FILTERS.any? { |type| filter[:certificateType].include?(type) }
96
+
97
+ # If the filter contains unsupported certificate types:
98
+ # - remove the certificateType filter completely and fetch all certificates
99
+ # - filter fetched certificates later by the given certificate types
100
+ if has_unsupported_cert_types_filter
101
+ new_filter[:certificateType] = nil
102
+ end
103
+ new_filter.compact!
104
+
105
+ resps = client.get_certificates(filter: new_filter, includes: includes, fields: fields, limit: limit, sort: sort).all_pages
106
+
107
+ certs = resps.flat_map(&:to_models)
108
+
109
+ if has_unsupported_cert_types_filter
110
+ # Filter fetched certificates by the given certificate types if we encountered unsupported certificate types in the filter previously.
111
+ certs.select! do |cert|
112
+ filter[:certificateType].include?(cert.certificate_type)
113
+ end
114
+ end
115
+
116
+ return certs
87
117
  end
88
118
 
89
119
  def self.create(client: nil, certificate_type: nil, csr_content: nil)
@@ -0,0 +1,62 @@
1
+ require_relative '../model'
2
+
3
+ module Spaceship
4
+ class ConnectAPI
5
+ class Webhook
6
+ include Spaceship::ConnectAPI::Model
7
+
8
+ attr_accessor :enabled
9
+ attr_accessor :event_types
10
+ attr_accessor :name
11
+ attr_accessor :url
12
+
13
+ attr_mapping({
14
+ "enabled" => "enabled",
15
+ "eventTypes" => "event_types",
16
+ "name" => "name",
17
+ "url" => "url"
18
+ })
19
+
20
+ # Found at https://developer.apple.com/documentation/appstoreconnectapi/webhookeventtype
21
+ module EventType
22
+ ALTERNATIVE_DISTRIBUTION_PACKAGE_AVAILABLE_UPDATED = "ALTERNATIVE_DISTRIBUTION_PACKAGE_AVAILABLE_UPDATED"
23
+ ALTERNATIVE_DISTRIBUTION_PACKAGE_VERSION_CREATED = "ALTERNATIVE_DISTRIBUTION_PACKAGE_VERSION_CREATED"
24
+ ALTERNATIVE_DISTRIBUTION_TERRITORY_AVAILABILITY_UPDATED = "ALTERNATIVE_DISTRIBUTION_TERRITORY_AVAILABILITY_UPDATED"
25
+ APP_STORE_VERSION_APP_VERSION_STATE_UPDATED = "APP_STORE_VERSION_APP_VERSION_STATE_UPDATED"
26
+ BACKGROUND_ASSET_VERSION_APP_STORE_RELEASE_STATE_UPDATED = "BACKGROUND_ASSET_VERSION_APP_STORE_RELEASE_STATE_UPDATED"
27
+ BACKGROUND_ASSET_VERSION_EXTERNAL_BETA_RELEASE_STATE_UPDATED = "BACKGROUND_ASSET_VERSION_EXTERNAL_BETA_RELEASE_STATE_UPDATED"
28
+ BACKGROUND_ASSET_VERSION_INTERNAL_BETA_RELEASE_CREATED = "BACKGROUND_ASSET_VERSION_INTERNAL_BETA_RELEASE_CREATED"
29
+ BACKGROUND_ASSET_VERSION_STATE_UPDATED = "BACKGROUND_ASSET_VERSION_STATE_UPDATED"
30
+ BETA_FEEDBACK_CRASH_SUBMISSION_CREATED = "BETA_FEEDBACK_CRASH_SUBMISSION_CREATED"
31
+ BETA_FEEDBACK_SCREENSHOT_SUBMISSION_CREATED = "BETA_FEEDBACK_SCREENSHOT_SUBMISSION_CREATED"
32
+ BUILD_BETA_DETAIL_EXTERNAL_BUILD_STATE_UPDATED = "BUILD_BETA_DETAIL_EXTERNAL_BUILD_STATE_UPDATED"
33
+ BUILD_UPLOAD_STATE_UPDATED = "BUILD_UPLOAD_STATE_UPDATED"
34
+ end
35
+
36
+ def self.type
37
+ return "webhooks"
38
+ end
39
+
40
+ #
41
+ # API
42
+ #
43
+
44
+ def self.all(client: nil, app_id:, filter: {}, includes: nil, limit: nil, sort: nil)
45
+ client ||= Spaceship::ConnectAPI
46
+ resps = client.get_webhooks(app_id: app_id, filter: filter, includes: includes, limit: limit, sort: sort).all_pages
47
+ return resps.flat_map(&:to_models)
48
+ end
49
+
50
+ def self.create(client: nil, app_id:, enabled: true, event_types:, name:, secret:, url:)
51
+ client ||= Spaceship::ConnectAPI
52
+ resp = client.post_webhook(app_id: app_id, enabled: enabled, event_types: event_types, name: name, secret: secret, url: url)
53
+ return resp.to_models.first
54
+ end
55
+
56
+ def delete!(client: nil)
57
+ client ||= Spaceship::ConnectAPI
58
+ return client.delete_webhook(webhook_id: id)
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1242,6 +1242,44 @@ module Spaceship
1242
1242
  params = tunes_request_client.build_params(filter: filter, includes: includes)
1243
1243
  tunes_request_client.get("#{Version::V1}/reviewRejections", params)
1244
1244
  end
1245
+
1246
+ #
1247
+ # webhooks
1248
+ #
1249
+
1250
+ def get_webhooks(app_id:, filter: {}, includes: nil, limit: nil, sort: nil)
1251
+ params = tunes_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
1252
+ tunes_request_client.get("#{Version::V1}/apps/#{app_id}/webhooks", params)
1253
+ end
1254
+
1255
+ def post_webhook(app_id:, enabled:, event_types:, name:, secret:, url:)
1256
+ body = {
1257
+ data: {
1258
+ type: "webhooks",
1259
+ attributes: {
1260
+ enabled: enabled,
1261
+ eventTypes: event_types,
1262
+ name: name,
1263
+ secret: secret,
1264
+ url: url
1265
+ },
1266
+ relationships: {
1267
+ app: {
1268
+ data: {
1269
+ id: app_id,
1270
+ type: "apps"
1271
+ }
1272
+ }
1273
+ }
1274
+ }
1275
+ }
1276
+
1277
+ tunes_request_client.post("#{Version::V1}/webhooks", body)
1278
+ end
1279
+
1280
+ def delete_webhook(webhook_id:)
1281
+ tunes_request_client.delete("#{Version::V1}/webhooks/#{webhook_id}")
1282
+ end
1245
1283
  end
1246
1284
  end
1247
1285
  end
@@ -74,6 +74,7 @@ require 'spaceship/connect_api/models/resolution_center_message'
74
74
  require 'spaceship/connect_api/models/resolution_center_thread'
75
75
  require 'spaceship/connect_api/models/review_rejection'
76
76
  require 'spaceship/connect_api/models/actor'
77
+ require 'spaceship/connect_api/models/webhook'
77
78
 
78
79
  module Spaceship
79
80
  class ConnectAPI
@@ -42,9 +42,28 @@ module Spaceship
42
42
  # @param music_id [String] the Music Id id (the autogenerated id, not the user specified identifier "music.com.etc...")
43
43
  def self.create(name: nil, apns: nil, device_check: nil, music_id: nil)
44
44
  service_config = {}
45
- service_config[APNS_ID] = [] if apns
46
- service_config[DEVICE_CHECK_ID] = [] if device_check
47
- service_config[MUSIC_KIT_ID] = [music_id] if music_id
45
+
46
+ if apns
47
+ service_config[APNS_ID] = {
48
+ scope: 'team',
49
+ environment: 'all',
50
+ identifiers: {}
51
+ }
52
+ end
53
+
54
+ if device_check
55
+ service_config[DEVICE_CHECK_ID] = {
56
+ identifiers: {}
57
+ }
58
+ end
59
+
60
+ if music_id
61
+ service_config[MUSIC_KIT_ID] = {
62
+ identifiers: {
63
+ music: [music_id]
64
+ }
65
+ }
66
+ end
48
67
 
49
68
  key = client.create_key!(name: name, service_configs: service_config)
50
69
  new(key)
@@ -10,6 +10,7 @@ require_relative 'provisioning_profile'
10
10
  require_relative 'certificate'
11
11
  require_relative 'website_push'
12
12
  require_relative 'persons'
13
+ require_relative 'key'
13
14
 
14
15
  module Spaceship
15
16
  # rubocop:disable Metrics/ClassLength
@@ -780,13 +781,39 @@ module Spaceship
780
781
  def create_key!(name: nil, service_configs: nil)
781
782
  fetch_csrf_token_for_keys
782
783
 
784
+ service_configs_requests = (service_configs || {}).map do |service_id, configs|
785
+ if service_id == Spaceship::Portal::Key::MUSIC_KIT_ID
786
+ {
787
+ serviceId: service_id,
788
+ isNew: true,
789
+ identifiers: configs[:identifiers] || {}
790
+ }
791
+ elsif service_id == Spaceship::Portal::Key::DEVICE_CHECK_ID
792
+ {
793
+ serviceId: service_id,
794
+ isNew: true,
795
+ identifiers: configs[:identifiers] || {}
796
+ }
797
+ elsif service_id == Spaceship::Portal::Key::APNS_ID
798
+ {
799
+ serviceId: service_id,
800
+ isNew: true,
801
+ identifiers: configs[:identifiers] || {},
802
+ environment: configs[:environment] || "all",
803
+ scope: configs[:scope] || "team"
804
+ }
805
+ else
806
+ raise "Unknown service id: #{service_id}"
807
+ end
808
+ end
809
+
783
810
  params = {
784
811
  name: name,
785
- serviceConfigurations: service_configs,
812
+ serviceConfigurationsRequests: service_configs_requests,
786
813
  teamId: team_id
787
814
  }
788
815
 
789
- response = request(:post, 'account/auth/key/create') do |req|
816
+ response = request(:post, 'account/auth/key/v2/create') do |req|
790
817
  req.headers['Content-Type'] = 'application/json'
791
818
  req.body = params.to_json
792
819
  end
metadata CHANGED
@@ -1,40 +1,40 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.230.0
4
+ version: 2.231.1
5
5
  platform: ruby
6
6
  authors:
7
- - Aaron Brager
8
- - Felix Krause
9
- - Satoshi Namai
10
- - Stefan Natchev
7
+ - Jan Piotrowski
8
+ - Josh Holtz
11
9
  - Łukasz Grabowski
12
- - Luka Mirosevic
13
- - Connor Tumbleson
14
- - Danielle Tomlinson
15
- - Max Ott
16
- - Fumiya Nakamura
10
+ - Iulian Onofrei
17
11
  - Olivier Halligon
18
- - Matthew Ellis
19
- - Jorge Revuelta H
20
- - Jérôme Lacoste
21
12
  - Jimmy Dee
13
+ - Satoshi Namai
14
+ - Danielle Tomlinson
22
15
  - Daniel Jankowski
16
+ - Felix Krause
17
+ - Maksym Grebenets
18
+ - Kohki Miki
19
+ - Luka Mirosevic
23
20
  - Joshua Liebowitz
24
21
  - Manu Wallner
25
- - Jan Piotrowski
26
22
  - Roger Oba
23
+ - Max Ott
24
+ - Fumiya Nakamura
25
+ - Jérôme Lacoste
27
26
  - Helmut Januschka
28
- - Andrew McBurney
29
- - Iulian Onofrei
30
- - Josh Holtz
27
+ - Jorge Revuelta H
31
28
  - Manish Rathi
32
- - Kohki Miki
33
- - Maksym Grebenets
29
+ - Stefan Natchev
30
+ - Connor Tumbleson
31
+ - Andrew McBurney
32
+ - Matthew Ellis
33
+ - Aaron Brager
34
34
  autorequire:
35
35
  bindir: bin
36
36
  cert_chain: []
37
- date: 2025-12-18 00:00:00.000000000 Z
37
+ date: 2026-01-20 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: addressable
@@ -110,20 +110,20 @@ dependencies:
110
110
  requirements:
111
111
  - - ">="
112
112
  - !ruby/object:Gem::Version
113
- version: 1.12.0
113
+ version: 1.17.3
114
114
  - - "<"
115
115
  - !ruby/object:Gem::Version
116
- version: 3.0.0
116
+ version: 5.0.0
117
117
  type: :runtime
118
118
  prerelease: false
119
119
  version_requirements: !ruby/object:Gem::Requirement
120
120
  requirements:
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
- version: 1.12.0
123
+ version: 1.17.3
124
124
  - - "<"
125
125
  - !ruby/object:Gem::Version
126
- version: 3.0.0
126
+ version: 5.0.0
127
127
  - !ruby/object:Gem::Dependency
128
128
  name: CFPropertyList
129
129
  requirement: !ruby/object:Gem::Requirement
@@ -826,6 +826,34 @@ dependencies:
826
826
  - - "<"
827
827
  - !ruby/object:Gem::Version
828
828
  version: '2.0'
829
+ - !ruby/object:Gem::Dependency
830
+ name: benchmark
831
+ requirement: !ruby/object:Gem::Requirement
832
+ requirements:
833
+ - - ">="
834
+ - !ruby/object:Gem::Version
835
+ version: 0.1.0
836
+ type: :runtime
837
+ prerelease: false
838
+ version_requirements: !ruby/object:Gem::Requirement
839
+ requirements:
840
+ - - ">="
841
+ - !ruby/object:Gem::Version
842
+ version: 0.1.0
843
+ - !ruby/object:Gem::Dependency
844
+ name: ostruct
845
+ requirement: !ruby/object:Gem::Requirement
846
+ requirements:
847
+ - - ">="
848
+ - !ruby/object:Gem::Version
849
+ version: 0.1.0
850
+ type: :runtime
851
+ prerelease: false
852
+ version_requirements: !ruby/object:Gem::Requirement
853
+ requirements:
854
+ - - ">="
855
+ - !ruby/object:Gem::Version
856
+ version: 0.1.0
829
857
  description: The easiest way to automate beta deployments and releases for your iOS
830
858
  and Android apps
831
859
  email:
@@ -1616,6 +1644,7 @@ files:
1616
1644
  - spaceship/lib/spaceship/connect_api/models/territory_availability.rb
1617
1645
  - spaceship/lib/spaceship/connect_api/models/user.rb
1618
1646
  - spaceship/lib/spaceship/connect_api/models/user_invitation.rb
1647
+ - spaceship/lib/spaceship/connect_api/models/webhook.rb
1619
1648
  - spaceship/lib/spaceship/connect_api/provisioning/client.rb
1620
1649
  - spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb
1621
1650
  - spaceship/lib/spaceship/connect_api/response.rb