fastlane 2.155.3 → 2.157.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +78 -78
- 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 +67 -7
- 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/command_executor.rb +1 -0
- 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 +16 -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 +36 -17
- data/sigh/lib/sigh/runner.rb +4 -4
- 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 +144 -213
- 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 +98 -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 +26 -23
- data/match/lib/match/.options.rb.swp +0 -0
- data/match/lib/match/.runner.rb.swp +0 -0
- data/sigh/lib/sigh/.options.rb.swp +0 -0
- data/sigh/lib/sigh/.runner.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/models/.profile.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/provisioning/.provisioning.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
|