fastlane 2.170.0 → 2.175.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 (134) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +74 -74
  3. data/cert/lib/cert/options.rb +2 -2
  4. data/deliver/lib/deliver/app_screenshot.rb +5 -7
  5. data/deliver/lib/deliver/app_screenshot_validator.rb +108 -0
  6. data/deliver/lib/deliver/commands_generator.rb +1 -1
  7. data/deliver/lib/deliver/loader.rb +13 -29
  8. data/deliver/lib/deliver/options.rb +2 -2
  9. data/deliver/lib/deliver/setup.rb +8 -3
  10. data/deliver/lib/deliver/upload_metadata.rb +2 -0
  11. data/deliver/lib/deliver/upload_screenshots.rb +2 -1
  12. data/fastlane/lib/fastlane/actions/adb.rb +1 -1
  13. data/fastlane/lib/fastlane/actions/add_git_tag.rb +12 -3
  14. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +2 -2
  15. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +1 -0
  16. data/fastlane/lib/fastlane/actions/appetize.rb +13 -1
  17. data/fastlane/lib/fastlane/actions/artifactory.rb +36 -3
  18. data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +10 -2
  19. data/fastlane/lib/fastlane/actions/build_app.rb +3 -1
  20. data/fastlane/lib/fastlane/actions/carthage.rb +22 -0
  21. data/fastlane/lib/fastlane/actions/cocoapods.rb +15 -1
  22. data/fastlane/lib/fastlane/actions/create_pull_request.rb +16 -1
  23. data/fastlane/lib/fastlane/actions/create_xcframework.rb +118 -0
  24. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +1 -1
  25. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +1 -1
  26. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +8 -2
  27. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +5 -1
  28. data/fastlane/lib/fastlane/actions/download_app_privacy_details_from_app_store.rb +142 -0
  29. data/fastlane/lib/fastlane/actions/download_dsyms.rb +5 -16
  30. data/fastlane/lib/fastlane/actions/git_commit.rb +7 -3
  31. data/fastlane/lib/fastlane/actions/github_api.rb +14 -3
  32. data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +2 -2
  33. data/fastlane/lib/fastlane/actions/nexus_upload.rb +1 -0
  34. data/fastlane/lib/fastlane/actions/pod_push.rb +9 -0
  35. data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -1
  36. data/fastlane/lib/fastlane/actions/register_device.rb +3 -3
  37. data/fastlane/lib/fastlane/actions/register_devices.rb +4 -3
  38. data/fastlane/lib/fastlane/actions/set_changelog.rb +2 -2
  39. data/fastlane/lib/fastlane/actions/set_github_release.rb +21 -8
  40. data/fastlane/lib/fastlane/actions/slack.rb +4 -5
  41. data/fastlane/lib/fastlane/actions/spm.rb +2 -2
  42. data/fastlane/lib/fastlane/actions/swiftlint.rb +4 -4
  43. data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +1 -1
  44. data/fastlane/lib/fastlane/actions/upload_app_privacy_details_to_app_store.rb +4 -2
  45. data/fastlane/lib/fastlane/cli_tools_distributor.rb +3 -0
  46. data/fastlane/lib/fastlane/documentation/actions_list.rb +2 -2
  47. data/fastlane/lib/fastlane/helper/adb_helper.rb +1 -1
  48. data/fastlane/lib/fastlane/helper/gem_helper.rb +2 -2
  49. data/fastlane/lib/fastlane/version.rb +1 -1
  50. data/fastlane/swift/Actions.swift +1 -1
  51. data/fastlane/swift/Appfile.swift +1 -1
  52. data/fastlane/swift/ArgumentProcessor.swift +1 -1
  53. data/fastlane/swift/ControlCommand.swift +1 -1
  54. data/fastlane/swift/Deliverfile.swift +2 -2
  55. data/fastlane/swift/DeliverfileProtocol.swift +2 -2
  56. data/fastlane/swift/Fastlane.swift +213 -38
  57. data/fastlane/swift/Gymfile.swift +2 -2
  58. data/fastlane/swift/GymfileProtocol.swift +11 -3
  59. data/fastlane/swift/LaneFileProtocol.swift +1 -1
  60. data/fastlane/swift/MainProcess.swift +1 -1
  61. data/fastlane/swift/Matchfile.swift +2 -2
  62. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  63. data/fastlane/swift/Plugins.swift +1 -1
  64. data/fastlane/swift/Precheckfile.swift +2 -2
  65. data/fastlane/swift/PrecheckfileProtocol.swift +6 -2
  66. data/fastlane/swift/RubyCommand.swift +1 -1
  67. data/fastlane/swift/RubyCommandable.swift +1 -1
  68. data/fastlane/swift/Runner.swift +2 -2
  69. data/fastlane/swift/RunnerArgument.swift +1 -1
  70. data/fastlane/swift/Scanfile.swift +2 -2
  71. data/fastlane/swift/ScanfileProtocol.swift +14 -2
  72. data/fastlane/swift/Screengrabfile.swift +2 -2
  73. data/fastlane/swift/ScreengrabfileProtocol.swift +2 -2
  74. data/fastlane/swift/Snapshotfile.swift +2 -2
  75. data/fastlane/swift/SnapshotfileProtocol.swift +15 -3
  76. data/fastlane/swift/SocketClient.swift +1 -1
  77. data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
  78. data/fastlane/swift/SocketResponse.swift +1 -1
  79. data/fastlane/swift/formatting/Brewfile.lock.json +20 -14
  80. data/fastlane/swift/main.swift +1 -1
  81. data/fastlane_core/lib/fastlane_core/command_executor.rb +3 -9
  82. data/fastlane_core/lib/fastlane_core/configuration/commander_generator.rb +1 -1
  83. data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +23 -0
  84. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +9 -5
  85. data/fastlane_core/lib/fastlane_core/helper.rb +28 -7
  86. data/fastlane_core/lib/fastlane_core/ipa_file_analyser.rb +41 -16
  87. data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +3 -4
  88. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +1 -1
  89. data/fastlane_core/lib/fastlane_core/project.rb +41 -14
  90. data/fastlane_core/lib/fastlane_core/update_checker/update_checker.rb +2 -2
  91. data/frameit/lib/frameit/device_types.rb +7 -1
  92. data/gym/lib/gym/error_handler.rb +8 -0
  93. data/gym/lib/gym/generators/build_command_generator.rb +3 -1
  94. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +2 -2
  95. data/gym/lib/gym/options.rb +12 -2
  96. data/match/lib/match/encryption/openssl.rb +4 -2
  97. data/match/lib/match/nuke.rb +5 -0
  98. data/match/lib/match/options.rb +2 -2
  99. data/match/lib/match/storage/git_storage.rb +14 -10
  100. data/pilot/lib/pilot/options.rb +2 -2
  101. data/precheck/lib/precheck/options.rb +8 -3
  102. data/precheck/lib/precheck/rule_processor.rb +1 -1
  103. data/precheck/lib/precheck/runner.rb +1 -1
  104. data/scan/lib/scan/options.rb +15 -0
  105. data/scan/lib/scan/runner.rb +6 -1
  106. data/scan/lib/scan/slack_poster.rb +4 -1
  107. data/scan/lib/scan/test_command_generator.rb +3 -1
  108. data/screengrab/lib/screengrab/android_environment.rb +2 -2
  109. data/screengrab/lib/screengrab/runner.rb +2 -0
  110. data/sigh/lib/sigh/options.rb +2 -2
  111. data/sigh/lib/sigh/runner.rb +1 -1
  112. data/snapshot/lib/assets/SnapshotHelper.swift +1 -1
  113. data/snapshot/lib/snapshot/options.rb +17 -2
  114. data/snapshot/lib/snapshot/update.rb +1 -1
  115. data/spaceship/README.md +2 -2
  116. data/spaceship/lib/spaceship/client.rb +14 -1
  117. data/spaceship/lib/spaceship/connect_api/api_client.rb +17 -2
  118. data/spaceship/lib/spaceship/connect_api/models/app.rb +6 -0
  119. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +7 -1
  120. data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +9 -0
  121. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +24 -0
  122. data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +26 -4
  123. data/spaceship/lib/spaceship/connect_api/models/device.rb +26 -0
  124. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +53 -0
  125. data/spaceship/lib/spaceship/connect_api/response.rb +3 -1
  126. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +12 -0
  127. data/spaceship/lib/spaceship/connect_api/token.rb +1 -1
  128. data/spaceship/lib/spaceship/playground.rb +2 -2
  129. data/spaceship/lib/spaceship/tunes/tunes_client.rb +2 -2
  130. data/spaceship/lib/spaceship/two_step_or_factor_client.rb +1 -0
  131. data/spaceship/lib/spaceship/upgrade_2fa_later_client.rb +91 -0
  132. metadata +51 -21
  133. data/fastlane/lib/fastlane/actions/.download_dsyms.rb.swp +0 -0
  134. data/spaceship/lib/spaceship/connect_api/models/.app_data_usage_data_protection.rb.swp +0 -0
@@ -8,7 +8,7 @@ module Snapshot
8
8
  def self.find_helper
9
9
  paths = Dir["./**/SnapshotHelper.swift"] + Dir["./**/SnapshotHelperXcode8.swift"]
10
10
  # exclude assets in gym
11
- paths.reject { |p| p.include?("snapshot/lib/assets/") }
11
+ paths.reject { |p| p.include?("snapshot/lib/assets/") || p.include?("DerivedData") }
12
12
  end
13
13
 
14
14
  def update(force: false)
data/spaceship/README.md CHANGED
@@ -83,7 +83,7 @@ Using spaceship, the execution time of [_sigh_](https://docs.fastlane.tools/acti
83
83
 
84
84
  _spaceship_ is part of _fastlane_:
85
85
 
86
- sudo gem install fastlane
86
+ gem install fastlane
87
87
 
88
88
  # Usage
89
89
 
@@ -93,7 +93,7 @@ To try _spaceship_, just run `fastlane spaceship`. It will automatically start t
93
93
 
94
94
  ![assets/docs/Playground.png](assets/docs/Playground.png)
95
95
 
96
- This requires you to install `pry` using `sudo gem install pry`. `pry` is not installed by default, as most [_fastlane_](https://fastlane.tools) users won't need the `spaceship playground`. You can add the `pry` dependency to your `Gemfile`.
96
+ This requires you to install `pry` using `gem install pry`. `pry` is not installed by default, as most [_fastlane_](https://fastlane.tools) users won't need the `spaceship playground`. You can add the `pry` dependency to your `Gemfile`.
97
97
 
98
98
  ## Apple Developer Portal API
99
99
 
@@ -403,6 +403,7 @@ module Spaceship
403
403
  # This will also handle 2 step verification and 2 factor authentication
404
404
  #
405
405
  # It is called in `send_login_request` of sub classes (which the method `login`, above, transferred over to via `do_login`)
406
+ # rubocop:disable Metrics/PerceivedComplexity
406
407
  def send_shared_login_request(user, password)
407
408
  # Check if we have a cached/valid session
408
409
  #
@@ -506,9 +507,19 @@ module Spaceship
506
507
  # User Credentials are wrong
507
508
  raise InvalidUserCredentialsError.new, "Invalid username and password combination. Used '#{user}' as the username."
508
509
  elsif response.status == 412 && AUTH_TYPES.include?(response.body["authType"])
510
+
511
+ if try_upgrade_2fa_later(response)
512
+ store_cookie
513
+ fetch_olympus_session
514
+ return true
515
+ end
516
+
509
517
  # Need to acknowledge Apple ID and Privacy statement - https://github.com/fastlane/fastlane/issues/12577
510
518
  # Looking for status of 412 might be enough but might be safer to keep looking only at what is being reported
511
- raise AppleIDAndPrivacyAcknowledgementNeeded.new, "Need to acknowledge to Apple's Apple ID and Privacy statement. Please manually log into https://appleid.apple.com (or https://appstoreconnect.apple.com) to acknowledge the statement."
519
+ raise AppleIDAndPrivacyAcknowledgementNeeded.new, "Need to acknowledge to Apple's Apple ID and Privacy statement. " \
520
+ "Please manually log into https://appleid.apple.com (or https://appstoreconnect.apple.com) to acknowledge the statement. " \
521
+ "Your account might also be asked to upgrade to 2FA. " \
522
+ "Set SPACESHIP_SKIP_2FA_UPGRADE=1 for fastlane to automaticaly bypass 2FA upgrade if possible."
512
523
  elsif (response['Set-Cookie'] || "").include?("itctx")
513
524
  raise "Looks like your Apple ID is not enabled for App Store Connect, make sure to be able to login online"
514
525
  else
@@ -517,6 +528,7 @@ module Spaceship
517
528
  end
518
529
  end
519
530
  end
531
+ # rubocop:enable Metrics/PerceivedComplexity
520
532
 
521
533
  # Get the `itctx` from the new (22nd May 2017) API endpoint "olympus"
522
534
  # Update (29th March 2019) olympus migrates to new appstoreconnect API
@@ -925,3 +937,4 @@ module Spaceship
925
937
  end
926
938
 
927
939
  require 'spaceship/two_step_or_factor_client'
940
+ require 'spaceship/upgrade_2fa_later_client'
@@ -196,7 +196,7 @@ module Spaceship
196
196
 
197
197
  store_csrf_tokens(response)
198
198
 
199
- return Spaceship::ConnectAPI::Response.new(body: response.body, status: response.status, client: self)
199
+ return Spaceship::ConnectAPI::Response.new(body: response.body, status: response.status, headers: response.headers, client: self)
200
200
  end
201
201
 
202
202
  def handle_401(response)
@@ -247,8 +247,23 @@ module Spaceship
247
247
  # ]
248
248
  # }
249
249
 
250
+ # Detail is missing in this response making debugging super hard
251
+ # {"errors" =>
252
+ # [
253
+ # {
254
+ # "id"=>"80ea6cff-0043-4543-9cd1-3e26b0fce383",
255
+ # "status"=>"409",
256
+ # "code"=>"ENTITY_ERROR.RELATIONSHIP.INVALID",
257
+ # "title"=>"The provided entity includes a relationship with an invalid value",
258
+ # "source"=>{
259
+ # "pointer"=>"/data/relationships/primarySubcategoryOne"
260
+ # }
261
+ # }
262
+ # ]
263
+ # }
264
+
250
265
  return response.body['errors'].map do |error|
251
- messages = [[error['title'], error['detail']].compact.join(" - ")]
266
+ messages = [[error['title'], error['detail'], error.dig("source", "pointer")].compact.join(" - ")]
252
267
 
253
268
  meta = error["meta"] || {}
254
269
  associated_errors = meta["associatedErrors"] || {}
@@ -144,6 +144,12 @@ module Spaceship
144
144
  end.first
145
145
  end
146
146
 
147
+ def fetch_latest_app_info(client: nil, includes: Spaceship::ConnectAPI::AppInfo::ESSENTIAL_INCLUDES)
148
+ client ||= Spaceship::ConnectAPI
149
+ resp = client.get_app_infos(app_id: id, includes: includes)
150
+ return resp.to_models.first
151
+ end
152
+
147
153
  #
148
154
  # Available Territories
149
155
  #
@@ -21,6 +21,9 @@ module Spaceship
21
21
  attr_accessor :created_date
22
22
 
23
23
  attr_accessor :app_store_version_submission
24
+ attr_accessor :app_store_version_phased_release
25
+ attr_accessor :app_store_review_detail
26
+ attr_accessor :app_store_version_localizations
24
27
 
25
28
  module AppStoreState
26
29
  READY_FOR_SALE = "READY_FOR_SALE"
@@ -58,7 +61,10 @@ module Spaceship
58
61
  "createdDate" => "created_date",
59
62
 
60
63
  "appStoreVersionSubmission" => "app_store_version_submission",
61
- "build" => "build"
64
+ "build" => "build",
65
+ "appStoreVersionPhasedRelease" => "app_store_version_phased_release",
66
+ "appStoreReviewDetail" => "app_store_review_detail",
67
+ "appStoreVersionLocalizations" => "app_store_version_localizations"
62
68
  })
63
69
 
64
70
  ESSENTIAL_INCLUDES = [
@@ -38,6 +38,15 @@ module Spaceship
38
38
  return client.post_bulk_beta_tester_assignments(beta_group_id: id, beta_testers: beta_testers)
39
39
  end
40
40
 
41
+ def update(client: nil, attributes: nil)
42
+ return if attributes.empty?
43
+
44
+ client ||= Spaceship::ConnectAPI
45
+
46
+ attributes = reverse_attr_mapping(attributes)
47
+ return client.patch_group(group_id: id, attributes: attributes).first
48
+ end
49
+
41
50
  def delete!
42
51
  return Spaceship::ConnectAPI.delete_beta_group(group_id: id)
43
52
  end
@@ -56,6 +56,30 @@ module Spaceship
56
56
  client ||= Spaceship::ConnectAPI
57
57
  return client.get_bundle_id(bundle_id_id: bundle_id_id, includes: includes).first
58
58
  end
59
+
60
+ def self.create(client: nil, name: nil, platform: nil, identifier: nil, seed_id: nil)
61
+ client ||= Spaceship::ConnectAPI
62
+ resp = client.post_bundle_id(name: name, platform: platform, identifier: identifier, seed_id: seed_id)
63
+ return resp.to_models.first
64
+ end
65
+
66
+ #
67
+ # BundleIdsCapabilities
68
+ #
69
+
70
+ def get_capabilities(client: nil, includes: nil)
71
+ client ||= Spaceship::ConnectAPI
72
+ resp = client.get_bundle_id_capabilities(bundle_id_id: id, includes: includes)
73
+ return resp.to_models
74
+ end
75
+
76
+ def create_capability(capability_type, settings: [], client: nil)
77
+ raise "capability_type is required " if capability_type.nil?
78
+
79
+ client ||= Spaceship::ConnectAPI
80
+ resp = client.post_bundle_id_capability(bundle_id_id: id, capability_type: capability_type, settings: settings)
81
+ return resp.to_models.first
82
+ end
59
83
  end
60
84
  end
61
85
  end
@@ -41,6 +41,21 @@ module Spaceship
41
41
  MARZIPAN = "MARZIPAN" # Catalyst
42
42
  end
43
43
 
44
+ module Settings
45
+ ICLOUD_VERSION = "ICLOUD_VERSION"
46
+ DATA_PROTECTION_PERMISSION_LEVEL = "DATA_PROTECTION_PERMISSION_LEVEL"
47
+ APPLE_ID_AUTH_APP_CONSENT = "APPLE_ID_AUTH_APP_CONSENT"
48
+ end
49
+
50
+ module Options
51
+ XCODE_5 = "XCODE_5"
52
+ XCODE_6 = "XCODE_6"
53
+ COMPLETE_PROTECTION = "COMPLETE_PROTECTION"
54
+ PROTECTED_UNLESS_OPEN = "PROTECTED_UNLESS_OPEN"
55
+ PROTECTED_UNTIL_FIRST_USER_AUTH = "PROTECTED_UNTIL_FIRST_USER_AUTH"
56
+ PRIMARY_APP_CONSENT = "PRIMARY_APP_CONSENT"
57
+ end
58
+
44
59
  def self.type
45
60
  return "bundleIdCapabilities"
46
61
  end
@@ -59,14 +74,21 @@ module Spaceship
59
74
  # API
60
75
  #
61
76
 
62
- def self.all(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
77
+ def self.all(client: nil, bundle_id_id:, limit: nil)
78
+ client ||= Spaceship::ConnectAPI
79
+ resp = client.get_bundle_id_capabilities(bundle_id_id: bundle_id_id, limit: limit).all_pages
80
+ return resp.flat_map(&:to_models)
81
+ end
82
+
83
+ def self.create(client: nil, bundle_id_id:, capability_type:, settings: [])
63
84
  client ||= Spaceship::ConnectAPI
64
- return client.get_users(filter: filter, includes: includes)
85
+ resp = client.post_bundle_id_capability(bundle_id_id: bundle_id_id, capability_type: capability_type, settings: settings)
86
+ return resp.to_models.first
65
87
  end
66
88
 
67
- def self.find(client: nil, email: nil, includes: nil)
89
+ def delete!(client: nil, filter: {}, includes: nil, limit: nil, sort: nil)
68
90
  client ||= Spaceship::ConnectAPI
69
- return all(client: client, filter: { email: email }, includes: includes)
91
+ client.delete_bundle_id_capability(bundle_id_capability_id: id)
70
92
  end
71
93
  end
72
94
  end
@@ -54,6 +54,32 @@ module Spaceship
54
54
  return resps.flat_map(&:to_models)
55
55
  end
56
56
 
57
+ # @param client [ConnectAPI] ConnectAPI client.
58
+ # @param platform [String] The platform of the device.
59
+ # @param include_disabled [Bool] Whether to include disable devices. false by default.
60
+ # @return (Device) Find a device based on the UDID of the device. nil if no device was found.
61
+ def self.find_by_udid(device_udid, client: nil, platform: nil, include_disabled: false)
62
+ self.all(client: client).find do |device|
63
+ device.udid.casecmp(device_udid) == 0 && (include_disabled ? true : device.enabled?)
64
+ end
65
+ end
66
+
67
+ # @param client [ConnectAPI] ConnectAPI client.
68
+ # @param name [String] The name to be assigned to the device, if it needs to be created.
69
+ # @param platform [String] The platform of the device.
70
+ # @param include_disabled [Bool] Whether to include disable devices. false by default.
71
+ # @return (Device) Find a device based on the UDID of the device. If no device was found, nil if no device was found.
72
+ def self.find_or_create(device_udid, client: nil, name: nil, platform: nil, include_disabled: false)
73
+ existing = self.find_by_udid(device_udid, client: client, platform: platform)
74
+ return existing if existing
75
+ return self.create(client: client, name: name, platform: platform, udid: device_udid)
76
+ end
77
+
78
+ # @param client [ConnectAPI] ConnectAPI client.
79
+ # @param name [String] The name to be assigned to the device.
80
+ # @param platform [String] The platform of the device.
81
+ # @param udid [String] The udid of the device being created.
82
+ # @return (Device) Find a device based on the UDID of the device. nil if no device was found.
57
83
  def self.create(client: nil, name: nil, platform: nil, udid: nil)
58
84
  client ||= Spaceship::ConnectAPI
59
85
  resp = client.post_device(name: name, platform: platform, udid: udid)
@@ -27,6 +27,59 @@ module Spaceship
27
27
  provisioning_request_client.get("bundleIds/#{bundle_id_id}", params)
28
28
  end
29
29
 
30
+ def post_bundle_id(name:, platform:, identifier:, seed_id:)
31
+ attributes = {
32
+ name: name,
33
+ platform: platform,
34
+ identifier: identifier,
35
+ seedId: seed_id
36
+ }
37
+
38
+ body = {
39
+ data: {
40
+ attributes: attributes,
41
+ type: "bundleIds"
42
+ }
43
+ }
44
+
45
+ provisioning_request_client.post("bundleIds", body)
46
+ end
47
+
48
+ #
49
+ # bundleIdCapability
50
+ #
51
+
52
+ def get_bundle_id_capabilities(bundle_id_id:, includes: nil, limit: nil, sort: nil)
53
+ params = provisioning_request_client.build_params(filter: nil, includes: includes, limit: limit, sort: sort)
54
+ provisioning_request_client.get("bundleIds/#{bundle_id_id}/bundleIdCapabilities", params)
55
+ end
56
+
57
+ def post_bundle_id_capability(bundle_id_id:, capability_type:, settings: [])
58
+ body = {
59
+ data: {
60
+ attributes: {
61
+ capabilityType: capability_type,
62
+ settings: settings
63
+ },
64
+ type: "bundleIdCapabilities",
65
+ relationships: {
66
+ bundleId: {
67
+ data: {
68
+ type: "bundleIds",
69
+ id: bundle_id_id
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
75
+
76
+ provisioning_request_client.post("bundleIdCapabilities", body)
77
+ end
78
+
79
+ def delete_bundle_id_capability(bundle_id_capability_id:)
80
+ provisioning_request_client.delete("bundleIdCapabilities/#{bundle_id_capability_id}")
81
+ end
82
+
30
83
  #
31
84
  # certificates
32
85
  #
@@ -6,11 +6,13 @@ module Spaceship
6
6
  include Enumerable
7
7
  attr_reader :body
8
8
  attr_reader :status
9
+ attr_reader :headers
9
10
  attr_reader :client
10
11
 
11
- def initialize(body: nil, status: nil, client: nil)
12
+ def initialize(body: nil, status: nil, headers: nil, client: nil)
12
13
  @body = body
13
14
  @status = status
15
+ @headers = headers
14
16
  @client = client
15
17
  end
16
18
 
@@ -214,6 +214,18 @@ module Spaceship
214
214
  test_flight_request_client.post("betaGroups", body)
215
215
  end
216
216
 
217
+ def patch_group(group_id: nil, attributes: {})
218
+ body = {
219
+ data: {
220
+ attributes: attributes,
221
+ id: group_id,
222
+ type: "betaGroups"
223
+ }
224
+ }
225
+
226
+ test_flight_request_client.patch("betaGroups/#{group_id}", body)
227
+ end
228
+
217
229
  def delete_beta_group(group_id: nil)
218
230
  raise "group_id is nil" if group_id.nil?
219
231
 
@@ -40,7 +40,7 @@ module Spaceship
40
40
  self.create(json)
41
41
  end
42
42
 
43
- def self.create(key_id: nil, issuer_id: nil, filepath: nil, key: nil, is_key_content_base64: false, duration: nil, in_house: nil)
43
+ def self.create(key_id: nil, issuer_id: nil, filepath: nil, key: nil, is_key_content_base64: false, duration: nil, in_house: nil, **)
44
44
  key_id ||= ENV['SPACESHIP_CONNECT_API_KEY_ID']
45
45
  issuer_id ||= ENV['SPACESHIP_CONNECT_API_ISSUER_ID']
46
46
  filepath ||= ENV['SPACESHIP_CONNECT_API_KEY_FILEPATH']
@@ -13,8 +13,8 @@ module Spaceship
13
13
  rescue Gem::LoadError
14
14
  puts("Could not find gem 'pry'".red)
15
15
  puts("")
16
- puts("If you installed spaceship using `sudo gem install spaceship` run")
17
- puts(" sudo gem install pry".yellow)
16
+ puts("If you installed spaceship using `gem install spaceship` run")
17
+ puts(" gem install pry".yellow)
18
18
  puts("to install the missing gem")
19
19
  puts("")
20
20
  puts("If you use a Gemfile add this to your Gemfile:")
@@ -579,10 +579,10 @@ module Spaceship
579
579
  }
580
580
 
581
581
  r = request(:post) do |req|
582
- req.url("https://analytics.itunes.apple.com/analytics/api/v1/data/time-series")
582
+ req.url("https://appstoreconnect.apple.com/analytics/api/v1/data/time-series")
583
583
  req.body = data.to_json
584
584
  req.headers['Content-Type'] = 'application/json'
585
- req.headers['X-Requested-By'] = 'analytics.itunes.apple.com'
585
+ req.headers['X-Requested-By'] = 'appstoreconnect.apple.com'
586
586
  end
587
587
 
588
588
  data = parse_response(r)
@@ -4,6 +4,7 @@ require_relative 'tunes/tunes_client'
4
4
  module Spaceship
5
5
  class Client
6
6
  def handle_two_step_or_factor(response)
7
+ raise "2FA can only be performed in interactive mode" if ENV["SPACESHIP_ONLY_ALLOW_INTERACTIVE_2FA"] == "true" && ENV["FASTLANE_IS_INTERACTIVE"] == "false"
7
8
  # extract `x-apple-id-session-id` and `scnt` from response, to be used by `update_request_headers`
8
9
  @x_apple_id_session_id = response["x-apple-id-session-id"]
9
10
  @scnt = response["scnt"]
@@ -0,0 +1,91 @@
1
+ require_relative 'globals'
2
+ require_relative 'tunes/tunes_client'
3
+
4
+ module Spaceship
5
+ class Client
6
+ def try_upgrade_2fa_later(response)
7
+ if ENV['SPACESHIP_SKIP_2FA_UPGRADE'].nil?
8
+ return false
9
+ end
10
+
11
+ puts("This account is being prompted to upgrade to 2FA")
12
+ puts("Attempting to automatically bypass the upgrade until a later date")
13
+ puts("To disable this, remove SPACESHIP_SKIP_2FA_UPGRADE=1 environment variable")
14
+
15
+ # Get URL that requests a repair and gets the widget key
16
+ widget_key_location = response.headers['location']
17
+ uri = URI.parse(widget_key_location)
18
+ params = CGI.parse(uri.query)
19
+
20
+ widget_key = params.dig('widgetKey', 0)
21
+ if widget_key.nil?
22
+ STDERR.puts("Couldn't find widgetKey to continue with requests")
23
+ return false
24
+ end
25
+
26
+ # Step 1 - Request repair
27
+ response_repair = request(:get) do |req|
28
+ req.url(widget_key_location)
29
+ end
30
+
31
+ # Step 2 - Request repair options
32
+ response_repair_options = request(:get) do |req|
33
+ req.url("https://appleid.apple.com/account/manage/repair/options")
34
+
35
+ req.headers['scnt'] = response_repair.headers['scnt']
36
+ req.headers['X-Apple-Id-Session-Id'] = response.headers['X-Apple-Id-Session-Id']
37
+ req.headers['X-Apple-Session-Token'] = response.headers['X-Apple-Repair-Session-Token']
38
+
39
+ req.headers['X-Apple-Skip-Repair-Attributes'] = '[]'
40
+ req.headers['X-Apple-Widget-Key'] = widget_key
41
+
42
+ req.headers['Content-Type'] = 'application/json'
43
+ req.headers['X-Requested-With'] = 'XMLHttpRequest'
44
+ req.headers['Accept'] = 'application/json, text/javascript'
45
+ end
46
+
47
+ # Step 3 - Request setup later
48
+ request(:get) do |req|
49
+ req.url("https://appleid.apple.com/account/security/upgrade/setuplater")
50
+
51
+ req.headers['scnt'] = response_repair_options.headers['scnt']
52
+ req.headers['X-Apple-Id-Session-Id'] = response.headers['X-Apple-Id-Session-Id']
53
+ req.headers['X-Apple-Session-Token'] = response_repair_options.headers['x-apple-session-token']
54
+ req.headers['X-Apple-Skip-Repair-Attributes'] = '[]'
55
+ req.headers['X-Apple-Widget-Key'] = widget_key
56
+
57
+ req.headers['Content-Type'] = 'application/json'
58
+ req.headers['X-Requested-With'] = 'XMLHttpRequest'
59
+ req.headers['Accept'] = 'application/json, text/javascript'
60
+ end
61
+
62
+ # Step 4 - Post complete
63
+ response_repair_complete = request(:post) do |req|
64
+ req.url("https://idmsa.apple.com/appleauth/auth/repair/complete")
65
+
66
+ req.body = ''
67
+ req.headers['scnt'] = response.headers['scnt']
68
+ req.headers['X-Apple-Id-Session-Id'] = response.headers['X-Apple-Id-Session-Id']
69
+ req.headers['X-Apple-Repair-Session-Token'] = response_repair_options.headers['X-Apple-Session-Token']
70
+
71
+ req.headers['X-Apple-Widget-Key'] = widget_key
72
+
73
+ req.headers['Content-Type'] = 'application/json'
74
+ req.headers['X-Requested-With'] = 'XMLHttpRequest'
75
+ req.headers['Accept'] = 'application/json;charset=utf-8'
76
+ end
77
+
78
+ if response_repair_complete.status == 204
79
+ return true
80
+ else
81
+ STDERR.puts("Failed with status code of #{response_repair_complete.status}")
82
+ return false
83
+ end
84
+ rescue => error
85
+ STDERR.puts(error.backtrace)
86
+ STDERR.puts("Failed to bypass 2FA upgrade")
87
+ STDERR.puts("To disable this from trying again, set SPACESHIP_SKIP_UPGRADE_2FA_LATER=1")
88
+ return false
89
+ end
90
+ end
91
+ end