fastlane 2.150.0.rc2 → 2.150.0.rc7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/deliver/lib/deliver/download_screenshots.rb +48 -26
- data/deliver/lib/deliver/runner.rb +4 -1
- data/deliver/lib/deliver/submit_for_review.rb +26 -7
- data/deliver/lib/deliver/upload_metadata.rb +18 -2
- data/deliver/lib/deliver/upload_screenshots.rb +34 -8
- data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +4 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- data/fastlane_core/lib/fastlane_core/build_watcher.rb +4 -4
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +89 -52
- data/pilot/lib/pilot/.manager.rb.swp +0 -0
- data/produce/lib/produce/itunes_connect.rb +29 -2
- data/spaceship/lib/spaceship/{.DS_Store → connect_api/.DS_Store} +0 -0
- data/spaceship/lib/spaceship/connect_api/client.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/file_uploader.rb +42 -10
- data/spaceship/lib/spaceship/connect_api/models/age_rating_declaration.rb +1 -1
- data/spaceship/lib/spaceship/connect_api/models/app.rb +47 -9
- data/spaceship/lib/spaceship/connect_api/models/app_info.rb +4 -0
- data/spaceship/lib/spaceship/connect_api/models/app_preview.rb +62 -10
- data/spaceship/lib/spaceship/connect_api/models/app_preview_set.rb +2 -2
- data/spaceship/lib/spaceship/connect_api/models/app_review_attachment.rb +18 -28
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +86 -37
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +26 -2
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +20 -1
- data/spaceship/lib/spaceship/connect_api/models/user.rb +2 -1
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +21 -9
- data/spaceship/lib/spaceship/connect_api/users/users.rb +13 -0
- metadata +12 -7
Binary file
|
@@ -21,6 +21,13 @@ module Produce
|
|
21
21
|
UI.success("App '#{Produce.config[:app_identifier]}' already exists (#{application.id}), nothing to do on App Store Connect")
|
22
22
|
# Nothing to do here
|
23
23
|
else
|
24
|
+
emails = Produce.config[:itc_users] || []
|
25
|
+
user_ids = []
|
26
|
+
unless emails.empty?
|
27
|
+
UI.message("Verifying users exist before creating app...")
|
28
|
+
user_ids = find_user_ids(emails: emails)
|
29
|
+
end
|
30
|
+
|
24
31
|
UI.success("Creating new app '#{Produce.config[:app_name]}' on App Store Connect")
|
25
32
|
|
26
33
|
platforms = Produce.config[:platforms] || [Produce.config[:platform]]
|
@@ -29,7 +36,6 @@ module Produce
|
|
29
36
|
Spaceship::ConnectAPI::Platform.map(platform)
|
30
37
|
end
|
31
38
|
|
32
|
-
# Produce.config[:company_name]
|
33
39
|
# Produce.config[:itc_users]
|
34
40
|
application = Spaceship::ConnectAPI::App.create(
|
35
41
|
name: Produce.config[:app_name],
|
@@ -37,7 +43,8 @@ module Produce
|
|
37
43
|
sku: Produce.config[:sku].to_s,
|
38
44
|
primary_locale: language,
|
39
45
|
bundle_id: app_identifier,
|
40
|
-
platforms: platforms
|
46
|
+
platforms: platforms,
|
47
|
+
company_name: Produce.config[:company_name]
|
41
48
|
)
|
42
49
|
|
43
50
|
application = fetch_application
|
@@ -60,12 +67,32 @@ module Produce
|
|
60
67
|
application.ensure_version!(Produce.config[:app_version], platform: platform) if Produce.config[:app_version]
|
61
68
|
end
|
62
69
|
|
70
|
+
# Add users to app
|
71
|
+
unless user_ids.empty?
|
72
|
+
application.add_users(user_ids: user_ids)
|
73
|
+
UI.message("Successfuly added #{user_ids.size} #{user_ids.count == 1 ? 'user' : 'users'} to app")
|
74
|
+
end
|
75
|
+
|
63
76
|
UI.success("Successfully created new app '#{Produce.config[:app_name]}' on App Store Connect with ID #{application.id}")
|
64
77
|
end
|
65
78
|
|
66
79
|
return application.id
|
67
80
|
end
|
68
81
|
|
82
|
+
def find_user_ids(emails: nil)
|
83
|
+
emails ||= []
|
84
|
+
users = Spaceship::ConnectAPI::User.all.select do |user|
|
85
|
+
emails.include?(user.email)
|
86
|
+
end
|
87
|
+
|
88
|
+
diff_emails = emails - users.map(&:email)
|
89
|
+
unless diff_emails.empty?
|
90
|
+
raise "Could not find users with emails of: #{diff_emails.join(',')}"
|
91
|
+
end
|
92
|
+
|
93
|
+
return users.map(&:id)
|
94
|
+
end
|
95
|
+
|
69
96
|
private
|
70
97
|
|
71
98
|
def platform
|
Binary file
|
@@ -2,10 +2,12 @@ require 'faraday' # HTTP Client
|
|
2
2
|
require 'faraday-cookie_jar'
|
3
3
|
require 'faraday_middleware'
|
4
4
|
|
5
|
+
require 'spaceship/globals'
|
6
|
+
|
5
7
|
module Spaceship
|
6
8
|
class ConnectAPI
|
7
9
|
module FileUploader
|
8
|
-
def self.upload(
|
10
|
+
def self.upload(upload_operations, bytes)
|
9
11
|
# {
|
10
12
|
# "method": "PUT",
|
11
13
|
# "url": "https://some-url-apple-gives-us",
|
@@ -19,17 +21,47 @@ module Spaceship
|
|
19
21
|
# ]
|
20
22
|
# }
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
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
|
25
42
|
end
|
43
|
+
puts("Uploading complete!") if Spaceship::Globals.verbose?
|
44
|
+
end
|
26
45
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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
|
33
65
|
end
|
34
66
|
|
35
67
|
def self.client
|
@@ -54,16 +54,15 @@ module Spaceship
|
|
54
54
|
end
|
55
55
|
end
|
56
56
|
|
57
|
-
def self.create(name: nil, version_string: nil, sku: nil, primary_locale: nil, bundle_id: nil, platforms: nil)
|
57
|
+
def self.create(name: nil, version_string: nil, sku: nil, primary_locale: nil, bundle_id: nil, platforms: nil, company_name: nil)
|
58
58
|
Spaceship::ConnectAPI.post_app(
|
59
59
|
name: name,
|
60
60
|
version_string: version_string,
|
61
|
-
sku: sku,
|
62
|
-
primary_locale,
|
61
|
+
sku: sku,
|
62
|
+
primary_locale: primary_locale,
|
63
63
|
bundle_id: bundle_id,
|
64
64
|
platforms: platforms,
|
65
|
-
|
66
|
-
available_in_new_territories: available_in_new_territories
|
65
|
+
company_name: company_name
|
67
66
|
)
|
68
67
|
end
|
69
68
|
|
@@ -84,10 +83,13 @@ module Spaceship
|
|
84
83
|
Spaceship::ConnectAPI::AppInfo::AppStoreState::PREPARE_FOR_SUBMISSION,
|
85
84
|
Spaceship::ConnectAPI::AppInfo::AppStoreState::DEVELOPER_REJECTED,
|
86
85
|
Spaceship::ConnectAPI::AppInfo::AppStoreState::REJECTED,
|
87
|
-
Spaceship::ConnectAPI::AppInfo::AppStoreState::METADATA_REJECTED
|
86
|
+
Spaceship::ConnectAPI::AppInfo::AppStoreState::METADATA_REJECTED,
|
87
|
+
Spaceship::ConnectAPI::AppInfo::AppStoreState::WAITING_FOR_REVIEW,
|
88
|
+
Spaceship::ConnectAPI::AppInfo::AppStoreState::INVALID_BINARY
|
88
89
|
]
|
89
90
|
|
90
|
-
|
91
|
+
filter = { app: id }
|
92
|
+
resp = Spaceship::ConnectAPI.get_app_infos(filter: filter)
|
91
93
|
return resp.to_models.select do |model|
|
92
94
|
states.include?(model.app_store_state)
|
93
95
|
end.first
|
@@ -108,6 +110,26 @@ module Spaceship
|
|
108
110
|
# App Store Versions
|
109
111
|
#
|
110
112
|
|
113
|
+
def reject_version_if_possible!
|
114
|
+
platform ||= Spaceship::ConnectAPI::Platform::IOS
|
115
|
+
filter = {
|
116
|
+
appStoreState: [
|
117
|
+
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::PENDING_DEVELOPER_RELEASE,
|
118
|
+
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::IN_REVIEW,
|
119
|
+
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::WAITING_FOR_REVIEW
|
120
|
+
].join(","),
|
121
|
+
platform: platform
|
122
|
+
}
|
123
|
+
|
124
|
+
# Get the latest version
|
125
|
+
version = get_app_store_versions(filter: filter, includes: "appStoreVersionSubmission")
|
126
|
+
.sort_by { |v| Gem::Version.new(v.version_string) }
|
127
|
+
.last
|
128
|
+
|
129
|
+
return false if version.nil?
|
130
|
+
return version.reject!
|
131
|
+
end
|
132
|
+
|
111
133
|
# Will make sure the current edit_version matches the given version number
|
112
134
|
# This will either create a new version or change the version number
|
113
135
|
# from an existing version
|
@@ -146,11 +168,17 @@ module Spaceship
|
|
146
168
|
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::PREPARE_FOR_SUBMISSION,
|
147
169
|
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::DEVELOPER_REJECTED,
|
148
170
|
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::REJECTED,
|
149
|
-
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::METADATA_REJECTED
|
171
|
+
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::METADATA_REJECTED,
|
172
|
+
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::WAITING_FOR_REVIEW,
|
173
|
+
Spaceship::ConnectAPI::AppStoreVersion::AppStoreState::INVALID_BINARY
|
150
174
|
].join(","),
|
151
175
|
platform: platform
|
152
176
|
}
|
153
|
-
|
177
|
+
|
178
|
+
# Get the latest version
|
179
|
+
return get_app_store_versions(filter: filter, includes: includes)
|
180
|
+
.sort_by { |v| Gem::Version.new(v.version_string) }
|
181
|
+
.last
|
154
182
|
end
|
155
183
|
|
156
184
|
def get_app_store_versions(filter: {}, includes: nil, limit: nil, sort: nil)
|
@@ -228,6 +256,16 @@ module Spaceship
|
|
228
256
|
).all_pages
|
229
257
|
return resps.flat_map(&:to_models).first
|
230
258
|
end
|
259
|
+
|
260
|
+
#
|
261
|
+
# Users
|
262
|
+
#
|
263
|
+
|
264
|
+
def add_users(user_ids: nil)
|
265
|
+
user_ids.each do |user_id|
|
266
|
+
Spaceship::ConnectAPI.add_user_visible_apps(user_id: user_id, app_ids: [id])
|
267
|
+
end
|
268
|
+
end
|
231
269
|
end
|
232
270
|
end
|
233
271
|
end
|
@@ -11,11 +11,15 @@ module Spaceship
|
|
11
11
|
|
12
12
|
module AppStoreState
|
13
13
|
READY_FOR_SALE = "READY_FOR_SALE"
|
14
|
+
PROCESSING_FOR_APP_STORE = "PROCESSING_FOR_APP_STORE"
|
15
|
+
PENDING_DEVELOPER_RELEASE = "PENDING_DEVELOPER_RELEASE"
|
16
|
+
IN_REVIEW = "IN_REVIEW"
|
14
17
|
WAITING_FOR_REVIEW = "WAITING_FOR_REVIEW"
|
15
18
|
DEVELOPER_REJECTED = "DEVELOPER_REJECTED"
|
16
19
|
REJECTED = "REJECTED"
|
17
20
|
PREPARE_FOR_SUBMISSION = "PREPARE_FOR_SUBMISSION"
|
18
21
|
METADATA_REJECTED = "METADATA_REJECTED"
|
22
|
+
INVALID_BINARY = "INVALID_BINARY"
|
19
23
|
end
|
20
24
|
|
21
25
|
module AppStoreAgeRating
|
@@ -1,5 +1,8 @@
|
|
1
1
|
require_relative '../model'
|
2
2
|
require_relative '../file_uploader'
|
3
|
+
require 'spaceship/globals'
|
4
|
+
|
5
|
+
require 'digest/md5'
|
3
6
|
|
4
7
|
module Spaceship
|
5
8
|
class ConnectAPI
|
@@ -34,39 +37,88 @@ module Spaceship
|
|
34
37
|
return "appPreviews"
|
35
38
|
end
|
36
39
|
|
40
|
+
def complete?
|
41
|
+
(asset_delivery_state || {})["state"] == "COMPLETE"
|
42
|
+
end
|
43
|
+
|
37
44
|
#
|
38
45
|
# API
|
39
46
|
#
|
40
47
|
|
41
|
-
def self.
|
48
|
+
def self.get(app_preview_id: nil)
|
49
|
+
Spaceship::ConnectAPI.get_app_preview(app_preview_id: app_preview_id).first
|
50
|
+
end
|
51
|
+
|
52
|
+
# Creates an AppPreview in an AppPreviewSet
|
53
|
+
# Setting the optional frame_time_code will force polling until video is done processing
|
54
|
+
# @param app_preview_set_id The AppPreviewSet id
|
55
|
+
# @param path The path of the file
|
56
|
+
# @param frame_time_code The time code for the preview still frame (ex: "00:00:07:01")
|
57
|
+
def self.create(app_preview_set_id: nil, path: nil, frame_time_code: nil)
|
42
58
|
require 'faraday'
|
43
59
|
|
44
60
|
filename = File.basename(path)
|
45
61
|
filesize = File.size(path)
|
46
|
-
|
62
|
+
bytes = File.binread(path)
|
47
63
|
|
48
64
|
post_attributes = {
|
49
65
|
fileSize: filesize,
|
50
66
|
fileName: filename
|
51
67
|
}
|
52
68
|
|
53
|
-
|
69
|
+
# Create placeholder
|
70
|
+
preview = Spaceship::ConnectAPI.post_app_preview(
|
54
71
|
app_preview_set_id: app_preview_set_id,
|
55
72
|
attributes: post_attributes
|
56
73
|
).to_models.first
|
57
74
|
|
58
|
-
|
59
|
-
|
75
|
+
# Upload the file
|
76
|
+
upload_operations = preview.upload_operations
|
77
|
+
Spaceship::ConnectAPI::FileUploader.upload(upload_operations, bytes)
|
60
78
|
|
79
|
+
# Update file uploading complete
|
61
80
|
patch_attributes = {
|
62
81
|
uploaded: true,
|
63
|
-
sourceFileChecksum:
|
82
|
+
sourceFileChecksum: Digest::MD5.hexdigest(bytes)
|
64
83
|
}
|
65
84
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
85
|
+
begin
|
86
|
+
preview = Spaceship::ConnectAPI.patch_app_preview(
|
87
|
+
app_preview_id: preview.id,
|
88
|
+
attributes: patch_attributes
|
89
|
+
).to_models.first
|
90
|
+
rescue => error
|
91
|
+
puts("Failed to patch app preview. Update may have gone through so verifying") if Spaceship::Globals.verbose?
|
92
|
+
|
93
|
+
preview = Spaceship::ConnectAPI::AppPreview.get(app_preview_id: preview.id)
|
94
|
+
raise error unless preview.complete?
|
95
|
+
end
|
96
|
+
|
97
|
+
# Poll for video processing completion to set still frame time
|
98
|
+
unless frame_time_code.nil?
|
99
|
+
loop do
|
100
|
+
unless preview.video_url.nil?
|
101
|
+
puts("Preview processing complete!") if Spaceship::Globals.verbose?
|
102
|
+
preview = preview.update(attributes: {
|
103
|
+
previewFrameTimeCode: frame_time_code
|
104
|
+
})
|
105
|
+
puts("Updated preview frame time code!") if Spaceship::Globals.verbose?
|
106
|
+
break
|
107
|
+
end
|
108
|
+
|
109
|
+
sleep_time = 30
|
110
|
+
puts("Waiting #{sleep_time} seconds before checking status of processing...") if Spaceship::Globals.verbose?
|
111
|
+
sleep(sleep_time)
|
112
|
+
|
113
|
+
preview = Spaceship::ConnectAPI::AppPreview.get(app_preview_id: preview.id)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
preview
|
118
|
+
end
|
119
|
+
|
120
|
+
def update(attributes: nil)
|
121
|
+
Spaceship::ConnectAPI.patch_app_preview(app_preview_id: id, attributes: attributes)
|
70
122
|
end
|
71
123
|
|
72
124
|
def delete!(filter: {}, includes: nil, limit: nil, sort: nil)
|
@@ -63,8 +63,8 @@ module Spaceship
|
|
63
63
|
return resp.to_models
|
64
64
|
end
|
65
65
|
|
66
|
-
def upload_preview(path: nil)
|
67
|
-
return Spaceship::ConnectAPI::AppPreview.create(app_preview_set_id: id, path: path)
|
66
|
+
def upload_preview(path: nil, frame_time_code: nil)
|
67
|
+
return Spaceship::ConnectAPI::AppPreview.create(app_preview_set_id: id, path: path, frame_time_code: frame_time_code)
|
68
68
|
end
|
69
69
|
end
|
70
70
|
end
|
@@ -1,4 +1,7 @@
|
|
1
1
|
require_relative '../model'
|
2
|
+
require_relative '../file_uploader'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
2
5
|
module Spaceship
|
3
6
|
class ConnectAPI
|
4
7
|
class AppReviewAttachment
|
@@ -31,46 +34,33 @@ module Spaceship
|
|
31
34
|
|
32
35
|
filename = File.basename(path)
|
33
36
|
filesize = File.size(path)
|
34
|
-
|
37
|
+
bytes = File.binread(path)
|
35
38
|
|
36
39
|
post_attributes = {
|
37
40
|
fileSize: filesize,
|
38
41
|
fileName: filename
|
39
42
|
}
|
40
43
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
# "length": 57365,
|
47
|
-
# "offset": 0,
|
48
|
-
# "requestHeaders": [
|
49
|
-
# {
|
50
|
-
# "name": "Content-Type",
|
51
|
-
# "value": "image/png"
|
52
|
-
# }
|
53
|
-
# ]
|
54
|
-
# }
|
55
|
-
upload_operation = post_resp.upload_operations.first
|
56
|
-
|
57
|
-
headers = {}
|
58
|
-
upload_operation["requestHeaders"].each do |hash|
|
59
|
-
headers[hash["name"]] = hash["value"]
|
60
|
-
end
|
44
|
+
# Create placeholder
|
45
|
+
attachment = Spaceship::ConnectAPI.post_app_review_attachment(
|
46
|
+
app_store_review_detail_id: app_store_review_detail_id,
|
47
|
+
attributes: post_attributes
|
48
|
+
).to_models.first
|
61
49
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
headers
|
66
|
-
)
|
50
|
+
# Upload the file
|
51
|
+
upload_operations = attachment.upload_operations
|
52
|
+
Spaceship::ConnectAPI::FileUploader.upload(upload_operations, bytes)
|
67
53
|
|
54
|
+
# Update file uploading complete
|
68
55
|
patch_attributes = {
|
69
56
|
uploaded: true,
|
70
|
-
sourceFileChecksum:
|
57
|
+
sourceFileChecksum: Digest::MD5.hexdigest(bytes)
|
71
58
|
}
|
72
59
|
|
73
|
-
Spaceship::ConnectAPI.patch_app_review_attachment(
|
60
|
+
Spaceship::ConnectAPI.patch_app_review_attachment(
|
61
|
+
app_review_attachment_id: attachment.id,
|
62
|
+
attributes: patch_attributes
|
63
|
+
).to_models.first
|
74
64
|
end
|
75
65
|
|
76
66
|
def delete!(filter: {}, includes: nil, limit: nil, sort: nil)
|