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
|
@@ -1,132 +1,197 @@
|
|
|
1
1
|
require_relative 'module'
|
|
2
2
|
|
|
3
|
+
require 'fastlane_core/build_watcher'
|
|
4
|
+
require 'fastlane_core/ipa_file_analyser'
|
|
5
|
+
require 'fastlane_core/pkg_file_analyser'
|
|
6
|
+
|
|
3
7
|
module Deliver
|
|
4
8
|
class SubmitForReview
|
|
5
9
|
def submit!(options)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
submission.add_id_info_uses_idfa = false
|
|
17
|
-
|
|
18
|
-
# User Values
|
|
19
|
-
if options[:submission_information]
|
|
20
|
-
options[:submission_information].each do |key, value|
|
|
21
|
-
UI.message("Setting '#{key}' to '#{value}'...")
|
|
22
|
-
submission.send("#{key}=", value)
|
|
23
|
-
end
|
|
10
|
+
legacy_app = options[:app]
|
|
11
|
+
app_id = legacy_app.apple_id
|
|
12
|
+
app = Spaceship::ConnectAPI::App.get(app_id: app_id)
|
|
13
|
+
|
|
14
|
+
platform = Spaceship::ConnectAPI::Platform.map(options[:platform])
|
|
15
|
+
version = app.get_edit_app_store_version(platform: platform)
|
|
16
|
+
|
|
17
|
+
unless version
|
|
18
|
+
UI.user_error!("Cannot submit for review - could not find an editable version for '#{platform}'")
|
|
19
|
+
return
|
|
24
20
|
end
|
|
25
21
|
|
|
26
|
-
|
|
27
|
-
|
|
22
|
+
build = select_build(options, app, version, platform)
|
|
23
|
+
|
|
24
|
+
update_export_compliance(options, app, build)
|
|
25
|
+
update_idfa(options, app, version)
|
|
26
|
+
update_submission_information(options, app)
|
|
27
|
+
|
|
28
|
+
version.create_app_store_version_submission
|
|
28
29
|
|
|
29
30
|
UI.success("Successfully submitted the app for review!")
|
|
30
31
|
end
|
|
31
32
|
|
|
32
|
-
private def select_build(options)
|
|
33
|
-
app = options[:app]
|
|
34
|
-
app_version = options[:app_version]
|
|
35
|
-
v = app.edit_version(platform: options[:platform])
|
|
36
|
-
|
|
33
|
+
private def select_build(options, app, version, platform)
|
|
37
34
|
if options[:build_number] && options[:build_number] != "latest"
|
|
38
35
|
UI.message("Selecting existing build-number: #{options[:build_number]}")
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
36
|
+
|
|
37
|
+
build = Spaceship::ConnectAPI::Build.all(
|
|
38
|
+
app_id: app.id,
|
|
39
|
+
version: options[:app_version],
|
|
40
|
+
build_number: options[:build_number],
|
|
41
|
+
platform: platform
|
|
42
|
+
).first
|
|
43
|
+
|
|
44
44
|
unless build
|
|
45
45
|
UI.user_error!("Build number: #{options[:build_number]} does not exist")
|
|
46
46
|
end
|
|
47
47
|
else
|
|
48
48
|
UI.message("Selecting the latest build...")
|
|
49
|
-
build =
|
|
49
|
+
build = wait_for_build_processing_to_be_complete(app: app, platform: platform, options: options)
|
|
50
50
|
end
|
|
51
|
-
UI.message("Selecting build #{app_version} (#{build.
|
|
51
|
+
UI.message("Selecting build #{build.app_version} (#{build.version})...")
|
|
52
52
|
|
|
53
|
-
|
|
54
|
-
v.save!
|
|
53
|
+
version.select_build(build_id: build.id)
|
|
55
54
|
|
|
56
55
|
UI.success("Successfully selected build")
|
|
56
|
+
|
|
57
|
+
return build
|
|
57
58
|
end
|
|
58
59
|
|
|
59
|
-
def
|
|
60
|
-
|
|
60
|
+
def update_export_compliance(options, app, build)
|
|
61
|
+
submission_information = options[:submission_information] || {}
|
|
62
|
+
uses_encryption = submission_information[:export_compliance_uses_encryption]
|
|
63
|
+
|
|
64
|
+
if build.uses_non_exempt_encryption.nil?
|
|
65
|
+
UI.verbose("Updating build for export compliance status of '#{uses_encryption}'")
|
|
66
|
+
|
|
67
|
+
if uses_encryption.to_s.empty?
|
|
68
|
+
message = [
|
|
69
|
+
"Export compliance is required to submit",
|
|
70
|
+
"Add information to the :submission_information option...",
|
|
71
|
+
" Docs: http://docs.fastlane.tools/actions/deliver/#compliance-and-idfa-settings",
|
|
72
|
+
" Example: submission_information: { export_compliance_uses_encryption: false }",
|
|
73
|
+
"This can also be set in your Info.plist with key 'ITSAppUsesNonExemptEncryption'"
|
|
74
|
+
].join("\n")
|
|
75
|
+
UI.user_error!(message)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
build = build.update(attributes: {
|
|
79
|
+
usesNonExemptEncryption: uses_encryption
|
|
80
|
+
})
|
|
61
81
|
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
UI.verbose("Successfully updated build for export compliance status of '#{build.uses_non_exempt_encryption}' on App Store Connect")
|
|
83
|
+
end
|
|
84
|
+
end
|
|
64
85
|
|
|
65
|
-
|
|
86
|
+
def update_idfa(options, app, version)
|
|
87
|
+
submission_information = options[:submission_information] || {}
|
|
88
|
+
uses_idfa = submission_information[:add_id_info_uses_idfa]
|
|
89
|
+
|
|
90
|
+
idfa_declaration = begin
|
|
91
|
+
version.fetch_idfa_declaration
|
|
92
|
+
rescue
|
|
93
|
+
nil
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Set IDFA on version
|
|
97
|
+
UI.verbose("Updating app store version for IDFA status of '#{uses_idfa}'")
|
|
98
|
+
unless uses_idfa.nil?
|
|
99
|
+
version = version.update(attributes: {
|
|
100
|
+
usesIdfa: uses_idfa
|
|
101
|
+
})
|
|
102
|
+
end
|
|
103
|
+
UI.verbose("Updated app store version for IDFA status of '#{version.uses_idfa}'")
|
|
104
|
+
|
|
105
|
+
# Error if uses_idfa not set
|
|
106
|
+
if version.uses_idfa.nil?
|
|
107
|
+
message = [
|
|
108
|
+
"Use of Advertising Identifier (IDFA) is required to submit",
|
|
109
|
+
"Add information to the :submission_information option...",
|
|
110
|
+
" Docs: http://docs.fastlane.tools/actions/deliver/#compliance-and-idfa-settings",
|
|
111
|
+
" Example: submission_information: { add_id_info_uses_idfa: false }",
|
|
112
|
+
" Example: submission_information: {",
|
|
113
|
+
" add_id_info_uses_idfa: true,",
|
|
114
|
+
" add_id_info_limits_tracking: false,",
|
|
115
|
+
" add_id_info_serves_ads: false,",
|
|
116
|
+
" add_id_info_uses_idfa: false,",
|
|
117
|
+
" add_id_info_tracks_install: false",
|
|
118
|
+
" }"
|
|
119
|
+
].join("\n")
|
|
120
|
+
UI.user_error!(message)
|
|
121
|
+
end
|
|
66
122
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
else
|
|
74
|
-
candidate_builds = app.tunes_all_builds_for_train(train: app_version)
|
|
123
|
+
# Create, update, or delete IDFA declaration
|
|
124
|
+
if uses_idfa == false
|
|
125
|
+
if idfa_declaration
|
|
126
|
+
UI.verbose("Deleting IDFA delcaration")
|
|
127
|
+
idfa_declaration.delete!
|
|
128
|
+
UI.verbose("Deleted IDFA delcaration")
|
|
75
129
|
end
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
130
|
+
elsif uses_idfa == true
|
|
131
|
+
attributes = {
|
|
132
|
+
honorsLimitedAdTracking: !!submission_information[:add_id_info_limits_tracking],
|
|
133
|
+
servesAds: !!submission_information[:add_id_info_serves_ads],
|
|
134
|
+
attributesAppInstallationToPreviousAd: !!submission_information[:add_id_info_tracks_install],
|
|
135
|
+
attributesActionWithPreviousAd: !!submission_information[:add_id_info_tracks_action]
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if idfa_declaration
|
|
139
|
+
UI.verbose("Updating IDFA delcaration")
|
|
140
|
+
idfa_declaration.update(attributes: attributes)
|
|
141
|
+
UI.verbose("Updated IDFA delcaration")
|
|
142
|
+
else
|
|
143
|
+
UI.verbose("Creating IDFA delcaration")
|
|
144
|
+
version.create_idfa_declaration(attributes: attributes)
|
|
145
|
+
UI.verbose("Created IDFA delcaration")
|
|
84
146
|
end
|
|
147
|
+
end
|
|
85
148
|
|
|
86
|
-
|
|
149
|
+
UI.success("Successfully updated IDFA delcarations on App Store Connect")
|
|
150
|
+
end
|
|
87
151
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# of the most recently uploaded build
|
|
91
|
-
app_version ||= latest_build.train_version
|
|
152
|
+
def update_submission_information(options, app)
|
|
153
|
+
submission_information = options[:submission_information] || {}
|
|
92
154
|
|
|
93
|
-
|
|
94
|
-
# Only set build if no latest build found or if same build versions as previously fetched build
|
|
95
|
-
# Issue: https://github.com/fastlane/fastlane/issues/10945
|
|
96
|
-
if build.nil? || (latest_build && latest_build.build_version == build.build_version && latest_build.train_version == app_version)
|
|
97
|
-
build = latest_build
|
|
98
|
-
end
|
|
155
|
+
content_rights = submission_information[:content_rights_contains_third_party_content]
|
|
99
156
|
|
|
100
|
-
|
|
157
|
+
unless content_rights.nil?
|
|
158
|
+
value = if content_rights
|
|
159
|
+
Spaceship::ConnectAPI::App::ContentRightsDeclaration::USES_THIRD_PARTY_CONTENT
|
|
160
|
+
else
|
|
161
|
+
Spaceship::ConnectAPI::App::ContentRightsDeclaration::DOES_NOT_USE_THIRD_PARTY_CONTENT
|
|
162
|
+
end
|
|
101
163
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
if (Time.now - start) > (60 * 5)
|
|
109
|
-
UI.message("")
|
|
110
|
-
UI.message("You can tweet: \"App Store Connect #iosprocessingtime #{((Time.now - start) / 60).round} minutes\"")
|
|
111
|
-
end
|
|
112
|
-
sleep(30)
|
|
164
|
+
UI.verbose("Updating contents rights declaration on App Store Connect")
|
|
165
|
+
app.update(attributes: {
|
|
166
|
+
contentRightsDeclaration: value
|
|
167
|
+
})
|
|
168
|
+
UI.success("Successfully updated contents rights declaration on App Store Connect")
|
|
113
169
|
end
|
|
114
|
-
nil
|
|
115
170
|
end
|
|
116
171
|
|
|
117
|
-
def
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
172
|
+
def wait_for_build_processing_to_be_complete(app: nil, platform: nil, options: nil)
|
|
173
|
+
app_version = options[:app_version]
|
|
174
|
+
app_version ||= FastlaneCore::IpaFileAnalyser.fetch_app_version(options[:ipa]) if options[:ipa]
|
|
175
|
+
app_version ||= FastlaneCore::PkgFileAnalyser.fetch_app_version(options[:pkg]) if options[:pkg]
|
|
176
|
+
|
|
177
|
+
app_build ||= FastlaneCore::IpaFileAnalyser.fetch_app_build(options[:ipa]) if options[:ipa]
|
|
178
|
+
app_build ||= FastlaneCore::PkgFileAnalyser.fetch_app_build(options[:pkg]) if options[:pkg]
|
|
179
|
+
|
|
180
|
+
latest_build = FastlaneCore::BuildWatcher.wait_for_build_processing_to_be_complete(
|
|
181
|
+
app_id: app.id,
|
|
182
|
+
platform: platform,
|
|
183
|
+
app_version: app_version,
|
|
184
|
+
build_version: app_build,
|
|
185
|
+
poll_interval: 15,
|
|
186
|
+
return_when_build_appears: false,
|
|
187
|
+
return_spaceship_testflight_build: false
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
unless latest_build.app_version == app_version && latest_build.version == app_build
|
|
191
|
+
UI.important("Uploaded app #{app_version} - #{app_build}, but received build #{latest_build.app_version} - #{latest_build.version}.")
|
|
127
192
|
end
|
|
128
193
|
|
|
129
|
-
return
|
|
194
|
+
return latest_build
|
|
130
195
|
end
|
|
131
196
|
end
|
|
132
197
|
end
|
|
@@ -2,40 +2,38 @@ require_relative 'module'
|
|
|
2
2
|
|
|
3
3
|
module Deliver
|
|
4
4
|
# upload description, rating, etc.
|
|
5
|
+
# rubocop:disable Metrics/ClassLength
|
|
5
6
|
class UploadMetadata
|
|
6
7
|
# All the localised values attached to the version
|
|
7
|
-
LOCALISED_VERSION_VALUES =
|
|
8
|
+
LOCALISED_VERSION_VALUES = {
|
|
9
|
+
description: "description",
|
|
10
|
+
keywords: "keywords",
|
|
11
|
+
release_notes: "whatsNew",
|
|
12
|
+
support_url: "supportUrl",
|
|
13
|
+
marketing_url: "marketingUrl",
|
|
14
|
+
promotional_text: "promotionalText"
|
|
15
|
+
}
|
|
8
16
|
|
|
9
17
|
# Everything attached to the version but not being localised
|
|
10
|
-
NON_LOCALISED_VERSION_VALUES =
|
|
18
|
+
NON_LOCALISED_VERSION_VALUES = {
|
|
19
|
+
copyright: "copyright"
|
|
20
|
+
}
|
|
11
21
|
|
|
12
22
|
# Localised app details values
|
|
13
|
-
LOCALISED_APP_VALUES =
|
|
23
|
+
LOCALISED_APP_VALUES = {
|
|
24
|
+
name: "name",
|
|
25
|
+
subtitle: "subtitle",
|
|
26
|
+
privacy_url: "privacyPolicyUrl",
|
|
27
|
+
apple_tv_privacy_policy: "privacyPolicyText"
|
|
28
|
+
}
|
|
14
29
|
|
|
15
30
|
# Non localized app details values
|
|
16
31
|
NON_LOCALISED_APP_VALUES = [:primary_category, :secondary_category,
|
|
17
32
|
:primary_first_sub_category, :primary_second_sub_category,
|
|
18
33
|
:secondary_first_sub_category, :secondary_second_sub_category]
|
|
19
34
|
|
|
20
|
-
# Trade Representative Contact Information values
|
|
21
|
-
TRADE_REPRESENTATIVE_CONTACT_INFORMATION_VALUES = {
|
|
22
|
-
trade_representative_trade_name: :trade_name,
|
|
23
|
-
trade_representative_first_name: :first_name,
|
|
24
|
-
trade_representative_last_name: :last_name,
|
|
25
|
-
trade_representative_address_line_1: :address_line1,
|
|
26
|
-
trade_representative_address_line_2: :address_line2,
|
|
27
|
-
trade_representative_address_line_3: :address_line3,
|
|
28
|
-
trade_representative_city_name: :city_name,
|
|
29
|
-
trade_representative_state: :state,
|
|
30
|
-
trade_representative_country: :country,
|
|
31
|
-
trade_representative_postal_code: :postal_code,
|
|
32
|
-
trade_representative_phone_number: :phone_number,
|
|
33
|
-
trade_representative_email: :email_address,
|
|
34
|
-
trade_representative_is_displayed_on_app_store: :is_displayed_on_app_store
|
|
35
|
-
}
|
|
36
|
-
|
|
37
35
|
# Review information values
|
|
38
|
-
|
|
36
|
+
REVIEW_INFORMATION_VALUES_LEGACY = {
|
|
39
37
|
review_first_name: :first_name,
|
|
40
38
|
review_last_name: :last_name,
|
|
41
39
|
review_phone_number: :phone_number,
|
|
@@ -44,6 +42,15 @@ module Deliver
|
|
|
44
42
|
review_demo_password: :demo_password,
|
|
45
43
|
review_notes: :notes
|
|
46
44
|
}
|
|
45
|
+
REVIEW_INFORMATION_VALUES = {
|
|
46
|
+
first_name: "contactFirstName",
|
|
47
|
+
last_name: "contactLastName",
|
|
48
|
+
phone_number: "contactPhone",
|
|
49
|
+
email_address: "contactEmail",
|
|
50
|
+
demo_user: "demoAccountName",
|
|
51
|
+
demo_password: "demoAccountPassword",
|
|
52
|
+
notes: "notes"
|
|
53
|
+
}
|
|
47
54
|
|
|
48
55
|
# Localized app details values, that are editable in live state
|
|
49
56
|
LOCALISED_LIVE_VALUES = [:description, :release_notes, :support_url, :marketing_url, :promotional_text, :privacy_url]
|
|
@@ -66,35 +73,46 @@ module Deliver
|
|
|
66
73
|
# Make sure to call `load_from_filesystem` before calling upload
|
|
67
74
|
def upload(options)
|
|
68
75
|
return if options[:skip_metadata]
|
|
69
|
-
# it is not possible to create new languages, because
|
|
70
|
-
# :keywords is not write-able on published versions
|
|
71
|
-
# therefore skip it.
|
|
72
|
-
verify_available_languages!(options) unless options[:edit_live]
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
legacy_app = options[:app]
|
|
78
|
+
app_id = legacy_app.apple_id
|
|
79
|
+
app = Spaceship::ConnectAPI::App.get(app_id: app_id)
|
|
80
|
+
|
|
81
|
+
platform = Spaceship::ConnectAPI::Platform.map(options[:platform])
|
|
82
|
+
|
|
83
|
+
app_store_version_localizations = verify_available_version_languages!(options, app) unless options[:edit_live]
|
|
84
|
+
app_info_localizations = verify_available_info_languages!(options, app) unless options[:edit_live]
|
|
75
85
|
|
|
76
|
-
details = app.details
|
|
77
86
|
if options[:edit_live]
|
|
78
87
|
# not all values are editable when using live_version
|
|
79
|
-
|
|
88
|
+
version = app.get_live_app_store_version(platform: platform)
|
|
80
89
|
localised_options = LOCALISED_LIVE_VALUES
|
|
81
90
|
non_localised_options = NON_LOCALISED_LIVE_VALUES
|
|
82
91
|
|
|
83
92
|
if v.nil?
|
|
84
93
|
UI.message("Couldn't find live version, editing the current version on App Store Connect instead")
|
|
85
|
-
|
|
94
|
+
version = app.get_edit_app_store_version(platform: platform)
|
|
86
95
|
# we don't want to update the localised_options and non_localised_options
|
|
87
96
|
# as we also check for `options[:edit_live]` at other areas in the code
|
|
88
97
|
# by not touching those 2 variables, deliver is more consistent with what the option says
|
|
89
98
|
# in the documentation
|
|
99
|
+
else
|
|
100
|
+
UI.message("Found live version")
|
|
90
101
|
end
|
|
91
102
|
else
|
|
92
|
-
|
|
93
|
-
localised_options = (LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES)
|
|
94
|
-
non_localised_options =
|
|
103
|
+
version = app.get_edit_app_store_version(platform: platform)
|
|
104
|
+
localised_options = (LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys)
|
|
105
|
+
non_localised_options = NON_LOCALISED_VERSION_VALUES.keys
|
|
95
106
|
end
|
|
96
107
|
|
|
97
|
-
|
|
108
|
+
# Needed for to filter out release notes from being sent up
|
|
109
|
+
is_first_version = app.get_live_app_store_version(platform: platform).nil?
|
|
110
|
+
|
|
111
|
+
UI.important("Will begin uploading metadata for '#{version.version_string}' on App Store Connect")
|
|
112
|
+
|
|
113
|
+
localized_version_attributes_by_locale = {}
|
|
114
|
+
localized_info_attributes_by_locale = {}
|
|
115
|
+
|
|
98
116
|
localised_options.each do |key|
|
|
99
117
|
current = options[key]
|
|
100
118
|
next unless current
|
|
@@ -104,70 +122,195 @@ module Deliver
|
|
|
104
122
|
next
|
|
105
123
|
end
|
|
106
124
|
|
|
125
|
+
if key == :release_notes && is_first_version
|
|
126
|
+
UI.error("Skipping 'release_notes'... this is the first version of the app")
|
|
127
|
+
next
|
|
128
|
+
end
|
|
129
|
+
|
|
107
130
|
current.each do |language, value|
|
|
108
131
|
next unless value.to_s.length > 0
|
|
109
132
|
strip_value = value.to_s.strip
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
133
|
+
|
|
134
|
+
if LOCALISED_VERSION_VALUES.include?(key) && !strip_value.empty?
|
|
135
|
+
attribute_name = LOCALISED_VERSION_VALUES[key]
|
|
136
|
+
|
|
137
|
+
localized_version_attributes_by_locale[language] ||= {}
|
|
138
|
+
localized_version_attributes_by_locale[language][attribute_name] = strip_value
|
|
115
139
|
end
|
|
140
|
+
|
|
141
|
+
next unless LOCALISED_APP_VALUES.include?(key) && !strip_value.empty?
|
|
142
|
+
attribute_name = LOCALISED_APP_VALUES[key]
|
|
143
|
+
|
|
144
|
+
localized_info_attributes_by_locale[language] ||= {}
|
|
145
|
+
localized_info_attributes_by_locale[language][attribute_name] = strip_value
|
|
116
146
|
end
|
|
117
147
|
end
|
|
118
148
|
|
|
149
|
+
non_localized_version_attributes = {}
|
|
119
150
|
non_localised_options.each do |key|
|
|
120
|
-
|
|
121
|
-
next unless
|
|
122
|
-
|
|
123
|
-
|
|
151
|
+
strip_value = options[key].to_s.strip
|
|
152
|
+
next unless strip_value.to_s.length > 0
|
|
153
|
+
|
|
154
|
+
if NON_LOCALISED_VERSION_VALUES.include?(key) && !strip_value.empty?
|
|
155
|
+
attribute_name = NON_LOCALISED_VERSION_VALUES[key]
|
|
156
|
+
non_localized_version_attributes[attribute_name] = strip_value
|
|
157
|
+
end
|
|
124
158
|
end
|
|
125
159
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
160
|
+
release_type = if options[:auto_release_date]
|
|
161
|
+
non_localized_version_attributes['earliestReleaseDate'] = options[:auto_release_date]
|
|
162
|
+
Spaceship::ConnectAPI::AppStoreVersion::ReleaseType::SCHEDULED
|
|
163
|
+
elsif options[:automatic_release]
|
|
164
|
+
Spaceship::ConnectAPI::AppStoreVersion::ReleaseType::AFTER_APPROVAL
|
|
165
|
+
else
|
|
166
|
+
Spaceship::ConnectAPI::AppStoreVersion::ReleaseType::MANUAL
|
|
167
|
+
end
|
|
168
|
+
non_localized_version_attributes['releaseType'] = release_type
|
|
169
|
+
|
|
170
|
+
# Update app store version localizations
|
|
171
|
+
app_store_version_localizations.each do |app_store_version_localization|
|
|
172
|
+
attributes = localized_version_attributes_by_locale[app_store_version_localization.locale]
|
|
173
|
+
if attributes
|
|
174
|
+
UI.message("Uploading metadata to App Store Connect for localized version '#{app_store_version_localization.locale}'")
|
|
175
|
+
app_store_version_localization.update(attributes: attributes)
|
|
176
|
+
end
|
|
177
|
+
end
|
|
129
178
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
179
|
+
# Update app info localizations
|
|
180
|
+
app_info_localizations.each do |app_info_localization|
|
|
181
|
+
attributes = localized_info_attributes_by_locale[app_info_localization.locale]
|
|
182
|
+
if attributes
|
|
183
|
+
UI.message("Uploading metadata to App Store Connect for localized info '#{app_info_localization.locale}'")
|
|
184
|
+
app_info_localization.update(attributes: attributes)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
134
187
|
|
|
135
|
-
|
|
188
|
+
# Update app store version
|
|
189
|
+
UI.message("Uploading metadata to App Store Connect for version")
|
|
190
|
+
version.update(attributes: non_localized_version_attributes)
|
|
136
191
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
192
|
+
# Update categories
|
|
193
|
+
app_info = app.fetch_edit_app_info
|
|
194
|
+
if app_info
|
|
195
|
+
category_id_map = {}
|
|
196
|
+
|
|
197
|
+
primary_category = options[:primary_category].to_s.strip
|
|
198
|
+
secondary_category = options[:secondary_category].to_s.strip
|
|
199
|
+
primary_first_sub_category = options[:primary_first_sub_category].to_s.strip
|
|
200
|
+
primary_second_sub_category = options[:primary_second_sub_category].to_s.strip
|
|
201
|
+
secondary_first_sub_category = options[:secondary_first_sub_category].to_s.strip
|
|
202
|
+
secondary_second_sub_category = options[:secondary_second_sub_category].to_s.strip
|
|
203
|
+
|
|
204
|
+
mapped_values = {}
|
|
205
|
+
|
|
206
|
+
# Only update primary and secondar category if explicitly set
|
|
207
|
+
unless primary_category.empty?
|
|
208
|
+
mapped = Spaceship::ConnectAPI::AppCategory.map_category_from_itc(
|
|
209
|
+
primary_category
|
|
210
|
+
)
|
|
211
|
+
|
|
212
|
+
mapped_values[primary_category] = mapped
|
|
213
|
+
category_id_map[:primary_category_id] = mapped
|
|
214
|
+
end
|
|
215
|
+
unless secondary_category.empty?
|
|
216
|
+
mapped = Spaceship::ConnectAPI::AppCategory.map_category_from_itc(
|
|
217
|
+
secondary_category
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
mapped_values[secondary_category] = mapped
|
|
221
|
+
category_id_map[:secondary_category_id] = mapped
|
|
152
222
|
end
|
|
223
|
+
|
|
224
|
+
# Only set if primary category is going to be set
|
|
225
|
+
unless primary_category.empty?
|
|
226
|
+
mapped = Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc(
|
|
227
|
+
primary_first_sub_category
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
mapped_values[primary_first_sub_category] = mapped
|
|
231
|
+
category_id_map[:primary_subcategory_one_id] = mapped
|
|
232
|
+
end
|
|
233
|
+
unless primary_category.empty?
|
|
234
|
+
mapped = Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc(
|
|
235
|
+
primary_second_sub_category
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
mapped_values[primary_second_sub_category] = mapped
|
|
239
|
+
category_id_map[:primary_subcategory_two_id] = mapped
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Only set if secondary category is going to be set
|
|
243
|
+
unless secondary_category.empty?
|
|
244
|
+
mapped = Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc(
|
|
245
|
+
secondary_first_sub_category
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
mapped_values[secondary_first_sub_category] = mapped
|
|
249
|
+
category_id_map[:secondary_subcategory_one_id] = mapped
|
|
250
|
+
end
|
|
251
|
+
unless secondary_category.empty?
|
|
252
|
+
mapped = Spaceship::ConnectAPI::AppCategory.map_subcategory_from_itc(
|
|
253
|
+
secondary_second_sub_category
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
mapped_values[secondary_second_sub_category] = mapped
|
|
257
|
+
category_id_map[:secondary_subcategory_two_id] = mapped
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# Print deprecation warnings if category was mapped
|
|
261
|
+
has_mapped_values = false
|
|
262
|
+
mapped_values.each do |k, v|
|
|
263
|
+
next if k.nil? || v.nil?
|
|
264
|
+
next if k == v
|
|
265
|
+
has_mapped_values = true
|
|
266
|
+
UI.deprecated("Category '#{k}' from iTunesConnect as been deprecated. Please replace with '#{v}'")
|
|
267
|
+
end
|
|
268
|
+
UI.deprecated("You can find more info at https://docs.fastlane.tools/actions/deliver/#reference") if has_mapped_values
|
|
269
|
+
|
|
270
|
+
app_info.update_categories(category_id_map: category_id_map)
|
|
153
271
|
end
|
|
154
|
-
end
|
|
155
272
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
273
|
+
# Update phased release
|
|
274
|
+
unless options[:phased_release].nil?
|
|
275
|
+
phased_release = begin
|
|
276
|
+
version.fetch_app_store_version_phased_release
|
|
277
|
+
rescue
|
|
278
|
+
nil
|
|
279
|
+
end # returns no data error so need to rescue
|
|
280
|
+
if !!options[:phased_release]
|
|
281
|
+
unless phased_release
|
|
282
|
+
UI.message("Creating phased release on App Store Connect")
|
|
283
|
+
version.create_app_store_version_phased_release(attributes: {
|
|
284
|
+
phasedReleaseState: Spaceship::ConnectAPI::AppStoreVersionPhasedRelease::PhasedReleaseState::INACTIVE
|
|
285
|
+
})
|
|
286
|
+
end
|
|
287
|
+
elsif phased_release
|
|
288
|
+
UI.message("Removing phased release on App Store Connect")
|
|
289
|
+
phased_release.delete!
|
|
290
|
+
end
|
|
170
291
|
end
|
|
292
|
+
|
|
293
|
+
# Update rating reset
|
|
294
|
+
unless options[:reset_ratings].nil?
|
|
295
|
+
reset_rating_request = begin
|
|
296
|
+
version.fetch_reset_ratings_request
|
|
297
|
+
rescue
|
|
298
|
+
nil
|
|
299
|
+
end # returns no data error so need to rescue
|
|
300
|
+
if !!options[:reset_ratings]
|
|
301
|
+
unless reset_rating_request
|
|
302
|
+
UI.message("Creating reset ratings request on App Store Connect")
|
|
303
|
+
version.create_reset_ratings_request
|
|
304
|
+
end
|
|
305
|
+
elsif reset_rating_request
|
|
306
|
+
UI.message("Removing reset ratings request on App Store Connect")
|
|
307
|
+
reset_rating_request.delete!
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
set_review_information(version, options)
|
|
312
|
+
set_review_attachment_file(version, options)
|
|
313
|
+
set_app_rating(version, options)
|
|
171
314
|
end
|
|
172
315
|
|
|
173
316
|
# rubocop:enable Metrics/PerceivedComplexity
|
|
@@ -181,7 +324,7 @@ module Deliver
|
|
|
181
324
|
enabled_languages = detect_languages(options)
|
|
182
325
|
|
|
183
326
|
# Get all languages used in existing settings
|
|
184
|
-
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
|
327
|
+
(LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
|
|
185
328
|
current = options[key]
|
|
186
329
|
next unless current && current.kind_of?(Hash)
|
|
187
330
|
current.each do |language, value|
|
|
@@ -200,7 +343,7 @@ module Deliver
|
|
|
200
343
|
return unless enabled_languages.include?("default")
|
|
201
344
|
UI.message("Detected languages: " + enabled_languages.to_s)
|
|
202
345
|
|
|
203
|
-
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
|
346
|
+
(LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
|
|
204
347
|
current = options[key]
|
|
205
348
|
next unless current && current.kind_of?(Hash)
|
|
206
349
|
|
|
@@ -222,7 +365,7 @@ module Deliver
|
|
|
222
365
|
enabled_languages = options[:languages] || []
|
|
223
366
|
|
|
224
367
|
# Get all languages used in existing settings
|
|
225
|
-
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
|
368
|
+
(LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
|
|
226
369
|
current = options[key]
|
|
227
370
|
next unless current && current.kind_of?(Hash)
|
|
228
371
|
current.each do |language, value|
|
|
@@ -245,41 +388,73 @@ module Deliver
|
|
|
245
388
|
.uniq
|
|
246
389
|
end
|
|
247
390
|
|
|
248
|
-
#
|
|
249
|
-
def
|
|
250
|
-
|
|
391
|
+
# Finding languages to enable
|
|
392
|
+
def verify_available_info_languages!(options, app)
|
|
393
|
+
app_info = app.fetch_edit_app_info
|
|
251
394
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
UI.user_error!("Could not find a version to edit for app '#{options[:app].name}', the app metadata is read-only currently") unless v
|
|
395
|
+
unless app_info
|
|
396
|
+
UI.user_error!("Cannot update languages - could not find an editable info")
|
|
397
|
+
return
|
|
398
|
+
end
|
|
257
399
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
400
|
+
localizations = app_info.get_app_info_localizations
|
|
401
|
+
|
|
402
|
+
languages = (options[:languages] || []).reject { |lang| lang == "default" }
|
|
403
|
+
locales_to_enable = languages - localizations.map(&:locale)
|
|
404
|
+
|
|
405
|
+
if locales_to_enable.count > 0
|
|
406
|
+
lng_text = "language"
|
|
407
|
+
lng_text += "s" if locales_to_enable.count != 1
|
|
408
|
+
Helper.show_loading_indicator("Activating info #{lng_text} #{locales_to_enable.join(', ')}...")
|
|
409
|
+
|
|
410
|
+
locales_to_enable.each do |locale|
|
|
411
|
+
app_info.create_app_info_localization(attributes: {
|
|
412
|
+
locale: locale
|
|
413
|
+
})
|
|
265
414
|
end
|
|
415
|
+
|
|
416
|
+
Helper.hide_loading_indicator
|
|
417
|
+
|
|
418
|
+
# Refresh version localizations
|
|
419
|
+
localizations = app_info.get_app_info_localizations
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
return localizations
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
# Finding languages to enable
|
|
426
|
+
def verify_available_version_languages!(options, app)
|
|
427
|
+
platform = Spaceship::ConnectAPI::Platform.map(options[:platform])
|
|
428
|
+
version = app.get_edit_app_store_version(platform: platform)
|
|
429
|
+
|
|
430
|
+
unless version
|
|
431
|
+
UI.user_error!("Cannot update languages - could not find an editable version for '#{platform}'")
|
|
432
|
+
return
|
|
266
433
|
end
|
|
267
434
|
|
|
268
|
-
|
|
269
|
-
# because "default" is not an iTC language
|
|
270
|
-
enabled_languages = enabled_languages.reject do |lang|
|
|
271
|
-
lang == "default"
|
|
272
|
-
end.uniq
|
|
435
|
+
localizations = version.get_app_store_version_localizations
|
|
273
436
|
|
|
274
|
-
|
|
275
|
-
|
|
437
|
+
languages = (options[:languages] || []).reject { |lang| lang == "default" }
|
|
438
|
+
locales_to_enable = languages - localizations.map(&:locale)
|
|
439
|
+
|
|
440
|
+
if locales_to_enable.count > 0
|
|
276
441
|
lng_text = "language"
|
|
277
|
-
lng_text += "s" if
|
|
278
|
-
Helper.show_loading_indicator("Activating #{lng_text} #{
|
|
279
|
-
|
|
442
|
+
lng_text += "s" if locales_to_enable.count != 1
|
|
443
|
+
Helper.show_loading_indicator("Activating version #{lng_text} #{locales_to_enable.join(', ')}...")
|
|
444
|
+
|
|
445
|
+
locales_to_enable.each do |locale|
|
|
446
|
+
version.create_app_store_version_localization(attributes: {
|
|
447
|
+
locale: locale
|
|
448
|
+
})
|
|
449
|
+
end
|
|
450
|
+
|
|
280
451
|
Helper.hide_loading_indicator
|
|
452
|
+
|
|
453
|
+
# Refresh version localizations
|
|
454
|
+
localizations = version.get_app_store_version_localizations
|
|
281
455
|
end
|
|
282
|
-
|
|
456
|
+
|
|
457
|
+
return localizations
|
|
283
458
|
end
|
|
284
459
|
|
|
285
460
|
# Loads the metadata files and stores them into the options object
|
|
@@ -290,7 +465,7 @@ module Deliver
|
|
|
290
465
|
ignore_validation = options[:ignore_language_directory_validation]
|
|
291
466
|
Loader.language_folders(options[:metadata_path], ignore_validation).each do |lang_folder|
|
|
292
467
|
language = File.basename(lang_folder)
|
|
293
|
-
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
|
468
|
+
(LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
|
|
294
469
|
path = File.join(lang_folder, "#{key}.txt")
|
|
295
470
|
next unless File.exist?(path)
|
|
296
471
|
|
|
@@ -301,7 +476,7 @@ module Deliver
|
|
|
301
476
|
end
|
|
302
477
|
|
|
303
478
|
# Load non localised data
|
|
304
|
-
(NON_LOCALISED_VERSION_VALUES + NON_LOCALISED_APP_VALUES).each do |key|
|
|
479
|
+
(NON_LOCALISED_VERSION_VALUES.keys + NON_LOCALISED_APP_VALUES).each do |key|
|
|
305
480
|
path = File.join(options[:metadata_path], "#{key}.txt")
|
|
306
481
|
next unless File.exist?(path)
|
|
307
482
|
|
|
@@ -309,20 +484,9 @@ module Deliver
|
|
|
309
484
|
options[key] ||= File.read(path)
|
|
310
485
|
end
|
|
311
486
|
|
|
312
|
-
# Load trade representative contact information
|
|
313
|
-
options[:trade_representative_contact_information] ||= {}
|
|
314
|
-
TRADE_REPRESENTATIVE_CONTACT_INFORMATION_VALUES.values.each do |option_name|
|
|
315
|
-
path = File.join(options[:metadata_path], TRADE_REPRESENTATIVE_CONTACT_INFORMATION_DIR, "#{option_name}.txt")
|
|
316
|
-
next unless File.exist?(path)
|
|
317
|
-
next if options[:trade_representative_contact_information][option_name].to_s.length > 0
|
|
318
|
-
|
|
319
|
-
UI.message("Loading '#{path}'...")
|
|
320
|
-
options[:trade_representative_contact_information][option_name] ||= File.read(path)
|
|
321
|
-
end
|
|
322
|
-
|
|
323
487
|
# Load review information
|
|
324
488
|
options[:app_review_information] ||= {}
|
|
325
|
-
REVIEW_INFORMATION_VALUES.
|
|
489
|
+
REVIEW_INFORMATION_VALUES.keys.each do |option_name|
|
|
326
490
|
path = File.join(options[:metadata_path], REVIEW_INFORMATION_DIR, "#{option_name}.txt")
|
|
327
491
|
next unless File.exist?(path)
|
|
328
492
|
next if options[:app_review_information][option_name].to_s.length > 0
|
|
@@ -336,7 +500,7 @@ module Deliver
|
|
|
336
500
|
|
|
337
501
|
# Normalizes languages keys from symbols to strings
|
|
338
502
|
def normalize_language_keys(options)
|
|
339
|
-
(LOCALISED_VERSION_VALUES + LOCALISED_APP_VALUES).each do |key|
|
|
503
|
+
(LOCALISED_VERSION_VALUES.keys + LOCALISED_APP_VALUES.keys).each do |key|
|
|
340
504
|
current = options[key]
|
|
341
505
|
next unless current && current.kind_of?(Hash)
|
|
342
506
|
|
|
@@ -348,33 +512,55 @@ module Deliver
|
|
|
348
512
|
options
|
|
349
513
|
end
|
|
350
514
|
|
|
351
|
-
def
|
|
352
|
-
return unless options[:trade_representative_contact_information]
|
|
353
|
-
info = options[:trade_representative_contact_information]
|
|
354
|
-
UI.user_error!("`trade_representative_contact_information` must be a hash", show_github_issues: true) unless info.kind_of?(Hash)
|
|
355
|
-
|
|
356
|
-
TRADE_REPRESENTATIVE_CONTACT_INFORMATION_VALUES.each do |key, option_name|
|
|
357
|
-
v.send("#{key}=", info[option_name].to_s.chomp) if info[option_name]
|
|
358
|
-
end
|
|
359
|
-
end
|
|
360
|
-
|
|
361
|
-
def set_review_information(v, options)
|
|
515
|
+
def set_review_information(version, options)
|
|
362
516
|
return unless options[:app_review_information]
|
|
363
517
|
info = options[:app_review_information]
|
|
364
518
|
UI.user_error!("`app_review_information` must be a hash", show_github_issues: true) unless info.kind_of?(Hash)
|
|
365
519
|
|
|
366
|
-
|
|
367
|
-
|
|
520
|
+
attributes = {}
|
|
521
|
+
REVIEW_INFORMATION_VALUES.each do |key, attribute_name|
|
|
522
|
+
strip_value = info[key].to_s.strip
|
|
523
|
+
attributes[attribute_name] = strip_value unless strip_value.empty?
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
if !attributes["demoAccountName"].to_s.empty? && !attributes["demoAccountPassword"].to_s.empty?
|
|
527
|
+
attributes["demoAccountRequired"] = true
|
|
528
|
+
else
|
|
529
|
+
attributes["demoAccountRequired"] = false
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
UI.message("Uploading app review information to App Store Connect")
|
|
533
|
+
app_store_review_detail = begin
|
|
534
|
+
version.fetch_app_store_review_detail
|
|
535
|
+
rescue
|
|
536
|
+
nil
|
|
537
|
+
end # errors if doesn't exist
|
|
538
|
+
if app_store_review_detail
|
|
539
|
+
app_store_review_detail.update(attributes: attributes)
|
|
540
|
+
else
|
|
541
|
+
version.create_app_store_review_detail(attributes: attributes)
|
|
368
542
|
end
|
|
369
|
-
v.review_user_needed = (v.review_demo_user.to_s.chomp + v.review_demo_password.to_s.chomp).length > 0
|
|
370
543
|
end
|
|
371
544
|
|
|
372
|
-
def set_review_attachment_file(
|
|
373
|
-
|
|
374
|
-
|
|
545
|
+
def set_review_attachment_file(version, options)
|
|
546
|
+
app_store_review_detail = version.fetch_app_store_review_detail
|
|
547
|
+
app_review_attachments = app_store_review_detail.fetch_app_review_attachments
|
|
548
|
+
|
|
549
|
+
if options[:app_review_attachment_file]
|
|
550
|
+
app_review_attachments.each do |app_review_attachment|
|
|
551
|
+
UI.message("Removing previous review attachment file from App Store Connect")
|
|
552
|
+
app_review_attachment.delete!
|
|
553
|
+
end
|
|
554
|
+
|
|
555
|
+
UI.message("Uploading review attachment file to App Store Connect")
|
|
556
|
+
app_store_review_detail.upload_attachment(path: options[:app_review_attachment_file])
|
|
557
|
+
else
|
|
558
|
+
app_review_attachments.each(&:delete!)
|
|
559
|
+
UI.message("Removing review attachment file to App Store Connect") unless app_review_attachments.empty?
|
|
560
|
+
end
|
|
375
561
|
end
|
|
376
562
|
|
|
377
|
-
def set_app_rating(
|
|
563
|
+
def set_app_rating(version, options)
|
|
378
564
|
return unless options[:app_rating_config_path]
|
|
379
565
|
|
|
380
566
|
require 'json'
|
|
@@ -385,7 +571,33 @@ module Deliver
|
|
|
385
571
|
UI.user_error!("Error parsing JSON file at path '#{options[:app_rating_config_path]}'")
|
|
386
572
|
end
|
|
387
573
|
UI.message("Setting the app's age rating...")
|
|
388
|
-
|
|
574
|
+
|
|
575
|
+
# Maping from legacy ITC values to App Store Connect Values
|
|
576
|
+
mapped_values = {}
|
|
577
|
+
attributes = {}
|
|
578
|
+
json.each do |k, v|
|
|
579
|
+
new_key = Spaceship::ConnectAPI::AgeRatingDeclaration.map_key_from_itc(k)
|
|
580
|
+
new_value = Spaceship::ConnectAPI::AgeRatingDeclaration.map_value_from_itc(new_key, v)
|
|
581
|
+
|
|
582
|
+
mapped_values[k] = new_key
|
|
583
|
+
mapped_values[v] = new_value
|
|
584
|
+
|
|
585
|
+
attributes[new_key] = new_value
|
|
586
|
+
end
|
|
587
|
+
|
|
588
|
+
# Print deprecation warnings if category was mapped
|
|
589
|
+
has_mapped_values = false
|
|
590
|
+
mapped_values.each do |k, v|
|
|
591
|
+
next if k.nil? || v.nil?
|
|
592
|
+
next if k == v
|
|
593
|
+
has_mapped_values = true
|
|
594
|
+
UI.deprecated("Age rating '#{k}' from iTunesConnect as been deprecated. Please replace with '#{v}'")
|
|
595
|
+
end
|
|
596
|
+
UI.deprecated("You can find more info at https://docs.fastlane.tools/actions/deliver/#reference") if has_mapped_values
|
|
597
|
+
|
|
598
|
+
age_rating_delcaration = version.fetch_age_rating_declaration
|
|
599
|
+
age_rating_delcaration.update(attributes: attributes)
|
|
389
600
|
end
|
|
390
601
|
end
|
|
602
|
+
# rubocop:enable Metrics/ClassLength
|
|
391
603
|
end
|