fastlane 2.155.1 → 2.157.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +72 -72
- data/deliver/lib/deliver.rb +1 -0
- data/deliver/lib/deliver/app_screenshot_iterator.rb +95 -0
- data/deliver/lib/deliver/detect_values.rb +4 -1
- data/deliver/lib/deliver/languages.rb +7 -0
- data/deliver/lib/deliver/loader.rb +4 -5
- data/deliver/lib/deliver/queue_worker.rb +64 -0
- data/deliver/lib/deliver/runner.rb +7 -5
- data/deliver/lib/deliver/upload_screenshots.rb +143 -128
- data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +120 -0
- data/fastlane/lib/fastlane/actions/commit_version_bump.rb +1 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +2 -0
- data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +17 -1
- data/fastlane/lib/fastlane/actions/set_changelog.rb +2 -2
- data/fastlane/lib/fastlane/actions/sonar.rb +5 -0
- data/fastlane/lib/fastlane/actions/spaceship_stats.rb +73 -0
- data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +4 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +68 -8
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +1 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +1 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +71 -42
- data/fastlane_core/lib/fastlane_core/project.rb +1 -0
- data/gym/lib/gym/error_handler.rb +1 -1
- data/gym/lib/gym/generators/build_command_generator.rb +0 -1
- data/pilot/lib/pilot/build_manager.rb +18 -4
- data/pilot/lib/pilot/manager.rb +15 -5
- data/pilot/lib/pilot/options.rb +16 -0
- data/produce/lib/produce/itunes_connect.rb +2 -2
- data/scan/lib/scan/test_command_generator.rb +3 -1
- data/screengrab/lib/screengrab/runner.rb +8 -7
- data/sigh/lib/sigh/runner.rb +9 -5
- data/snapshot/lib/snapshot/test_command_generator_base.rb +3 -1
- data/spaceship/lib/spaceship.rb +4 -0
- data/spaceship/lib/spaceship/client.rb +2 -0
- data/spaceship/lib/spaceship/connect_api.rb +0 -15
- data/spaceship/lib/spaceship/connect_api/api_client.rb +270 -0
- data/spaceship/lib/spaceship/connect_api/client.rb +139 -213
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +3 -2
- data/spaceship/lib/spaceship/connect_api/provisioning/client.rb +8 -17
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +75 -64
- data/spaceship/lib/spaceship/connect_api/spaceship.rb +94 -0
- data/spaceship/lib/spaceship/connect_api/testflight/client.rb +8 -17
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +288 -277
- data/spaceship/lib/spaceship/connect_api/token.rb +46 -5
- data/spaceship/lib/spaceship/connect_api/token_refresh_middleware.rb +24 -0
- data/spaceship/lib/spaceship/connect_api/tunes/client.rb +8 -17
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +717 -706
- data/spaceship/lib/spaceship/connect_api/users/client.rb +8 -17
- data/spaceship/lib/spaceship/connect_api/users/users.rb +28 -17
- data/spaceship/lib/spaceship/stats_middleware.rb +65 -0
- metadata +25 -18
- data/sigh/lib/sigh/.runner.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/models/.device.rb.swp +0 -0
@@ -4,10 +4,17 @@ require 'digest/md5'
|
|
4
4
|
require_relative 'app_screenshot'
|
5
5
|
require_relative 'module'
|
6
6
|
require_relative 'loader'
|
7
|
+
require_relative 'queue_worker'
|
8
|
+
require_relative 'app_screenshot_iterator'
|
7
9
|
|
8
10
|
module Deliver
|
9
11
|
# upload screenshots to App Store Connect
|
10
12
|
class UploadScreenshots
|
13
|
+
DeleteScreenshotJob = Struct.new(:app_screenshot, :localization, :app_screenshot_set)
|
14
|
+
UploadScreenshotJob = Struct.new(:app_screenshot_set, :path)
|
15
|
+
|
16
|
+
NUMBER_OF_THREADS = Helper.test? ? 1 : [ENV.fetch("DELIVER_NUMBER_OF_THREADS", 10).to_i, 10].min
|
17
|
+
|
11
18
|
def upload(options, screenshots)
|
12
19
|
return if options[:skip_screenshots]
|
13
20
|
return if options[:edit_live]
|
@@ -50,57 +57,47 @@ module Deliver
|
|
50
57
|
localizations = version.get_app_store_version_localizations
|
51
58
|
end
|
52
59
|
|
53
|
-
upload_screenshots(
|
60
|
+
upload_screenshots(localizations, screenshots_per_language)
|
61
|
+
|
62
|
+
Helper.show_loading_indicator("Sorting screenshots uploaded...")
|
63
|
+
sort_screenshots(localizations)
|
64
|
+
Helper.hide_loading_indicator
|
65
|
+
|
66
|
+
UI.success("Successfully uploaded screenshots to App Store Connect")
|
54
67
|
end
|
55
68
|
|
56
69
|
def delete_screenshots(localizations, screenshots_per_language, tries: 5)
|
57
70
|
tries -= 1
|
58
71
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
errors = []
|
70
|
-
|
71
|
-
screenshot_sets.each do |screenshot_set|
|
72
|
-
UI.message("Removing all previously uploaded screenshots for '#{localization.locale}' '#{screenshot_set.screenshot_display_type}'...")
|
73
|
-
screenshot_set.app_screenshots.each do |screenshot|
|
74
|
-
UI.verbose("Deleting screenshot - #{localization.locale} #{screenshot_set.screenshot_display_type} #{screenshot.id}")
|
75
|
-
threads << Thread.new do
|
76
|
-
begin
|
77
|
-
screenshot.delete!
|
78
|
-
UI.verbose("Deleted screenshot - #{localization.locale} #{screenshot_set.screenshot_display_type} #{screenshot.id}")
|
79
|
-
rescue => error
|
80
|
-
UI.verbose("Failed to delete screenshot - #{localization.locale} #{screenshot_set.screenshot_display_type} #{screenshot.id}")
|
81
|
-
errors << error
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
72
|
+
worker = QueueWorker.new(NUMBER_OF_THREADS) do |job|
|
73
|
+
start_time = Time.now
|
74
|
+
target = "#{job.localization.locale} #{job.app_screenshot_set.screenshot_display_type} #{job.app_screenshot.id}"
|
75
|
+
begin
|
76
|
+
UI.verbose("Deleting '#{target}'")
|
77
|
+
job.app_screenshot.delete!
|
78
|
+
UI.message("Deleted '#{target}' - (#{Time.now - start_time} secs)")
|
79
|
+
rescue => error
|
80
|
+
UI.error("Failed to delete screenshot #{target} - (#{Time.now - start_time} secs)")
|
81
|
+
UI.error(error.message)
|
85
82
|
end
|
83
|
+
end
|
86
84
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
threads.each(&:join)
|
92
|
-
Helper.hide_loading_indicator unless FastlaneCore::Globals.verbose?
|
93
|
-
end
|
85
|
+
iterator = AppScreenshotIterator.new(localizations)
|
86
|
+
iterator.each_app_screenshot do |localization, app_screenshot_set, app_screenshot|
|
87
|
+
# Only delete screenshots if trying to upload
|
88
|
+
next unless screenshots_per_language.keys.include?(localization.locale)
|
94
89
|
|
95
|
-
|
96
|
-
|
97
|
-
UI.error(error.message)
|
98
|
-
end
|
90
|
+
UI.verbose("Queued delete sceeenshot job for #{localization.locale} #{app_screenshot_set.screenshot_display_type} #{app_screenshot.id}")
|
91
|
+
worker.enqueue(DeleteScreenshotJob.new(app_screenshot, localization, app_screenshot_set))
|
99
92
|
end
|
100
93
|
|
94
|
+
worker.start
|
95
|
+
|
101
96
|
# Verify all screenshots have been deleted
|
102
97
|
# Sometimes API requests will fail but screenshots will still be deleted
|
103
|
-
count =
|
98
|
+
count = iterator.each_app_screenshot_set.map { |_, app_screenshot_set| app_screenshot_set }
|
99
|
+
.reduce(0) { |sum, app_screenshot_set| sum + app_screenshot_set.app_screenshots.size }
|
100
|
+
|
104
101
|
UI.important("Number of screenshots not deleted: #{count}")
|
105
102
|
if count > 0
|
106
103
|
if tries.zero?
|
@@ -114,113 +111,127 @@ module Deliver
|
|
114
111
|
end
|
115
112
|
end
|
116
113
|
|
117
|
-
def
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
114
|
+
def upload_screenshots(localizations, screenshots_per_language, tries: 5)
|
115
|
+
tries -= 1
|
116
|
+
|
117
|
+
# Upload screenshots
|
118
|
+
worker = QueueWorker.new(NUMBER_OF_THREADS) do |job|
|
119
|
+
begin
|
120
|
+
UI.verbose("Uploading '#{job.path}'...")
|
121
|
+
start_time = Time.now
|
122
|
+
job.app_screenshot_set.upload_screenshot(path: job.path, wait_for_processing: false)
|
123
|
+
UI.message("Uploaded '#{job.path}'... (#{Time.now - start_time} secs)")
|
124
|
+
rescue => error
|
125
|
+
UI.error(error)
|
123
126
|
end
|
124
127
|
end
|
125
128
|
|
126
|
-
|
127
|
-
|
129
|
+
number_of_screenshots = 0
|
130
|
+
iterator = AppScreenshotIterator.new(localizations)
|
131
|
+
iterator.each_local_screenshot(screenshots_per_language) do |localization, app_screenshot_set, screenshot, index|
|
132
|
+
if index >= 10
|
133
|
+
UI.error("Too many screenshots found for device '#{screenshot.device_type}' in '#{screenshot.language}', skipping this one (#{screenshot.path})")
|
134
|
+
next
|
135
|
+
end
|
128
136
|
|
129
|
-
|
130
|
-
|
131
|
-
# Default to waiting if submitting for review (since needed for submission)
|
132
|
-
# Otherwise use enviroment variable
|
133
|
-
if ENV["DELIVER_SKIP_WAIT_FOR_SCREENSHOT_PROCESSING"].nil?
|
134
|
-
wait_for_processing = options[:submit_for_review]
|
135
|
-
UI.verbose("Setting wait_for_processing from ':submit_for_review' option")
|
136
|
-
else
|
137
|
-
UI.verbose("Setting wait_for_processing from 'DELIVER_SKIP_WAIT_FOR_SCREENSHOT_PROCESSING' environment variable")
|
138
|
-
wait_for_processing = !FastlaneCore::Env.truthy?("DELIVER_SKIP_WAIT_FOR_SCREENSHOT_PROCESSING")
|
139
|
-
end
|
137
|
+
checksum = UploadScreenshots.calculate_checksum(screenshot.path)
|
138
|
+
duplicate = (app_screenshot_set.app_screenshots || []).any? { |s| s.source_file_checksum == checksum }
|
140
139
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
140
|
+
# Enqueue uploading job if it's not duplicated otherwise screenshot will be skipped
|
141
|
+
if duplicate
|
142
|
+
UI.message("Previous uploaded. Skipping '#{screenshot.path}'...")
|
143
|
+
else
|
144
|
+
worker.enqueue(UploadScreenshotJob.new(app_screenshot_set, screenshot.path))
|
145
|
+
end
|
146
|
+
|
147
|
+
number_of_screenshots += 1
|
147
148
|
end
|
148
149
|
|
149
|
-
|
150
|
-
indized = {} # per language and device type
|
150
|
+
worker.start
|
151
151
|
|
152
|
-
|
153
|
-
# Find localization to upload screenshots to
|
154
|
-
localization = localizations.find do |l|
|
155
|
-
l.locale == language
|
156
|
-
end
|
152
|
+
UI.verbose('Uploading jobs are completed')
|
157
153
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
154
|
+
Helper.show_loading_indicator("Waiting for all the screenshots processed...")
|
155
|
+
states = wait_for_complete(iterator)
|
156
|
+
Helper.hide_loading_indicator
|
157
|
+
retry_upload_screenshots_if_needed(iterator, states, number_of_screenshots, tries, localizations, screenshots_per_language)
|
162
158
|
|
163
|
-
|
159
|
+
UI.message("Successfully uploaded all screenshots")
|
160
|
+
end
|
164
161
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
162
|
+
# Verify all screenshots have been processed
|
163
|
+
def wait_for_complete(iterator)
|
164
|
+
loop do
|
165
|
+
states = iterator.each_app_screenshot.map { |_, _, app_screenshot| app_screenshot }.each_with_object({}) do |app_screenshot, hash|
|
166
|
+
state = app_screenshot.asset_delivery_state['state']
|
167
|
+
hash[state] ||= 0
|
168
|
+
hash[state] += 1
|
169
|
+
end
|
170
170
|
|
171
|
-
|
172
|
-
|
173
|
-
count: app_screenshot_set.app_screenshots.size,
|
174
|
-
checksums: []
|
175
|
-
}
|
171
|
+
is_processing = states.fetch('UPLOAD_COMPLETE', 0) > 0
|
172
|
+
return states unless is_processing
|
176
173
|
|
177
|
-
|
178
|
-
|
179
|
-
|
174
|
+
UI.verbose("There are still incomplete screenshots - #{states}")
|
175
|
+
sleep(5)
|
176
|
+
end
|
177
|
+
end
|
180
178
|
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
179
|
+
# Verify all screenshots states on App Store Connect are okay
|
180
|
+
def retry_upload_screenshots_if_needed(iterator, states, number_of_screenshots, tries, localizations, screenshots_per_language)
|
181
|
+
is_failure = states.fetch("FAILED", 0) > 0
|
182
|
+
is_missing_screenshot = !screenshots_per_language.empty? && !verify_local_screenshots_are_uploaded(iterator, screenshots_per_language)
|
183
|
+
return unless is_failure || is_missing_screenshot
|
185
184
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
185
|
+
if tries.zero?
|
186
|
+
iterator.each_app_screenshot.select { |_, _, app_screenshot| app_screenshot.error? }.each do |localization, _, app_screenshot|
|
187
|
+
UI.error("#{app_screenshot.file_name} for #{localization.locale} has error(s) - #{app_screenshot.error_messages.join(', ')}")
|
188
|
+
end
|
189
|
+
incomplete_screenshot_count = states.reject { |k, v| k == 'COMPLETE' }.reduce(0) { |sum, (k, v)| sum + v }
|
190
|
+
UI.user_error!("Failed verification of all screenshots uploaded... #{incomplete_screenshot_count} incomplete screenshot(s) still exist")
|
191
|
+
else
|
192
|
+
UI.error("Failed to upload all screenshots... Tries remaining: #{tries}")
|
193
|
+
# Delete bad entries before retry
|
194
|
+
iterator.each_app_screenshot do |_, _, app_screenshot|
|
195
|
+
app_screenshot.delete! unless app_screenshot.complete?
|
196
|
+
end
|
197
|
+
upload_screenshots(localizations, screenshots_per_language, tries: tries)
|
198
|
+
end
|
199
|
+
end
|
190
200
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
app_screenshot_sets_map[display_type] = set
|
201
|
+
# Return `true` if all the local screenshots are uploaded to App Store Connect
|
202
|
+
def verify_local_screenshots_are_uploaded(iterator, screenshots_per_language)
|
203
|
+
# Check if local screenshots' checksum exist on App Store Connect
|
204
|
+
checksum_to_app_screenshot = iterator.each_app_screenshot.map { |_, _, app_screenshot| [app_screenshot.source_file_checksum, app_screenshot] }.to_h
|
196
205
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
end
|
206
|
+
missing_local_screenshots = iterator.each_local_screenshot(screenshots_per_language).select do |_, _, local_screenshot, index|
|
207
|
+
checksum = UploadScreenshots.calculate_checksum(local_screenshot.path)
|
208
|
+
checksum_to_app_screenshot[checksum].nil? && index < 10 # if index is more than 10, it's skipped
|
209
|
+
end
|
202
210
|
|
203
|
-
|
211
|
+
missing_local_screenshots.each do |_, _, screenshot, _|
|
212
|
+
UI.error("#{screenshot.path} is missing on App Store Connect.")
|
213
|
+
end
|
204
214
|
|
205
|
-
|
206
|
-
|
207
|
-
next
|
208
|
-
end
|
215
|
+
missing_local_screenshots.empty?
|
216
|
+
end
|
209
217
|
|
210
|
-
|
211
|
-
|
212
|
-
duplicate = indized[localization.locale][set.screenshot_display_type][:checksums].include?(checksum)
|
218
|
+
def sort_screenshots(localizations)
|
219
|
+
iterator = AppScreenshotIterator.new(localizations)
|
213
220
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
end
|
221
|
+
# Re-order screenshots within app_screenshot_set
|
222
|
+
worker = QueueWorker.new(NUMBER_OF_THREADS) do |app_screenshot_set|
|
223
|
+
original_ids = app_screenshot_set.app_screenshots.map(&:id)
|
224
|
+
sorted_ids = app_screenshot_set.app_screenshots.sort_by(&:file_name).map(&:id)
|
225
|
+
if original_ids != sorted_ids
|
226
|
+
app_screenshot_set.reorder_screenshots(app_screenshot_ids: sorted_ids)
|
221
227
|
end
|
222
228
|
end
|
223
|
-
|
229
|
+
|
230
|
+
iterator.each_app_screenshot_set do |_, app_screenshot_set|
|
231
|
+
worker.enqueue(app_screenshot_set)
|
232
|
+
end
|
233
|
+
|
234
|
+
worker.start
|
224
235
|
end
|
225
236
|
|
226
237
|
def collect_screenshots(options)
|
@@ -293,11 +304,15 @@ module Deliver
|
|
293
304
|
|
294
305
|
# helper method so Spaceship::Tunes.client.available_languages is easier to test
|
295
306
|
def self.available_languages
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
307
|
+
# 2020-08-24 - Available locales are not available as an endpoint in App Store Connect
|
308
|
+
# Update with Spaceship::Tunes.client.available_languages.sort (as long as endpoint is avilable)
|
309
|
+
Deliver::Languages::ALL_LANGUAGES
|
310
|
+
end
|
311
|
+
|
312
|
+
# helper method to mock this step in tests
|
313
|
+
def self.calculate_checksum(path)
|
314
|
+
bytes = File.binread(path)
|
315
|
+
Digest::MD5.hexdigest(bytes)
|
301
316
|
end
|
302
317
|
end
|
303
318
|
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
module Fastlane
|
2
|
+
module Actions
|
3
|
+
module SharedValues
|
4
|
+
APP_STORE_CONNECT_API_KEY = :APP_STORE_CONNECT_API_KEY
|
5
|
+
end
|
6
|
+
|
7
|
+
class AppStoreConnectApiKeyAction < Action
|
8
|
+
def self.run(options)
|
9
|
+
key_id = options[:key_id]
|
10
|
+
issuer_id = options[:issuer_id]
|
11
|
+
key_content = options[:key_content]
|
12
|
+
key_filepath = options[:key_filepath]
|
13
|
+
duration = options[:duration]
|
14
|
+
in_house = options[:in_house]
|
15
|
+
|
16
|
+
if key_content.nil? && key_filepath.nil?
|
17
|
+
UI.user_error!(":key_content or :key_filepath is required")
|
18
|
+
end
|
19
|
+
|
20
|
+
# This hash matches the named arguments on
|
21
|
+
# the Spaceship::ConnectAPI::Token.create method
|
22
|
+
key = {
|
23
|
+
key_id: key_id,
|
24
|
+
issuer_id: issuer_id,
|
25
|
+
key: key_content || File.binread(key_filepath),
|
26
|
+
duration: duration,
|
27
|
+
in_house: in_house
|
28
|
+
}
|
29
|
+
|
30
|
+
Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY] = key
|
31
|
+
|
32
|
+
return key
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.description
|
36
|
+
"Load the App Store Connect API token to use in other fastlane tools and actions"
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.available_options
|
40
|
+
[
|
41
|
+
FastlaneCore::ConfigItem.new(key: :key_id,
|
42
|
+
env_name: "APP_STORE_CONNECT_API_KEY_KEY_ID",
|
43
|
+
description: "The key ID"),
|
44
|
+
FastlaneCore::ConfigItem.new(key: :issuer_id,
|
45
|
+
env_name: "APP_STORE_CONNECT_API_KEY_ISSUER_ID",
|
46
|
+
description: "The issuer ID"),
|
47
|
+
FastlaneCore::ConfigItem.new(key: :key_filepath,
|
48
|
+
env_name: "APP_STORE_CONNECT_API_KEY_KEY_FILEPATH",
|
49
|
+
description: "The path to the key p8 file",
|
50
|
+
optional: true,
|
51
|
+
conflicting_options: [:key_content],
|
52
|
+
verify_block: proc do |value|
|
53
|
+
UI.user_error!("Couldn't find key p8 file at path '#{value}'") unless File.exist?(value)
|
54
|
+
end),
|
55
|
+
FastlaneCore::ConfigItem.new(key: :key_content,
|
56
|
+
env_name: "APP_STORE_CONNECT_API_KEY_KEY",
|
57
|
+
description: "The content of the key p8 file",
|
58
|
+
optional: true,
|
59
|
+
conflicting_options: [:filepath]),
|
60
|
+
FastlaneCore::ConfigItem.new(key: :duration,
|
61
|
+
env_name: "APP_STORE_CONNECT_API_KEY_DURATION",
|
62
|
+
description: "The token session duration",
|
63
|
+
optional: true,
|
64
|
+
type: Integer),
|
65
|
+
FastlaneCore::ConfigItem.new(key: :in_house,
|
66
|
+
env_name: "APP_STORE_CONNECT_API_KEY_IN_HOUSE",
|
67
|
+
description: "Is App Store or Enterprise (in house) team? App Store Connect API cannot not determine this on its own (yet)",
|
68
|
+
optional: true,
|
69
|
+
type: Boolean)
|
70
|
+
]
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.output
|
74
|
+
[
|
75
|
+
['APP_STORE_CONNECT_API_KEY', 'The App Store Connect API key information used for authorization requests. This hash can be passed directly into the :api_key options on other tools or into Spaceship::ConnectAPI::Token.create method']
|
76
|
+
]
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.author
|
80
|
+
["joshdholtz"]
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.is_supported?(platform)
|
84
|
+
true
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.details
|
88
|
+
[
|
89
|
+
"Load the App Store Connect API token to use in other fastlane tools and actions"
|
90
|
+
].join("\n")
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.example_code
|
94
|
+
[
|
95
|
+
'app_store_connect_api_key(
|
96
|
+
key_id: "D83848D23",
|
97
|
+
issuer_id: "227b0bbf-ada8-458c-9d62-3d8022b7d07f",
|
98
|
+
key_filepath: "D83848D23.p8"
|
99
|
+
)',
|
100
|
+
'app_store_connect_api_key(
|
101
|
+
key_id: "D83848D23",
|
102
|
+
issuer_id: "227b0bbf-ada8-458c-9d62-3d8022b7d07f",
|
103
|
+
key_filepath: "D83848D23.p8",
|
104
|
+
duration: 200,
|
105
|
+
in_house: true
|
106
|
+
)',
|
107
|
+
'app_store_connect_api_key(
|
108
|
+
key_id: "D83848D23",
|
109
|
+
issuer_id: "227b0bbf-ada8-458c-9d62-3d8022b7d07f",
|
110
|
+
key_content: "-----BEGIN EC PRIVATE KEY-----\nfewfawefawfe\n-----END EC PRIVATE KEY-----"
|
111
|
+
)'
|
112
|
+
]
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.category
|
116
|
+
:app_store_connect
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|