fastlane 2.229.0 → 2.232.2

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 (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +98 -92
  3. data/bin/fastlane +2 -2
  4. data/deliver/lib/assets/summary.html.erb +3 -3
  5. data/deliver/lib/deliver/app_screenshot.rb +215 -347
  6. data/deliver/lib/deliver/app_screenshot_iterator.rb +4 -1
  7. data/deliver/lib/deliver/app_screenshot_validator.rb +5 -21
  8. data/deliver/lib/deliver/loader.rb +2 -9
  9. data/deliver/lib/deliver/upload_metadata.rb +5 -0
  10. data/deliver/lib/deliver/upload_screenshots.rb +4 -2
  11. data/fastlane/lib/assets/completions/completion.bash +1 -1
  12. data/fastlane/lib/assets/completions/completion.sh +2 -2
  13. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +19 -14
  14. data/fastlane/lib/fastlane/actions/appium.rb +1 -1
  15. data/fastlane/lib/fastlane/actions/docs/create_app_online.md +6 -3
  16. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +3 -1
  17. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +34 -6
  18. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +2 -0
  19. data/fastlane/lib/fastlane/actions/get_version_number.rb +1 -1
  20. data/fastlane/lib/fastlane/actions/import_certificate.rb +9 -1
  21. data/fastlane/lib/fastlane/actions/increment_build_number.rb +1 -1
  22. data/fastlane/lib/fastlane/actions/install_xcode_plugin.rb +3 -2
  23. data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +1 -1
  24. data/fastlane/lib/fastlane/actions/modify_services.rb +1 -0
  25. data/fastlane/lib/fastlane/actions/notarize.rb +1 -1
  26. data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +1 -1
  27. data/fastlane/lib/fastlane/actions/xcov.rb +1 -7
  28. data/fastlane/lib/fastlane/cli_tools_distributor.rb +19 -1
  29. data/fastlane/lib/fastlane/console.rb +2 -2
  30. data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +4 -4
  31. data/fastlane/lib/fastlane/erb_template_helper.rb +1 -7
  32. data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
  33. data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +20 -20
  34. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -1
  35. data/fastlane/lib/fastlane/version.rb +2 -1
  36. data/fastlane/swift/Actions.swift +1 -1
  37. data/fastlane/swift/Appfile.swift +13 -5
  38. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  39. data/fastlane/swift/Atomic.swift +1 -1
  40. data/fastlane/swift/ControlCommand.swift +5 -4
  41. data/fastlane/swift/Deliverfile.swift +2 -2
  42. data/fastlane/swift/DeliverfileProtocol.swift +265 -68
  43. data/fastlane/swift/Fastlane.swift +140 -88
  44. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +3 -1
  45. data/fastlane/swift/Gymfile.swift +2 -2
  46. data/fastlane/swift/GymfileProtocol.swift +227 -54
  47. data/fastlane/swift/LaneFileProtocol.swift +4 -2
  48. data/fastlane/swift/MainProcess.swift +1 -1
  49. data/fastlane/swift/Matchfile.swift +2 -2
  50. data/fastlane/swift/MatchfileProtocol.swift +225 -58
  51. data/fastlane/swift/OptionalConfigValue.swift +1 -1
  52. data/fastlane/swift/Plugins.swift +1 -1
  53. data/fastlane/swift/Precheckfile.swift +2 -2
  54. data/fastlane/swift/PrecheckfileProtocol.swift +45 -13
  55. data/fastlane/swift/RubyCommand.swift +6 -7
  56. data/fastlane/swift/RubyCommandable.swift +1 -1
  57. data/fastlane/swift/Runner.swift +2 -2
  58. data/fastlane/swift/RunnerArgument.swift +1 -1
  59. data/fastlane/swift/Scanfile.swift +2 -2
  60. data/fastlane/swift/ScanfileProtocol.swift +332 -82
  61. data/fastlane/swift/Screengrabfile.swift +2 -2
  62. data/fastlane/swift/ScreengrabfileProtocol.swift +89 -24
  63. data/fastlane/swift/Snapshotfile.swift +2 -2
  64. data/fastlane/swift/SnapshotfileProtocol.swift +216 -53
  65. data/fastlane/swift/SocketClient.swift +2 -2
  66. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  67. data/fastlane/swift/SocketResponse.swift +1 -1
  68. data/fastlane/swift/main.swift +1 -1
  69. data/fastlane_core/lib/fastlane_core/cert_checker.rb +10 -0
  70. data/fastlane_core/lib/fastlane_core/fastlane_pty.rb +5 -1
  71. data/fastlane_core/lib/fastlane_core/ipa_upload_package_builder.rb +14 -0
  72. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +38 -8
  73. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +3 -1
  74. data/fastlane_core/lib/fastlane_core/project.rb +8 -0
  75. data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +7 -1
  76. data/frameit/lib/frameit/device.rb +2 -2
  77. data/frameit/lib/frameit/device_types.rb +108 -70
  78. data/frameit/lib/frameit/template_finder.rb +1 -1
  79. data/gym/lib/assets/wrap_xcodebuild/xcbuild-safe.sh +1 -0
  80. data/gym/lib/gym/module.rb +9 -4
  81. data/gym/lib/gym/options.rb +20 -2
  82. data/gym/lib/gym/runner.rb +38 -3
  83. data/produce/lib/produce/commands_generator.rb +2 -0
  84. data/produce/lib/produce/developer_center.rb +1 -0
  85. data/produce/lib/produce/service.rb +6 -1
  86. data/scan/lib/scan/error_handler.rb +5 -0
  87. data/scan/lib/scan/options.rb +11 -1
  88. data/scan/lib/scan/test_command_generator.rb +8 -0
  89. data/sigh/lib/assets/resign.sh +6 -3
  90. data/sigh/lib/sigh/local_manage.rb +6 -4
  91. data/sigh/lib/sigh/runner.rb +18 -1
  92. data/snapshot/lib/snapshot/detect_values.rb +1 -1
  93. data/snapshot/lib/snapshot/options.rb +13 -1
  94. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +4 -2
  95. data/spaceship/lib/spaceship/client.rb +32 -2
  96. data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +62 -8
  97. data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +4 -4
  98. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +7 -1
  99. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +16 -16
  100. data/spaceship/lib/spaceship/connect_api/models/build_upload.rb +42 -0
  101. data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +2 -0
  102. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +32 -2
  103. data/spaceship/lib/spaceship/connect_api/models/webhook.rb +62 -0
  104. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +0 -6
  105. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +9 -0
  106. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +38 -0
  107. data/spaceship/lib/spaceship/connect_api.rb +2 -0
  108. data/spaceship/lib/spaceship/errors.rb +8 -6
  109. data/spaceship/lib/spaceship/portal/key.rb +22 -3
  110. data/spaceship/lib/spaceship/portal/portal_client.rb +29 -2
  111. data/spaceship/lib/spaceship/spaceauth_runner.rb +5 -15
  112. data/supply/lib/supply/client.rb +18 -1
  113. data/trainer/lib/trainer/legacy_xcresult.rb +1 -1
  114. data/trainer/lib/trainer/test_parser.rb +1 -1
  115. data/trainer/lib/trainer/xcresult/helper.rb +11 -1
  116. metadata +116 -41
  117. data/fastlane/lib/fastlane/core_ext/bundler_monkey_patch.rb +0 -14
  118. data/fastlane/lib/fastlane/plugins/template/.circleci/config.yml +0 -43
  119. data/fastlane/lib/fastlane/plugins/template/.travis.yml +0 -4
@@ -5,6 +5,7 @@ require 'credentials_manager/appfile_config'
5
5
  require_relative 'module'
6
6
 
7
7
  module Snapshot
8
+ # rubocop:disable Metrics/ClassLength
8
9
  class Options
9
10
  def self.verify_type(item_name, acceptable_types, value)
10
11
  type_ok = [Array, String].any? { |type| value.kind_of?(type) }
@@ -257,6 +258,11 @@ module Snapshot
257
258
  description: "Sets a custom path for Swift Package Manager dependencies",
258
259
  type: String,
259
260
  optional: true),
261
+ FastlaneCore::ConfigItem.new(key: :package_cache_path,
262
+ env_name: "SNAPSHOT_PACKAGE_CACHE_PATH",
263
+ description: "Sets a custom package cache path for Swift Package Manager dependencies",
264
+ type: String,
265
+ optional: true),
260
266
  FastlaneCore::ConfigItem.new(key: :skip_package_dependencies_resolution,
261
267
  env_name: "SNAPSHOT_SKIP_PACKAGE_DEPENDENCIES_RESOLUTION",
262
268
  description: "Skips resolution of Swift Package Manager dependencies",
@@ -264,7 +270,12 @@ module Snapshot
264
270
  default_value: false),
265
271
  FastlaneCore::ConfigItem.new(key: :disable_package_automatic_updates,
266
272
  env_name: "SNAPSHOT_DISABLE_PACKAGE_AUTOMATIC_UPDATES",
267
- description: "Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file",
273
+ description: "Prevents packages from automatically being resolved to versions other than those recorded in the `Package.resolved` file. This translates in the option `-disableAutomaticPackageResolution` being passed to xcodebuild",
274
+ type: Boolean,
275
+ default_value: false),
276
+ FastlaneCore::ConfigItem.new(key: :skip_package_repository_fetches,
277
+ env_name: "SNAPSHOT_SKIP_PACKAGE_REPOSITORY_FETCHES",
278
+ description: "Skips updating package dependencies from their remote. This translates in the option `-skipPackageUpdates` being passed to xcodebuild",
268
279
  type: Boolean,
269
280
  default_value: false),
270
281
  FastlaneCore::ConfigItem.new(key: :package_authorization_provider,
@@ -332,4 +343,5 @@ module Snapshot
332
343
  ]
333
344
  end
334
345
  end
346
+ # rubocop:enable Metrics/ClassLength
335
347
  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
 
@@ -8,34 +8,66 @@ module Spaceship
8
8
  attr_accessor :alcohol_tobacco_or_drug_use_or_references
9
9
  attr_accessor :contests
10
10
  attr_accessor :gambling_simulated
11
- attr_accessor :korea_age_rating_override
11
+ attr_accessor :guns_or_other_weapons
12
+ attr_accessor :horror_or_fear_themes
13
+ attr_accessor :mature_or_suggestive_themes
12
14
  attr_accessor :medical_or_treatment_information
13
15
  attr_accessor :profanity_or_crude_humor
14
16
  attr_accessor :sexual_content_graphic_and_nudity
15
17
  attr_accessor :sexual_content_or_nudity
16
- attr_accessor :horror_or_fear_themes
17
- attr_accessor :mature_or_suggestive_themes
18
18
  attr_accessor :violence_cartoon_or_fantasy
19
19
  attr_accessor :violence_realistic_prolonged_graphic_or_sadistic
20
20
  attr_accessor :violence_realistic
21
21
 
22
22
  # Boolean
23
+ attr_accessor :advertising
24
+ attr_accessor :age_assurance
23
25
  attr_accessor :gambling
26
+ attr_accessor :health_or_wellness_topics
24
27
  attr_accessor :loot_box
28
+ attr_accessor :messaging_and_chat
29
+ attr_accessor :parental_controls
25
30
  attr_accessor :unrestricted_web_access
31
+ attr_accessor :user_generated_content
32
+
33
+ # AgeRating
34
+ attr_accessor :age_rating_override_v2
35
+
36
+ # KoreaAgeRating
37
+ attr_accessor :korea_age_rating_override
26
38
 
27
39
  # KidsAge
28
40
  attr_accessor :kids_age_band
29
41
 
42
+ # URL
43
+ attr_accessor :developer_age_rating_info_url
44
+
30
45
  # Deprecated as of App Store Connect API 1.3
31
46
  attr_accessor :gambling_and_contests
32
47
 
33
48
  module Rating
34
49
  NONE = "NONE"
50
+ INFREQUENT = "INFREQUENT"
35
51
  INFREQUENT_OR_MILD = "INFREQUENT_OR_MILD"
52
+ FREQUENT = "FREQUENT"
36
53
  FREQUENT_OR_INTENSE = "FREQUENT_OR_INTENSE"
37
54
  end
38
55
 
56
+ module AgeRating
57
+ NONE = "NONE"
58
+ NINE_PLUS = "NINE_PLUS"
59
+ THIRTEEN_PLUS = "THIRTEEN_PLUS"
60
+ SIXTEEN_PLUS = "SIXTEEN_PLUS"
61
+ EIGHTEEN_PLUS = "EIGHTEEN_PLUS"
62
+ UNRATED = "UNRATED"
63
+ end
64
+
65
+ module KoreaAgeRating
66
+ NONE = "NONE"
67
+ FIFTEEN_PLUS = "FIFTEEN_PLUS"
68
+ NINETEEN_PLUS = "NINETEEN_PLUS"
69
+ end
70
+
39
71
  module KidsAge
40
72
  FIVE_AND_UNDER = "FIVE_AND_UNDER"
41
73
  SIX_TO_EIGHT = "SIX_TO_EIGHT"
@@ -43,25 +75,34 @@ module Spaceship
43
75
  end
44
76
 
45
77
  attr_mapping({
78
+ "advertising" => "advertising",
79
+ "ageAssurance" => "age_assurance",
80
+ "ageRatingOverrideV2" => "age_rating_override_v2",
46
81
  "alcoholTobaccoOrDrugUseOrReferences" => "alcohol_tobacco_or_drug_use_or_references",
47
82
  "contests" => "contests",
83
+ "developerAgeRatingInfoUrl" => "developer_age_rating_info_url",
48
84
  "gambling" => "gambling",
49
85
  "gamblingSimulated" => "gambling_simulated",
86
+ "gunsOrOtherWeapons" => "guns_or_other_weapons",
87
+ "healthOrWellnessTopics" => "health_or_wellness_topics",
88
+ "horrorOrFearThemes" => "horror_or_fear_themes",
89
+ "kidsAgeBand" => "kids_age_band",
50
90
  "koreaAgeRatingOverride" => "korea_age_rating_override",
51
91
  "lootBox" => "loot_box",
92
+ "matureOrSuggestiveThemes" => "mature_or_suggestive_themes",
52
93
  "medicalOrTreatmentInformation" => "medical_or_treatment_information",
94
+ "messagingAndChat" => "messaging_and_chat",
95
+ "parentalControls" => "parental_controls",
53
96
  "profanityOrCrudeHumor" => "profanity_or_crude_humor",
54
97
  "sexualContentGraphicAndNudity" => "sexual_content_graphic_and_nudity",
55
98
  "sexualContentOrNudity" => "sexual_content_or_nudity",
56
- "horrorOrFearThemes" => "horror_or_fear_themes",
57
- "matureOrSuggestiveThemes" => "mature_or_suggestive_themes",
58
99
  "unrestrictedWebAccess" => "unrestricted_web_access",
100
+ "userGeneratedContent" => "user_generated_content",
59
101
  "violenceCartoonOrFantasy" => "violence_cartoon_or_fantasy",
60
102
  "violenceRealisticProlongedGraphicOrSadistic" => "violence_realistic_prolonged_graphic_or_sadistic",
61
103
  "violenceRealistic" => "violence_realistic",
62
- "kidsAgeBand" => "kids_age_band",
63
104
 
64
- # Deprecated as of App Store Connect API 1.3
105
+ # Deprecated as of App Store Connect API 1.3 - No longer accepted by API
65
106
  "gamblingAndContests" => "gambling_and_contests",
66
107
  })
67
108
 
@@ -124,7 +165,20 @@ module Spaceship
124
165
  end
125
166
 
126
167
  def self.map_value_from_itc(key, value)
127
- if ["gamblingAndContests", "unrestrictedWebAccess"].include?(key)
168
+ boolean_keys = [
169
+ "advertising",
170
+ "ageAssurance",
171
+ "gambling",
172
+ "gamblingAndContests",
173
+ "healthOrWellnessTopics",
174
+ "lootBox",
175
+ "messagingAndChat",
176
+ "parentalControls",
177
+ "unrestrictedWebAccess",
178
+ "userGeneratedContent"
179
+ ]
180
+
181
+ if boolean_keys.include?(key)
128
182
  new_value = LEGACY_BOOLEAN_VALUE_ITC_MAP[value]
129
183
  return value if new_value.nil?
130
184
  return new_value
@@ -33,15 +33,15 @@ module Spaceship
33
33
  client ||= Spaceship::ConnectAPI
34
34
  attributes = reverse_attr_mapping(attributes)
35
35
  client.patch_app_info_localization(app_info_localization_id: id, attributes: attributes)
36
- rescue
37
- raise Spaceship::AppStoreLocalizationError, @locale
36
+ rescue => error
37
+ raise Spaceship::AppStoreLocalizationError.new(@locale, error)
38
38
  end
39
39
 
40
40
  def delete!(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
41
41
  client ||= Spaceship::ConnectAPI
42
42
  client.delete_app_info_localization(app_info_localization_id: id)
43
- rescue
44
- raise Spaceship::AppStoreLocalizationError, @locale
43
+ rescue => error
44
+ raise Spaceship::AppStoreLocalizationError.new(@locale, error)
45
45
  end
46
46
  end
47
47
  end
@@ -43,12 +43,15 @@ module Spaceship
43
43
  APP_WATCH_SERIES_3 = "APP_WATCH_SERIES_3"
44
44
  APP_WATCH_SERIES_4 = "APP_WATCH_SERIES_4"
45
45
  APP_WATCH_SERIES_7 = "APP_WATCH_SERIES_7"
46
+ APP_WATCH_SERIES_10 = "APP_WATCH_SERIES_10"
46
47
  APP_WATCH_ULTRA = "APP_WATCH_ULTRA"
47
48
 
48
49
  APP_APPLE_TV = "APP_APPLE_TV"
49
50
 
50
51
  APP_DESKTOP = "APP_DESKTOP"
51
52
 
53
+ APP_APPLE_VISION_PRO = "APP_APPLE_VISION_PRO"
54
+
52
55
  ALL_IMESSAGE = [
53
56
  IMESSAGE_APP_IPHONE_40,
54
57
  IMESSAGE_APP_IPHONE_47,
@@ -98,9 +101,12 @@ module Spaceship
98
101
  APP_WATCH_SERIES_3,
99
102
  APP_WATCH_SERIES_4,
100
103
  APP_WATCH_SERIES_7,
104
+ APP_WATCH_SERIES_10,
101
105
  APP_WATCH_ULTRA,
102
106
 
103
- APP_DESKTOP
107
+ APP_DESKTOP,
108
+
109
+ APP_APPLE_VISION_PRO
104
110
  ]
105
111
  end
106
112
 
@@ -44,31 +44,31 @@ module Spaceship
44
44
  client ||= Spaceship::ConnectAPI
45
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)
46
46
  return resp.to_models
47
- rescue
48
- raise Spaceship::AppStoreLocalizationError, @locale
47
+ rescue => error
48
+ raise Spaceship::AppStoreLocalizationError.new(@locale, error)
49
49
  end
50
50
 
51
51
  def self.all(client: nil, app_store_version_id: nil, filter: {}, includes: nil, limit: nil, sort: nil)
52
52
  client ||= Spaceship::ConnectAPI
53
53
  resp = client.get_app_store_version_localizations(app_store_version_id: app_store_version_id, filter: filter, includes: includes, limit: limit, sort: sort)
54
54
  return resp.to_models
55
- rescue
56
- raise Spaceship::AppStoreLocalizationError, @locale
55
+ rescue => error
56
+ raise Spaceship::AppStoreLocalizationError.new(@locale, error)
57
57
  end
58
58
 
59
59
  def update(client: nil, attributes: nil)
60
60
  client ||= Spaceship::ConnectAPI
61
61
  attributes = reverse_attr_mapping(attributes)
62
62
  client.patch_app_store_version_localization(app_store_version_localization_id: id, attributes: attributes)
63
- rescue
64
- raise Spaceship::AppStoreLocalizationError, @locale
63
+ rescue => error
64
+ raise Spaceship::AppStoreLocalizationError.new(@locale, error)
65
65
  end
66
66
 
67
67
  def delete!(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
68
68
  client ||= Spaceship::ConnectAPI
69
69
  client.delete_app_store_version_localization(app_store_version_localization_id: id)
70
- rescue
71
- raise Spaceship::AppStoreLocalizationError, @locale
70
+ rescue => error
71
+ raise Spaceship::AppStoreLocalizationError.new(@locale, error)
72
72
  end
73
73
 
74
74
  #
@@ -80,16 +80,16 @@ module Spaceship
80
80
  filter ||= {}
81
81
  filter["appStoreVersionLocalization"] = id
82
82
  return Spaceship::ConnectAPI::AppPreviewSet.all(client: client, filter: filter, includes: includes, limit: limit, sort: sort)
83
- rescue
84
- raise Spaceship::AppStoreAppPreviewError, @locale
83
+ rescue => error
84
+ raise Spaceship::AppStoreAppPreviewError.new(@locale, error)
85
85
  end
86
86
 
87
87
  def create_app_preview_set(client: nil, attributes: nil)
88
88
  client ||= Spaceship::ConnectAPI
89
89
  resp = client.post_app_preview_set(app_store_version_localization_id: id, attributes: attributes)
90
90
  return resp.to_models.first
91
- rescue
92
- raise Spaceship::AppStoreAppPreviewError, @locale
91
+ rescue => error
92
+ raise Spaceship::AppStoreAppPreviewError.new(@locale, error)
93
93
  end
94
94
 
95
95
  #
@@ -99,16 +99,16 @@ module Spaceship
99
99
  def get_app_screenshot_sets(client: nil, filter: {}, includes: "appScreenshots", limit: nil, sort: nil)
100
100
  client ||= Spaceship::ConnectAPI
101
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
102
+ rescue => error
103
+ raise Spaceship::AppStoreScreenshotError.new(@locale, error)
104
104
  end
105
105
 
106
106
  def create_app_screenshot_set(client: nil, attributes: nil)
107
107
  client ||= Spaceship::ConnectAPI
108
108
  resp = client.post_app_screenshot_set(app_store_version_localization_id: id, attributes: attributes)
109
109
  return resp.to_models.first
110
- rescue
111
- raise Spaceship::AppStoreScreenshotError, @locale
110
+ rescue => error
111
+ raise Spaceship::AppStoreScreenshotError.new(@locale, error)
112
112
  end
113
113
  end
114
114
  end
@@ -0,0 +1,42 @@
1
+ require_relative '../model'
2
+ module Spaceship
3
+ class ConnectAPI
4
+ class BuildUpload
5
+ include Spaceship::ConnectAPI::Model
6
+
7
+ attr_accessor :cf_build_version
8
+ attr_accessor :cf_build_short_version_string
9
+ attr_accessor :created_date
10
+ attr_accessor :state
11
+ attr_accessor :platform
12
+ attr_accessor :uploaded_date
13
+
14
+ attr_mapping({
15
+ "cfBundleVersion" => "cf_build_version",
16
+ "cfBundleShortVersionString" => "cf_build_short_version_string",
17
+ "createdDate" => "created_date",
18
+ "state" => "state",
19
+ "platform" => "platform",
20
+ "uploadedDate" => "uploaded_date"
21
+ })
22
+
23
+ def self.type
24
+ return "buildUploads"
25
+ end
26
+
27
+ #
28
+ # API
29
+ #
30
+
31
+ def self.all(client: nil, app_id: nil, version: nil, build_number: nil)
32
+ client ||= Spaceship::ConnectAPI
33
+ resps = client.get_build_uploads(
34
+ app_id: app_id,
35
+ filter: { cfBundleShortVersionString: version, cfBundleVersion: build_number },
36
+ limit: 1
37
+ ).all_pages
38
+ return resps.flat_map(&:to_models)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -77,6 +77,8 @@ module Spaceship
77
77
 
78
78
  # Undocumented as of 2020-06-09
79
79
  MARZIPAN = "MARZIPAN" # Catalyst
80
+ # Undocumented as of 2025-10-15
81
+ DECLARED_AGE_RANGE = "DECLARED_AGE_RANGE"
80
82
  end
81
83
 
82
84
  module Settings
@@ -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
@@ -77,12 +77,6 @@ module Spaceship
77
77
  type: "bundleIds",
78
78
  id: bundle_id_id
79
79
  }
80
- },
81
- capability: {
82
- data: {
83
- type: "capabilities",
84
- id: capability_type
85
- }
86
80
  }
87
81
  }
88
82
  }
@@ -494,6 +494,15 @@ module Spaceship
494
494
  test_flight_request_client.get("#{Version::V1}/apps/#{app_id}/buildDeliveries", params)
495
495
  end
496
496
 
497
+ #
498
+ # buildUploads
499
+ #
500
+
501
+ def get_build_uploads(app_id:, filter: {}, includes: nil, limit: nil, sort: nil)
502
+ params = test_flight_request_client.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
503
+ test_flight_request_client.get("#{Version::V1}/apps/#{app_id}/buildUploads", params)
504
+ end
505
+
497
506
  #
498
507
  # preReleaseVersions
499
508
  #
@@ -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
@@ -31,6 +31,7 @@ require 'spaceship/connect_api/models/beta_tester'
31
31
  require 'spaceship/connect_api/models/beta_tester_metric'
32
32
  require 'spaceship/connect_api/models/build'
33
33
  require 'spaceship/connect_api/models/build_delivery'
34
+ require 'spaceship/connect_api/models/build_upload'
34
35
  require 'spaceship/connect_api/models/build_beta_detail'
35
36
  require 'spaceship/connect_api/models/build_bundle'
36
37
  require 'spaceship/connect_api/models/build_bundle_file_sizes'
@@ -74,6 +75,7 @@ require 'spaceship/connect_api/models/resolution_center_message'
74
75
  require 'spaceship/connect_api/models/resolution_center_thread'
75
76
  require 'spaceship/connect_api/models/review_rejection'
76
77
  require 'spaceship/connect_api/models/actor'
78
+ require 'spaceship/connect_api/models/webhook'
77
79
 
78
80
  module Spaceship
79
81
  class ConnectAPI