fastlane 2.170.0 → 2.175.0

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