fastlane 2.149.0 → 2.150.0.rc4
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 +82 -82
- data/deliver/lib/deliver.rb +0 -1
- data/deliver/lib/deliver/app_screenshot.rb +26 -25
- data/deliver/lib/deliver/options.rb +6 -11
- data/deliver/lib/deliver/runner.rb +7 -21
- data/deliver/lib/deliver/setup.rb +5 -30
- data/deliver/lib/deliver/submit_for_review.rb +155 -90
- data/deliver/lib/deliver/upload_metadata.rb +355 -143
- data/deliver/lib/deliver/upload_price_tier.rb +22 -8
- data/deliver/lib/deliver/upload_screenshots.rb +134 -39
- data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +77 -96
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +3 -2
- data/fastlane/lib/fastlane/actions/download_dsyms.rb +7 -1
- data/fastlane/lib/fastlane/actions/google_play_track_release_names.rb +74 -0
- data/fastlane/lib/fastlane/actions/set_changelog.rb +23 -20
- data/fastlane/lib/fastlane/actions/slack.rb +1 -1
- data/fastlane/lib/fastlane/actions/spm.rb +7 -0
- data/fastlane/lib/fastlane/actions/upload_symbols_to_crashlytics.rb +1 -32
- data/fastlane/lib/fastlane/lane.rb +3 -3
- data/fastlane/lib/fastlane/swift_fastlane_function.rb +8 -4
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/ControlCommand.swift +1 -0
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/Fastlane.swift +48 -12
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/xcshareddata/xcschemes/FastlaneRunner.xcscheme +3 -9
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/LaneFileProtocol.swift +2 -5
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +1 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/RubyCommand.swift +29 -6
- data/fastlane/swift/RubyCommandable.swift +1 -0
- data/fastlane/swift/Runner.swift +85 -13
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +1 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +3 -3
- data/fastlane/swift/SocketClient.swift +76 -45
- data/fastlane/swift/SocketClientDelegateProtocol.swift +1 -1
- data/fastlane/swift/SocketResponse.swift +1 -0
- data/fastlane_core/lib/fastlane_core/configuration/config_item.rb +1 -3
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +89 -52
- data/fastlane_core/lib/fastlane_core/pkg_file_analyser.rb +7 -0
- data/fastlane_core/lib/fastlane_core/project.rb +0 -1
- data/frameit/lib/frameit/device_types.rb +100 -100
- data/produce/lib/produce/itunes_connect.rb +32 -21
- data/produce/lib/produce/options.rb +3 -3
- data/sigh/lib/assets/resign.sh +7 -7
- data/snapshot/lib/assets/SnapshotHelper.swift +5 -5
- data/snapshot/lib/assets/SnapshotHelperXcode8.swift +3 -3
- data/snapshot/lib/snapshot/options.rb +0 -1
- data/snapshot/lib/snapshot/reports_generator.rb +8 -1
- data/spaceship/lib/spaceship/.DS_Store +0 -0
- data/spaceship/lib/spaceship/client.rb +4 -3
- data/spaceship/lib/spaceship/connect_api.rb +25 -2
- data/spaceship/lib/spaceship/connect_api/client.rb +97 -31
- data/spaceship/lib/spaceship/connect_api/file_uploader.rb +98 -0
- data/spaceship/lib/spaceship/connect_api/model.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +113 -0
- data/spaceship/lib/spaceship/connect_api/models/app.rb +120 -3
- data/spaceship/lib/spaceship/connect_api/models/app_category.rb +94 -0
- data/spaceship/lib/spaceship/connect_api/models/app_info.rb +67 -0
- data/spaceship/lib/spaceship/connect_api/models/app_info_localization.rb +38 -0
- data/spaceship/lib/spaceship/connect_api/models/app_preview.rb +129 -0
- data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +71 -0
- data/spaceship/lib/spaceship/connect_api/models/app_price.rb +22 -0
- data/spaceship/lib/spaceship/connect_api/models/app_price_tier.rb +12 -0
- data/spaceship/lib/spaceship/connect_api/models/app_review_attachment.rb +71 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +93 -0
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +101 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_review_detail.rb +51 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +183 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +86 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_phased_release.rb +36 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version_submission.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/build.rb +4 -0
- data/spaceship/lib/spaceship/connect_api/models/idfa_declaration.rb +40 -0
- data/spaceship/lib/spaceship/connect_api/models/reset_ratings_request.rb +26 -0
- data/spaceship/lib/spaceship/connect_api/models/territory.rb +27 -0
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +10 -3
- data/spaceship/lib/spaceship/connect_api/tunes/client.rb +33 -0
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +841 -0
- data/spaceship/lib/spaceship/spaceauth_runner.rb +2 -2
- data/supply/lib/supply/client.rb +19 -0
- data/supply/lib/supply/reader.rb +16 -0
- metadata +44 -39
- data/deliver/lib/deliver/upload_assets.rb +0 -27
- data/fastlane/lib/assets/.s3_html_template.erb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.hipchat.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
- data/scan/lib/scan/.options.rb.swp +0 -0
|
@@ -54,7 +54,7 @@ module Produce
|
|
|
54
54
|
optional: true,
|
|
55
55
|
default_value: "ios",
|
|
56
56
|
verify_block: proc do |value|
|
|
57
|
-
UI.user_error!("The platform can only be ios or osx") unless %('ios', 'osx').include?(value)
|
|
57
|
+
UI.user_error!("The platform can only be ios or osx") unless %('ios', 'osx', 'tvos').include?(value)
|
|
58
58
|
end),
|
|
59
59
|
FastlaneCore::ConfigItem.new(key: :platforms,
|
|
60
60
|
short_option: "-J",
|
|
@@ -64,13 +64,13 @@ module Produce
|
|
|
64
64
|
optional: true,
|
|
65
65
|
type: Array,
|
|
66
66
|
verify_block: proc do |values|
|
|
67
|
-
types = %w(ios osx)
|
|
67
|
+
types = %w(ios osx tvos)
|
|
68
68
|
UI.user_error!("The platform can only be #{types}") unless (values - types).empty?
|
|
69
69
|
end),
|
|
70
70
|
FastlaneCore::ConfigItem.new(key: :language,
|
|
71
71
|
short_option: "-m",
|
|
72
72
|
env_name: "PRODUCE_LANGUAGE",
|
|
73
|
-
description: "Primary Language (e.g. '
|
|
73
|
+
description: "Primary Language (e.g. 'en-US', 'fr-FR')",
|
|
74
74
|
default_value: "English",
|
|
75
75
|
verify_block: proc do |language|
|
|
76
76
|
end),
|
data/sigh/lib/assets/resign.sh
CHANGED
|
@@ -620,7 +620,7 @@ function resign {
|
|
|
620
620
|
# Start with using what comes in provisioning profile entitlements before patching
|
|
621
621
|
cp -f "$PROFILE_ENTITLEMENTS" "$PATCHED_ENTITLEMENTS"
|
|
622
622
|
|
|
623
|
-
log "Removing
|
|
623
|
+
log "Removing denylisted keys from patched profile"
|
|
624
624
|
# See https://github.com/facebook/buck/issues/798 and https://github.com/facebook/buck/pull/802/files
|
|
625
625
|
|
|
626
626
|
# Update in https://github.com/facebook/buck/commit/99c0fbc3ab5ecf04d186913374f660683deccdef
|
|
@@ -628,7 +628,7 @@ function resign {
|
|
|
628
628
|
|
|
629
629
|
# Buck changes referenced above are not self-explanatory and do not seem exhaustive or up-to-date
|
|
630
630
|
# Comments below explain the rules applied to each key in order to make realignment with future Xcode export logic easier
|
|
631
|
-
|
|
631
|
+
DENYLISTED_KEYS=(\
|
|
632
632
|
# PP list identifiers inconsistent with app-defined ones and this key does not seem to appear in IPA entitlements, so ignore it
|
|
633
633
|
"com.apple.developer.icloud-container-development-container-identifiers" \
|
|
634
634
|
# This key has an invalid generic value in PP (actual value is set by Xcode during export), see dedicated processing a few blocks below
|
|
@@ -637,7 +637,7 @@ function resign {
|
|
|
637
637
|
"com.apple.developer.icloud-container-identifiers" \
|
|
638
638
|
# PP enable all available services and not app-defined ones, must use App entitlements value
|
|
639
639
|
"com.apple.developer.icloud-services" \
|
|
640
|
-
# Was already
|
|
640
|
+
# Was already denylisted in previous version, but has someone ever seen this key in a PP?
|
|
641
641
|
"com.apple.developer.restricted-resource-mode" \
|
|
642
642
|
# If actually used by the App, this value will be set in its entitlements
|
|
643
643
|
"com.apple.developer.nfc.readersession.formats" \
|
|
@@ -675,15 +675,15 @@ function resign {
|
|
|
675
675
|
"com.apple.developer.default-data-protection" \
|
|
676
676
|
# PP seem to list the same groups as the App, but use App entitlements value to be sure
|
|
677
677
|
"com.apple.security.application-groups" \
|
|
678
|
-
# Was already
|
|
678
|
+
# Was already denylisted in previous version, seems to be an artifact from an old Xcode release
|
|
679
679
|
"com.apple.developer.maps" \
|
|
680
680
|
# If actually used by the App, this value will be set in its entitlements
|
|
681
681
|
"com.apple.external-accessory.wireless-configuration"
|
|
682
682
|
)
|
|
683
683
|
|
|
684
|
-
#
|
|
685
|
-
for KEY in "${
|
|
686
|
-
log "Removing
|
|
684
|
+
# Denylisted keys must not be included into new profile, so remove them from patched profile
|
|
685
|
+
for KEY in "${DENYLISTED_KEYS[@]}"; do
|
|
686
|
+
log "Removing denylisted key: $KEY"
|
|
687
687
|
PlistBuddy -c "Delete $KEY" "$PATCHED_ENTITLEMENTS" 2>/dev/null
|
|
688
688
|
done
|
|
689
689
|
|
|
@@ -218,7 +218,7 @@ open class Snapshot: NSObject {
|
|
|
218
218
|
|
|
219
219
|
private extension XCUIElementAttributes {
|
|
220
220
|
var isNetworkLoadingIndicator: Bool {
|
|
221
|
-
if
|
|
221
|
+
if hasAllowListedIdentifier { return false }
|
|
222
222
|
|
|
223
223
|
let hasOldLoadingIndicatorSize = frame.size == CGSize(width: 10, height: 20)
|
|
224
224
|
let hasNewLoadingIndicatorSize = frame.size.width.isBetween(46, and: 47) && frame.size.height.isBetween(2, and: 3)
|
|
@@ -226,10 +226,10 @@ private extension XCUIElementAttributes {
|
|
|
226
226
|
return hasOldLoadingIndicatorSize || hasNewLoadingIndicatorSize
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
var
|
|
230
|
-
let
|
|
229
|
+
var hasAllowListedIdentifier: Bool {
|
|
230
|
+
let allowListedIdentifiers = ["GeofenceLocationTrackingOn", "StandardLocationTrackingOn"]
|
|
231
231
|
|
|
232
|
-
return
|
|
232
|
+
return allowListedIdentifiers.contains(identifier)
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
func isStatusBar(_ deviceWidth: CGFloat) -> Bool {
|
|
@@ -279,4 +279,4 @@ private extension CGFloat {
|
|
|
279
279
|
|
|
280
280
|
// Please don't remove the lines below
|
|
281
281
|
// They are used to detect outdated configuration files
|
|
282
|
-
// SnapshotHelperVersion [1.
|
|
282
|
+
// SnapshotHelperVersion [1.23]
|
|
@@ -159,8 +159,8 @@ open class Snapshot: NSObject {
|
|
|
159
159
|
|
|
160
160
|
extension XCUIElement {
|
|
161
161
|
var isLoadingIndicator: Bool {
|
|
162
|
-
let
|
|
163
|
-
if
|
|
162
|
+
let allowListedLoaders = ["GeofenceLocationTrackingOn", "StandardLocationTrackingOn"]
|
|
163
|
+
if allowListedLoaders.contains(self.identifier) {
|
|
164
164
|
return false
|
|
165
165
|
}
|
|
166
166
|
return self.frame.size == CGSize(width: 10, height: 20)
|
|
@@ -169,4 +169,4 @@ extension XCUIElement {
|
|
|
169
169
|
|
|
170
170
|
// Please don't remove the lines below
|
|
171
171
|
// They are used to detect outdated configuration files
|
|
172
|
-
// SnapshotHelperXcode8Version [1.
|
|
172
|
+
// SnapshotHelperXcode8Version [1.5]
|
|
@@ -156,7 +156,6 @@ module Snapshot
|
|
|
156
156
|
env_name: 'SNAPSHOT_HTML_TEMPLATE',
|
|
157
157
|
short_option: "-e",
|
|
158
158
|
description: "A path to screenshots.html template",
|
|
159
|
-
default_value: File.join(Snapshot::ROOT, "lib", "snapshot/page.html.erb"),
|
|
160
159
|
optional: true),
|
|
161
160
|
|
|
162
161
|
# Everything around building
|
|
@@ -5,6 +5,14 @@ module Snapshot
|
|
|
5
5
|
require 'erb'
|
|
6
6
|
require 'fastimage'
|
|
7
7
|
|
|
8
|
+
def html_path
|
|
9
|
+
if Snapshot.config[:html_template]
|
|
10
|
+
Snapshot.config[:html_template]
|
|
11
|
+
else
|
|
12
|
+
File.join(Snapshot::ROOT, "lib", "snapshot/page.html.erb")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
8
16
|
def generate
|
|
9
17
|
UI.message("Generating HTML Report")
|
|
10
18
|
|
|
@@ -36,7 +44,6 @@ module Snapshot
|
|
|
36
44
|
end
|
|
37
45
|
end
|
|
38
46
|
|
|
39
|
-
html_path = Snapshot.config[:html_template]
|
|
40
47
|
html = ERB.new(File.read(html_path)).result(binding) # https://web.archive.org/web/20160430190141/www.rrn.dk/rubys-erb-templating-system
|
|
41
48
|
|
|
42
49
|
export_path = "#{screens_path}/screenshots.html"
|
|
Binary file
|
|
@@ -194,15 +194,16 @@ module Spaceship
|
|
|
194
194
|
self.new(cookie: another_client.instance_variable_get(:@cookie), current_team_id: another_client.team_id)
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
-
def initialize(cookie: nil, current_team_id: nil)
|
|
197
|
+
def initialize(cookie: nil, current_team_id: nil, timeout: nil)
|
|
198
198
|
options = {
|
|
199
199
|
request: {
|
|
200
|
-
timeout: (ENV["SPACESHIP_TIMEOUT"] || 300).to_i,
|
|
201
|
-
open_timeout: (ENV["SPACESHIP_TIMEOUT"] || 300).to_i
|
|
200
|
+
timeout: (ENV["SPACESHIP_TIMEOUT"] || timeout || 300).to_i,
|
|
201
|
+
open_timeout: (ENV["SPACESHIP_TIMEOUT"] || timeout || 300).to_i
|
|
202
202
|
}
|
|
203
203
|
}
|
|
204
204
|
@current_team_id = current_team_id
|
|
205
205
|
@cookie = cookie || HTTP::CookieJar.new
|
|
206
|
+
|
|
206
207
|
@client = Faraday.new(self.class.hostname, options) do |c|
|
|
207
208
|
c.response(:json, content_type: /\bjson$/)
|
|
208
209
|
c.response(:xml, content_type: /\bxml$/)
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
require 'spaceship/connect_api/model'
|
|
2
2
|
require 'spaceship/connect_api/response'
|
|
3
3
|
require 'spaceship/connect_api/token'
|
|
4
|
+
require 'spaceship/connect_api/file_uploader'
|
|
4
5
|
|
|
5
6
|
require 'spaceship/connect_api/provisioning/provisioning'
|
|
6
7
|
require 'spaceship/connect_api/testflight/testflight'
|
|
7
8
|
require 'spaceship/connect_api/users/users'
|
|
9
|
+
require 'spaceship/connect_api/tunes/tunes'
|
|
8
10
|
|
|
9
11
|
require 'spaceship/connect_api/models/bundle_id_capability'
|
|
10
12
|
require 'spaceship/connect_api/models/bundle_id'
|
|
@@ -30,11 +32,32 @@ require 'spaceship/connect_api/models/build_delivery'
|
|
|
30
32
|
require 'spaceship/connect_api/models/build_beta_detail'
|
|
31
33
|
require 'spaceship/connect_api/models/pre_release_version'
|
|
32
34
|
|
|
35
|
+
require 'spaceship/connect_api/models/age_rating_declaration'
|
|
36
|
+
require 'spaceship/connect_api/models/app_category'
|
|
37
|
+
require 'spaceship/connect_api/models/app_info'
|
|
38
|
+
require 'spaceship/connect_api/models/app_info_localization'
|
|
39
|
+
require 'spaceship/connect_api/models/app_preview_set'
|
|
40
|
+
require 'spaceship/connect_api/models/app_preview'
|
|
41
|
+
require 'spaceship/connect_api/models/app_price'
|
|
42
|
+
require 'spaceship/connect_api/models/app_price_tier'
|
|
43
|
+
require 'spaceship/connect_api/models/app_review_attachment'
|
|
44
|
+
require 'spaceship/connect_api/models/app_store_review_detail'
|
|
45
|
+
require 'spaceship/connect_api/models/app_store_version_submission'
|
|
46
|
+
require 'spaceship/connect_api/models/app_screenshot_set'
|
|
47
|
+
require 'spaceship/connect_api/models/app_screenshot'
|
|
48
|
+
require 'spaceship/connect_api/models/app_store_version_localization'
|
|
49
|
+
require 'spaceship/connect_api/models/app_store_version_phased_release'
|
|
50
|
+
require 'spaceship/connect_api/models/app_store_version'
|
|
51
|
+
require 'spaceship/connect_api/models/idfa_declaration'
|
|
52
|
+
require 'spaceship/connect_api/models/reset_ratings_request'
|
|
53
|
+
require 'spaceship/connect_api/models/territory'
|
|
54
|
+
|
|
33
55
|
module Spaceship
|
|
34
56
|
class ConnectAPI
|
|
35
57
|
extend Spaceship::ConnectAPI::Provisioning
|
|
36
58
|
extend Spaceship::ConnectAPI::TestFlight
|
|
37
59
|
extend Spaceship::ConnectAPI::Users
|
|
60
|
+
extend Spaceship::ConnectAPI::Tunes
|
|
38
61
|
|
|
39
62
|
@token = nil
|
|
40
63
|
|
|
@@ -63,9 +86,9 @@ module Spaceship
|
|
|
63
86
|
|
|
64
87
|
# Map from fastlane input and Spaceship::TestFlight platform values
|
|
65
88
|
case platform.to_sym
|
|
66
|
-
when :appletvos
|
|
89
|
+
when :appletvos, :tvos
|
|
67
90
|
return Spaceship::ConnectAPI::Platform::TV_OS
|
|
68
|
-
when :osx
|
|
91
|
+
when :osx, :macos, :mac
|
|
69
92
|
return Spaceship::ConnectAPI::Platform::MAC_OS
|
|
70
93
|
when :ios
|
|
71
94
|
return Spaceship::ConnectAPI::Platform::IOS
|
|
@@ -13,7 +13,7 @@ module Spaceship
|
|
|
13
13
|
# Instantiates a client with cookie session or a JWT token.
|
|
14
14
|
def initialize(cookie: nil, current_team_id: nil, token: nil)
|
|
15
15
|
if token.nil?
|
|
16
|
-
super(cookie: cookie, current_team_id: current_team_id)
|
|
16
|
+
super(cookie: cookie, current_team_id: current_team_id, timeout: 1200)
|
|
17
17
|
else
|
|
18
18
|
options = {
|
|
19
19
|
request: {
|
|
@@ -78,46 +78,76 @@ module Spaceship
|
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
def get(url_or_path, params = nil)
|
|
81
|
-
response =
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
81
|
+
response = with_asc_retry do
|
|
82
|
+
request(:get) do |req|
|
|
83
|
+
req.url(url_or_path)
|
|
84
|
+
req.options.params_encoder = Faraday::NestedParamsEncoder
|
|
85
|
+
req.params = params if params
|
|
86
|
+
req.headers['Content-Type'] = 'application/json'
|
|
87
|
+
end
|
|
86
88
|
end
|
|
87
89
|
handle_response(response)
|
|
88
90
|
end
|
|
89
91
|
|
|
90
92
|
def post(url_or_path, body)
|
|
91
|
-
response =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
93
|
+
response = with_asc_retry do
|
|
94
|
+
request(:post) do |req|
|
|
95
|
+
req.url(url_or_path)
|
|
96
|
+
req.body = body.to_json
|
|
97
|
+
req.headers['Content-Type'] = 'application/json'
|
|
98
|
+
end
|
|
95
99
|
end
|
|
96
100
|
handle_response(response)
|
|
97
101
|
end
|
|
98
102
|
|
|
99
103
|
def patch(url_or_path, body)
|
|
100
|
-
response =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
+
response = with_asc_retry do
|
|
105
|
+
request(:patch) do |req|
|
|
106
|
+
req.url(url_or_path)
|
|
107
|
+
req.body = body.to_json
|
|
108
|
+
req.headers['Content-Type'] = 'application/json'
|
|
109
|
+
end
|
|
104
110
|
end
|
|
105
111
|
handle_response(response)
|
|
106
112
|
end
|
|
107
113
|
|
|
108
114
|
def delete(url_or_path, params = nil, body = nil)
|
|
109
|
-
response =
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
+
response = with_asc_retry do
|
|
116
|
+
request(:delete) do |req|
|
|
117
|
+
req.url(url_or_path)
|
|
118
|
+
req.options.params_encoder = Faraday::NestedParamsEncoder if params
|
|
119
|
+
req.params = params if params
|
|
120
|
+
req.body = body.to_json if body
|
|
121
|
+
req.headers['Content-Type'] = 'application/json' if body
|
|
122
|
+
end
|
|
115
123
|
end
|
|
116
124
|
handle_response(response)
|
|
117
125
|
end
|
|
118
126
|
|
|
119
127
|
protected
|
|
120
128
|
|
|
129
|
+
def with_asc_retry(tries = 5, &_block)
|
|
130
|
+
tries = 1 if Object.const_defined?("SpecHelper")
|
|
131
|
+
response = yield
|
|
132
|
+
|
|
133
|
+
tries -= 1
|
|
134
|
+
status = response.status if response
|
|
135
|
+
|
|
136
|
+
if [504].include?(status)
|
|
137
|
+
msg = "Timeout received! Retrying after 3 seconds (remaining: #{tries})..."
|
|
138
|
+
raise msg
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
return response
|
|
142
|
+
rescue => error
|
|
143
|
+
puts(error) if Spaceship::Globals.verbose?
|
|
144
|
+
if tries.zero?
|
|
145
|
+
return response
|
|
146
|
+
else
|
|
147
|
+
retry
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
121
151
|
def handle_response(response)
|
|
122
152
|
if (200...300).cover?(response.status) && (response.body.nil? || response.body.empty?)
|
|
123
153
|
return
|
|
@@ -141,21 +171,57 @@ module Spaceship
|
|
|
141
171
|
def handle_errors(response)
|
|
142
172
|
# Example error format
|
|
143
173
|
# {
|
|
144
|
-
#
|
|
145
|
-
#
|
|
146
|
-
#
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
#
|
|
150
|
-
#
|
|
151
|
-
# "
|
|
174
|
+
# "errors":[
|
|
175
|
+
# {
|
|
176
|
+
# "id":"cbfd8674-4802-4857-bfe8-444e1ea36e32",
|
|
177
|
+
# "status":"409",
|
|
178
|
+
# "code":"STATE_ERROR",
|
|
179
|
+
# "title":"The request cannot be fulfilled because of the state of another resource.",
|
|
180
|
+
# "detail":"Submit for review errors found.",
|
|
181
|
+
# "meta":{
|
|
182
|
+
# "associatedErrors":{
|
|
183
|
+
# "/v1/appScreenshots/":[
|
|
184
|
+
# {
|
|
185
|
+
# "id":"23d1734f-b81f-411a-98e4-6d3e763d54ed",
|
|
186
|
+
# "status":"409",
|
|
187
|
+
# "code":"STATE_ERROR.SCREENSHOT_REQUIRED.APP_WATCH_SERIES_4",
|
|
188
|
+
# "title":"App screenshot missing (APP_WATCH_SERIES_4)."
|
|
189
|
+
# },
|
|
190
|
+
# {
|
|
191
|
+
# "id":"db993030-0a93-48e9-9fd7-7e5676633431",
|
|
192
|
+
# "status":"409",
|
|
193
|
+
# "code":"STATE_ERROR.SCREENSHOT_REQUIRED.APP_WATCH_SERIES_4",
|
|
194
|
+
# "title":"App screenshot missing (APP_WATCH_SERIES_4)."
|
|
195
|
+
# }
|
|
196
|
+
# ],
|
|
197
|
+
# "/v1/builds/d710b6fa-5235-4fe4-b791-2b80d6818db0":[
|
|
198
|
+
# {
|
|
199
|
+
# "id":"e421fe6f-0e3b-464b-89dc-ba437e7bb77d",
|
|
200
|
+
# "status":"409",
|
|
201
|
+
# "code":"ENTITY_ERROR.ATTRIBUTE.REQUIRED",
|
|
202
|
+
# "title":"The provided entity is missing a required attribute",
|
|
203
|
+
# "detail":"You must provide a value for the attribute 'usesNonExemptEncryption' with this request",
|
|
204
|
+
# "source":{
|
|
205
|
+
# "pointer":"/data/attributes/usesNonExemptEncryption"
|
|
206
|
+
# }
|
|
207
|
+
# }
|
|
208
|
+
# ]
|
|
209
|
+
# }
|
|
210
|
+
# }
|
|
152
211
|
# }
|
|
153
|
-
#
|
|
212
|
+
# ]
|
|
154
213
|
# }
|
|
155
214
|
|
|
156
215
|
return response.body['errors'].map do |error|
|
|
157
|
-
|
|
158
|
-
|
|
216
|
+
messages = [[error['title'], error['detail']].compact.join(" - ")]
|
|
217
|
+
|
|
218
|
+
meta = error["meta"] || {}
|
|
219
|
+
associated_errors = meta["associatedErrors"] || {}
|
|
220
|
+
|
|
221
|
+
messages + associated_errors.values.flatten.map do |associated_error|
|
|
222
|
+
[[associated_error["title"], associated_error["detail"]].compact.join(" - ")]
|
|
223
|
+
end
|
|
224
|
+
end.flatten.join("\n")
|
|
159
225
|
end
|
|
160
226
|
|
|
161
227
|
private
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
require 'faraday' # HTTP Client
|
|
2
|
+
require 'faraday-cookie_jar'
|
|
3
|
+
require 'faraday_middleware'
|
|
4
|
+
|
|
5
|
+
require 'spaceship/globals'
|
|
6
|
+
|
|
7
|
+
module Spaceship
|
|
8
|
+
class ConnectAPI
|
|
9
|
+
module FileUploader
|
|
10
|
+
def self.upload(upload_operations, bytes)
|
|
11
|
+
# {
|
|
12
|
+
# "method": "PUT",
|
|
13
|
+
# "url": "https://some-url-apple-gives-us",
|
|
14
|
+
# "length": 57365,
|
|
15
|
+
# "offset": 0,
|
|
16
|
+
# "requestHeaders": [
|
|
17
|
+
# {
|
|
18
|
+
# "name": "Content-Type",
|
|
19
|
+
# "value": "image/png"
|
|
20
|
+
# }
|
|
21
|
+
# ]
|
|
22
|
+
# }
|
|
23
|
+
|
|
24
|
+
upload_operations.each_with_index do |upload_operation, index|
|
|
25
|
+
headers = {}
|
|
26
|
+
upload_operation["requestHeaders"].each do |hash|
|
|
27
|
+
headers[hash["name"]] = hash["value"]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
offset = upload_operation["offset"]
|
|
31
|
+
length = upload_operation["length"]
|
|
32
|
+
|
|
33
|
+
puts("Uploading file (part #{index + 1})...") if Spaceship::Globals.verbose?
|
|
34
|
+
with_retry do
|
|
35
|
+
client.send(
|
|
36
|
+
upload_operation["method"].downcase,
|
|
37
|
+
upload_operation["url"],
|
|
38
|
+
bytes[offset, length],
|
|
39
|
+
headers
|
|
40
|
+
)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
puts("Uploading complete!") if Spaceship::Globals.verbose?
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.with_retry(tries = 5, &_block)
|
|
47
|
+
tries = 1 if Object.const_defined?("SpecHelper")
|
|
48
|
+
response = yield
|
|
49
|
+
|
|
50
|
+
tries -= 1
|
|
51
|
+
|
|
52
|
+
unless (200...300).cover?(response.status)
|
|
53
|
+
msg = "Received status of #{response.status}! Retrying after 3 seconds (remaining: #{tries})..."
|
|
54
|
+
raise msg
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
return response
|
|
58
|
+
rescue => error
|
|
59
|
+
puts(error) if Spaceship::Globals.verbose?
|
|
60
|
+
if tries.zero?
|
|
61
|
+
raise "Failed to upload file after retries... Received #{response.status}"
|
|
62
|
+
else
|
|
63
|
+
retry
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def self.client
|
|
68
|
+
options = {
|
|
69
|
+
request: {
|
|
70
|
+
timeout: (ENV["SPACESHIP_TIMEOUT"] || 300).to_i,
|
|
71
|
+
open_timeout: (ENV["SPACESHIP_TIMEOUT"] || 300).to_i
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@client ||= Faraday.new(options) do |c|
|
|
76
|
+
c.response(:json, content_type: /\bjson$/)
|
|
77
|
+
c.response(:xml, content_type: /\bxml$/)
|
|
78
|
+
c.response(:plist, content_type: /\bplist$/)
|
|
79
|
+
c.adapter(Faraday.default_adapter)
|
|
80
|
+
|
|
81
|
+
if ENV['SPACESHIP_DEBUG']
|
|
82
|
+
# for debugging only
|
|
83
|
+
# This enables tracking of networking requests using Charles Web Proxy
|
|
84
|
+
c.proxy = "https://127.0.0.1:8888"
|
|
85
|
+
c.ssl[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
|
|
86
|
+
elsif ENV["SPACESHIP_PROXY"]
|
|
87
|
+
c.proxy = ENV["SPACESHIP_PROXY"]
|
|
88
|
+
c.ssl[:verify_mode] = OpenSSL::SSL::VERIFY_NONE if ENV["SPACESHIP_PROXY_SSL_VERIFY_NONE"]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if ENV["DEBUG"]
|
|
92
|
+
puts("To run spaceship through a local proxy, use SPACESHIP_DEBUG")
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|