fastlane 2.153.1 → 2.155.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +74 -74
  3. data/deliver/lib/deliver/html_generator.rb +8 -1
  4. data/deliver/lib/deliver/setup.rb +1 -3
  5. data/deliver/lib/deliver/upload_metadata.rb +21 -4
  6. data/fastlane/lib/fastlane/actions/carthage.rb +7 -0
  7. data/fastlane/lib/fastlane/actions/create_keychain.rb +5 -1
  8. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +21 -2
  9. data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +3 -3
  10. data/fastlane/lib/fastlane/actions/git_pull.rb +13 -2
  11. data/fastlane/lib/fastlane/actions/sync_code_signing.rb +5 -0
  12. data/fastlane/lib/fastlane/version.rb +1 -1
  13. data/fastlane/swift/Deliverfile.swift +1 -1
  14. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  15. data/fastlane/swift/Fastlane.swift +402 -187
  16. data/fastlane/swift/Gymfile.swift +1 -1
  17. data/fastlane/swift/GymfileProtocol.swift +1 -1
  18. data/fastlane/swift/Matchfile.swift +1 -1
  19. data/fastlane/swift/MatchfileProtocol.swift +10 -2
  20. data/fastlane/swift/Precheckfile.swift +1 -1
  21. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  22. data/fastlane/swift/Scanfile.swift +1 -1
  23. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  24. data/fastlane/swift/Screengrabfile.swift +1 -1
  25. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  26. data/fastlane/swift/Snapshotfile.swift +1 -1
  27. data/fastlane/swift/SnapshotfileProtocol.swift +9 -1
  28. data/fastlane_core/lib/fastlane_core/device_manager.rb +7 -2
  29. data/frameit/lib/frameit/editor.rb +3 -1
  30. data/gym/lib/gym/detect_values.rb +6 -3
  31. data/gym/lib/gym/module.rb +30 -0
  32. data/gym/lib/gym/runner.rb +23 -18
  33. data/{spaceship/lib/spaceship/connect_api/.model.rb.swp → match/lib/match/.options.rb.swp} +0 -0
  34. data/{deliver/lib/deliver/.upload_metadata.rb.swp → match/lib/match/.runner.rb.swp} +0 -0
  35. data/match/lib/match/generator.rb +6 -0
  36. data/match/lib/match/options.rb +16 -4
  37. data/match/lib/match/runner.rb +13 -5
  38. data/match/lib/match/spaceship_ensure.rb +7 -9
  39. data/match/lib/match/storage/git_storage.rb +16 -2
  40. data/match/lib/match/storage/google_cloud_storage.rb +1 -1
  41. data/pilot/lib/pilot/build_manager.rb +9 -0
  42. data/pilot/lib/pilot/options.rb +1 -1
  43. data/{frameit/lib/frameit/.editor.rb.swp → sigh/lib/sigh/.options.rb.swp} +0 -0
  44. data/sigh/lib/sigh/.runner.rb.swp +0 -0
  45. data/sigh/lib/sigh/download_all.rb +42 -27
  46. data/sigh/lib/sigh/module.rb +26 -0
  47. data/sigh/lib/sigh/options.rb +2 -2
  48. data/sigh/lib/sigh/runner.rb +100 -35
  49. data/snapshot/lib/snapshot/options.rb +10 -0
  50. data/snapshot/lib/snapshot/simulator_launchers/launcher_configuration.rb +2 -0
  51. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +5 -0
  52. data/snapshot/lib/snapshot/test_command_generator.rb +3 -2
  53. data/snapshot/lib/snapshot/test_command_generator_xcode_8.rb +4 -1
  54. data/spaceship/lib/spaceship/connect_api/client.rb +3 -1
  55. data/spaceship/lib/spaceship/connect_api/model.rb +1 -1
  56. data/spaceship/lib/spaceship/connect_api/models/.profile.rb.swp +0 -0
  57. data/spaceship/lib/spaceship/connect_api/models/app.rb +22 -2
  58. data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +17 -5
  59. data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +41 -7
  60. data/spaceship/lib/spaceship/connect_api/models/profile.rb +32 -1
  61. data/spaceship/lib/spaceship/connect_api/{models/.app_store_review_detail.rb.swp → provisioning/.provisioning.rb.swp} +0 -0
  62. data/spaceship/lib/spaceship/connect_api/provisioning/client.rb +46 -4
  63. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +41 -0
  64. data/supply/lib/supply/client.rb +2 -1
  65. data/supply/lib/supply/options.rb +8 -1
  66. metadata +23 -22
  67. data/spaceship/lib/spaceship/connect_api/models/.app_store_version.rb.swp +0 -0
@@ -116,6 +116,11 @@ module Snapshot
116
116
  description: "Enabling this option will automatically erase the simulator before running the application",
117
117
  default_value: false,
118
118
  is_string: false),
119
+ FastlaneCore::ConfigItem.new(key: :headless,
120
+ env_name: 'SNAPSHOT_HEADLESS',
121
+ description: "Enabling this option will prevent displaying the simulator window",
122
+ default_value: true,
123
+ type: Boolean),
119
124
  FastlaneCore::ConfigItem.new(key: :override_status_bar,
120
125
  env_name: 'SNAPSHOT_OVERRIDE_STATUS_BAR',
121
126
  description: "Enabling this option wil automatically override the status bar to show 9:41 AM, full battery, and full reception",
@@ -273,6 +278,11 @@ module Snapshot
273
278
  env_name: "SNAPSHOT_DISABLE_XCPRETTY",
274
279
  description: "Disable xcpretty formatting of build",
275
280
  type: Boolean,
281
+ optional: true),
282
+ FastlaneCore::ConfigItem.new(key: :suppress_xcode_output,
283
+ env_name: "SNAPSHOT_SUPPRESS_XCODE_OUTPUT",
284
+ description: "Suppress the output of xcodebuild to stdout. Output is still saved in buildlog_path",
285
+ type: Boolean,
276
286
  optional: true)
277
287
  ]
278
288
  end
@@ -7,6 +7,7 @@ module Snapshot
7
7
  attr_accessor :add_videos
8
8
  attr_accessor :clean
9
9
  attr_accessor :erase_simulator
10
+ attr_accessor :headless
10
11
  attr_accessor :localize_simulator
11
12
  attr_accessor :dark_mode
12
13
  attr_accessor :reinstall_app
@@ -34,6 +35,7 @@ module Snapshot
34
35
  @add_videos = snapshot_config[:add_videos]
35
36
  @clean = snapshot_config[:clean]
36
37
  @erase_simulator = snapshot_config[:erase_simulator]
38
+ @headless = snapshot_config[:headless]
37
39
  @localize_simulator = snapshot_config[:localize_simulator]
38
40
  @dark_mode = snapshot_config[:dark_mode]
39
41
  @reinstall_app = snapshot_config[:reinstall_app]
@@ -76,6 +76,11 @@ module Snapshot
76
76
  disable_slide_to_type(type)
77
77
  end
78
78
  end
79
+
80
+ unless launcher_config.headless
81
+ simulator_path = File.join(Helper.xcode_path, 'Applications', 'Simulator.app')
82
+ Helper.backticks("open -a #{simulator_path} -g", print: FastlaneCore::Globals.verbose?)
83
+ end
79
84
  end
80
85
 
81
86
  # pass an array of device types
@@ -33,8 +33,9 @@ module Snapshot
33
33
 
34
34
  xcpretty = "xcpretty #{Snapshot.config[:xcpretty_args]}"
35
35
  xcpretty << "--no-color" if Helper.colors_disabled?
36
-
37
- return pipe << "| #{xcpretty}"
36
+ pipe << "| #{xcpretty}"
37
+ pipe << "> /dev/null" if Snapshot.config[:suppress_xcode_output]
38
+ return pipe
38
39
  end
39
40
 
40
41
  def destination(devices)
@@ -24,7 +24,10 @@ module Snapshot
24
24
 
25
25
  def pipe(device_type, language, locale)
26
26
  log_path = xcodebuild_log_path(device_type: device_type, language: language, locale: locale)
27
- return ["| tee #{log_path.shellescape} | xcpretty #{Snapshot.config[:xcpretty_args]}"]
27
+ pipe = ["| tee #{log_path.shellescape}"]
28
+ pipe << "| xcpretty #{Snapshot.config[:xcpretty_args]}"
29
+ pipe << "> /dev/null" if Snapshot.config[:suppress_xcode_output]
30
+ return pipe
28
31
  end
29
32
 
30
33
  def destination(device_name)
@@ -129,7 +129,6 @@ module Spaceship
129
129
  tries = 1 if Object.const_defined?("SpecHelper")
130
130
  response = yield
131
131
 
132
- tries -= 1
133
132
  status = response.status if response
134
133
 
135
134
  if [500, 504].include?(status)
@@ -139,6 +138,7 @@ module Spaceship
139
138
 
140
139
  return response
141
140
  rescue => error
141
+ tries -= 1
142
142
  puts(error) if Spaceship::Globals.verbose?
143
143
  if tries.zero?
144
144
  return response
@@ -164,6 +164,8 @@ module Spaceship
164
164
 
165
165
  raise UnexpectedResponse, "Temporary App Store Connect error: #{response.body}" if response.body['statusCode'] == 'ERROR'
166
166
 
167
+ store_csrf_tokens(response)
168
+
167
169
  return Spaceship::ConnectAPI::Response.new(body: response.body, status: response.status, client: self)
168
170
  end
169
171
 
@@ -152,7 +152,7 @@ module Spaceship
152
152
  id == included_data["id"] && type == included_data["type"]
153
153
  end
154
154
 
155
- inflate_model(relationship_data, included)
155
+ inflate_model(relationship_data, included) if relationship_data
156
156
  end
157
157
 
158
158
  # Map a hash or an array of data
@@ -10,6 +10,7 @@ module Spaceship
10
10
  attr_accessor :bundle_id
11
11
  attr_accessor :sku
12
12
  attr_accessor :primary_locale
13
+ attr_accessor :is_opted_in_to_distribute_ios_app_on_mac_app_store
13
14
  attr_accessor :removed
14
15
  attr_accessor :is_aag
15
16
  attr_accessor :available_in_new_territories
@@ -26,6 +27,7 @@ module Spaceship
26
27
  "bundleId" => "bundle_id",
27
28
  "sku" => "sku",
28
29
  "primaryLocale" => "primary_locale",
30
+ "isOptedInToDistributeIosAppOnMacAppStore" => "is_opted_in_to_distribute_ios_app_on_mac_app_store",
29
31
  "removed" => "removed",
30
32
  "isAAG" => "is_aag",
31
33
  "availableInNewTerritories" => "available_in_new_territories",
@@ -186,14 +188,14 @@ module Spaceship
186
188
 
187
189
  # Get the latest version
188
190
  return get_app_store_versions(filter: filter, includes: includes)
189
- .sort_by { |v| Gem::Version.new(v.version_string) }
191
+ .sort_by { |v| Date.parse(v.created_date) }
190
192
  .last
191
193
  end
192
194
 
193
195
  def get_live_app_store_version(platform: nil, includes: nil)
194
196
  platform ||= Spaceship::ConnectAPI::Platform::IOS
195
197
  filter = {
196
- appStoreState: [Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::READY_FOR_SALE].join(","),
198
+ appStoreState: Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::READY_FOR_SALE,
197
199
  platform: platform
198
200
  }
199
201
  return get_app_store_versions(filter: filter, includes: includes).first
@@ -219,6 +221,24 @@ module Spaceship
219
221
  .last
220
222
  end
221
223
 
224
+ def get_in_review_app_store_version(platform: nil, includes: nil)
225
+ platform ||= Spaceship::ConnectAPI::Platform::IOS
226
+ filter = {
227
+ appStoreState: Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::IN_REVIEW,
228
+ platform: platform
229
+ }
230
+ return get_app_store_versions(filter: filter, includes: includes).first
231
+ end
232
+
233
+ def get_pending_release_app_store_version(platform: nil, includes: nil)
234
+ platform ||= Spaceship::ConnectAPI::Platform::IOS
235
+ filter = {
236
+ appStoreState: Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::PENDING_DEVELOPER_RELEASE,
237
+ platform: platform
238
+ }
239
+ return get_app_store_versions(filter: filter, includes: includes).first
240
+ end
241
+
222
242
  def get_app_store_versions(filter: {}, includes: nil, limit: nil, sort: nil)
223
243
  resps = Spaceship::ConnectAPI.get_app_store_versions(app_id: id, filter: filter, includes: includes, limit: limit, sort: sort).all_pages
224
244
  return resps.flat_map(&:to_models)
@@ -1,4 +1,5 @@
1
1
  require_relative '../model'
2
+ require_relative './bundle_id_capability'
2
3
  module Spaceship
3
4
  class ConnectAPI
4
5
  class BundleId
@@ -20,15 +21,20 @@ module Spaceship
20
21
  "bundleIdCapabilities" => 'bundle_id_capabilities'
21
22
  })
22
23
 
23
- module Platform
24
- IOS = "IOS"
25
- MAC_OS = "MAC_OS"
26
- end
27
-
28
24
  def self.type
29
25
  return "bundleIds"
30
26
  end
31
27
 
28
+ #
29
+ # Helpers
30
+ #
31
+
32
+ def supports_catalyst?
33
+ return bundle_id_capabilities.any? do |capability|
34
+ capability.is_type?(Spaceship::ConnectAPI::BundleIdCapability::Type::MARZIPAN)
35
+ end
36
+ end
37
+
32
38
  #
33
39
  # API
34
40
  #
@@ -38,6 +44,12 @@ module Spaceship
38
44
  return resps.flat_map(&:to_models)
39
45
  end
40
46
 
47
+ def self.find(identifier, includes: nil)
48
+ return all(filter: { identifier: identifier }, includes: includes).find do |app|
49
+ app.identifier == identifier
50
+ end
51
+ end
52
+
41
53
  def self.get(bundle_id_id: nil, includes: nil)
42
54
  return Spaceship::ConnectAPI.get_bundle_id(bundle_id_id: bundle_id_id, includes: includes).first
43
55
  end
@@ -4,23 +4,57 @@ module Spaceship
4
4
  class BundleIdCapability
5
5
  include Spaceship::ConnectAPI::Model
6
6
 
7
- attr_accessor :capabilityType
8
- attr_accessor :bundleIdCapabilitiesSettingOption
7
+ attr_accessor :capability_type
8
+ attr_accessor :settings
9
9
 
10
10
  attr_mapping({
11
- "capabilityType" => "capabilityType",
12
- "settings" => "email"
11
+ "capabilityType" => "capability_type",
12
+ "settings" => "settings"
13
13
  })
14
14
 
15
- module Platform
16
- IOS = "IOS"
17
- MAC_OS = "MAC_OS"
15
+ module Type
16
+ ICLOUD = "ICLOUD"
17
+ IN_APP_PURCHASE = "IN_APP_PURCHASE"
18
+ GAME_CENTER = "GAME_CENTER"
19
+ PUSH_NOTIFICATIONS = "PUSH_NOTIFICATIONS"
20
+ WALLET = "WALLET"
21
+ INTER_APP_AUDIO = "INTER_APP_AUDIO"
22
+ MAPS = "MAPS"
23
+ ASSOCIATED_DOMAINS = "ASSOCIATED_DOMAINS"
24
+ PERSONAL_VPN = "PERSONAL_VPN"
25
+ APP_GROUPS = "APP_GROUPS"
26
+ HEALTHKIT = "HEALTHKIT"
27
+ HOMEKIT = "HOMEKIT"
28
+ WIRELESS_ACCESSORY_CONFIGURATION = "WIRELESS_ACCESSORY_CONFIGURATION"
29
+ APPLE_PAY = "APPLE_PAY"
30
+ DATA_PROTECTION = "DATA_PROTECTION"
31
+ SIRIKIT = "SIRIKIT"
32
+ NETWORK_EXTENSIONS = "NETWORK_EXTENSIONS"
33
+ MULTIPATH = "MULTIPATH"
34
+ HOT_SPOT = "HOT_SPOT"
35
+ NFC_TAG_READING = "NFC_TAG_READING"
36
+ CLASSKIT = "CLASSKIT"
37
+ AUTOFILL_CREDENTIAL_PROVIDER = "AUTOFILL_CREDENTIAL_PROVIDER"
38
+ ACCESS_WIFI_INFORMATION = "ACCESS_WIFI_INFORMATION"
39
+
40
+ # Undocumented as of 2020-06-09
41
+ MARZIPAN = "MARZIPAN" # Catalyst
18
42
  end
19
43
 
20
44
  def self.type
21
45
  return "bundleIdCapabilities"
22
46
  end
23
47
 
48
+ #
49
+ # Helpers
50
+ #
51
+
52
+ def is_type?(type)
53
+ # JWT session returns type under "capability_type" attribute
54
+ # Web session returns type under "id" attribute but with "P7GJR49W72_" prefixed
55
+ return capability_type == type || id.end_with?(type)
56
+ end
57
+
24
58
  #
25
59
  # API
26
60
  #
@@ -13,6 +13,9 @@ module Spaceship
13
13
  attr_accessor :profile_type
14
14
  attr_accessor :expiration_date
15
15
 
16
+ attr_accessor :bundle_id
17
+ attr_accessor :certificates
18
+
16
19
  attr_mapping({
17
20
  "name" => "name",
18
21
  "platform" => "platform",
@@ -21,7 +24,10 @@ module Spaceship
21
24
  "createdDate" => "created_date",
22
25
  "profileState" => "profile_state",
23
26
  "profileType" => "profile_type",
24
- "expirationDate" => "expiration_date"
27
+ "expirationDate" => "expiration_date",
28
+
29
+ "bundleId" => "bundle_id",
30
+ "certificates" => "certificates"
25
31
  })
26
32
 
27
33
  module ProfileState
@@ -41,12 +47,19 @@ module Spaceship
41
47
  TVOS_APP_STORE = "TVOS_APP_STORE"
42
48
  TVOS_APP_ADHOC = "TVOS_APP_ADHOC"
43
49
  TVOS_APP_INHOUSE = "TVOS_APP_INHOUSE"
50
+ MAC_CATALYST_APP_DEVELOPMENT = "MAC_CATALYST_APP_DEVELOPMENT"
51
+ MAC_CATALYST_APP_STORE = "MAC_CATALYST_APP_STORE"
52
+ MAC_CATALYST_APP_DIRECT = "MAC_CATALYST_APP_DIRECT"
44
53
  end
45
54
 
46
55
  def self.type
47
56
  return "profiles"
48
57
  end
49
58
 
59
+ def valid?
60
+ return profile_state == ProfileState::ACTIVE
61
+ end
62
+
50
63
  #
51
64
  # API
52
65
  #
@@ -55,6 +68,24 @@ module Spaceship
55
68
  resps = Spaceship::ConnectAPI.get_profiles(filter: filter, includes: includes).all_pages
56
69
  return resps.flat_map(&:to_models)
57
70
  end
71
+
72
+ def self.create(name: nil, profile_type: nil, bundle_id_id: nil, certificate_ids: nil, device_ids: nil, template_name: nil)
73
+ resp = Spaceship::ConnectAPI.post_profiles(
74
+ bundle_id_id: bundle_id_id,
75
+ certificates: certificate_ids,
76
+ devices: device_ids,
77
+ attributes: {
78
+ name: name,
79
+ profileType: profile_type,
80
+ templateName: template_name
81
+ }
82
+ )
83
+ return resp.to_models.first
84
+ end
85
+
86
+ def delete!
87
+ return Spaceship::ConnectAPI.delete_profile(profile_id: id)
88
+ end
58
89
  end
59
90
  end
60
91
  end
@@ -33,14 +33,30 @@ module Spaceship
33
33
  #
34
34
 
35
35
  def get(url_or_path, params = nil)
36
- # The App Store Connect API is only available in a web session through a
37
- # a proxy server where GET requests are actually sent as a POST
38
- return get_as_post(url_or_path, params) if web_session?
36
+ # The Provisioning App Store Connect API needs to be proxied through a
37
+ # POST request if using web session
38
+ return proxy_get(url_or_path, params) if web_session?
39
39
 
40
40
  super(url_or_path, params)
41
41
  end
42
42
 
43
- def get_as_post(url_or_path, params = nil)
43
+ def post(url_or_path, body)
44
+ # The Provisioning App Store Connect API needs teamId added to the body of
45
+ # each post if using web session
46
+ return proxy_post(url_or_path, body) if web_session?
47
+
48
+ super(url_or_path, body)
49
+ end
50
+
51
+ def delete(url_or_path, params = nil)
52
+ # The Provisioning App Store Connect API needs to be proxied through a
53
+ # POST request if using web session
54
+ return proxy_delete(url_or_path, params) if web_session?
55
+
56
+ super(url_or_path, params)
57
+ end
58
+
59
+ def proxy_get(url_or_path, params = nil)
44
60
  encoded_params = Faraday::NestedParamsEncoder.encode(params)
45
61
  body = { "urlEncodedQueryParams" => encoded_params, "teamId" => team_id }
46
62
 
@@ -53,6 +69,32 @@ module Spaceship
53
69
  end
54
70
  handle_response(response)
55
71
  end
72
+
73
+ def proxy_post(url_or_path, body)
74
+ body[:data][:attributes][:teamId] = team_id
75
+
76
+ response = request(:post) do |req|
77
+ req.url(url_or_path)
78
+ req.body = body.to_json
79
+ req.headers['Content-Type'] = 'application/vnd.api+json'
80
+ req.headers['X-Requested-With'] = 'XMLHttpRequest'
81
+ end
82
+ handle_response(response)
83
+ end
84
+
85
+ def proxy_delete(url_or_path, params = nil)
86
+ encoded_params = Faraday::NestedParamsEncoder.encode(params)
87
+ body = { "urlEncodedQueryParams" => encoded_params, "teamId" => team_id }
88
+
89
+ response = request(:post) do |req|
90
+ req.url(url_or_path)
91
+ req.body = body.to_json
92
+ req.headers['Content-Type'] = 'application/vnd.api+json'
93
+ req.headers['X-HTTP-Method-Override'] = 'DELETE'
94
+ req.headers['X-Requested-With'] = 'XMLHttpRequest'
95
+ end
96
+ handle_response(response)
97
+ end
56
98
  end
57
99
  end
58
100
  end
@@ -43,6 +43,47 @@ module Spaceship
43
43
  params = Client.instance.build_params(filter: filter, includes: includes, limit: limit, sort: sort)
44
44
  Client.instance.get("profiles", params)
45
45
  end
46
+
47
+ def post_profiles(bundle_id_id: nil, certificates: nil, devices: nil, attributes: {})
48
+ body = {
49
+ data: {
50
+ attributes: attributes,
51
+ type: "profiles",
52
+ relationships: {
53
+ bundleId: {
54
+ data: {
55
+ type: "bundleIds",
56
+ id: bundle_id_id
57
+ }
58
+ },
59
+ certificates: {
60
+ data: certificates.map do |certificate|
61
+ {
62
+ type: "certificates",
63
+ id: certificate
64
+ }
65
+ end
66
+ },
67
+ devices: {
68
+ data: (devices || []).map do |device|
69
+ {
70
+ type: "devices",
71
+ id: device
72
+ }
73
+ end
74
+ }
75
+ }
76
+ }
77
+ }
78
+
79
+ Client.instance.post("profiles", body)
80
+ end
81
+
82
+ def delete_profile(profile_id: nil)
83
+ raise "Profile id is nil" if profile_id.nil?
84
+
85
+ Client.instance.delete("profiles/#{profile_id}")
86
+ end
46
87
  end
47
88
  end
48
89
  end