deliver 0.13.5 → 1.0.0.beta1
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 +9 -208
- data/bin/deliver +1 -1
- data/lib/assets/DeliverfileDefault +2 -22
- data/lib/assets/summary.html.erb +27 -39
- data/lib/deliver.rb +16 -14
- data/lib/deliver/app_screenshot.rb +43 -33
- data/lib/deliver/commands_generator.rb +30 -108
- data/lib/deliver/detect_values.rb +23 -0
- data/lib/deliver/download_screenshots.rb +30 -9
- data/lib/deliver/html_generator.rb +7 -8
- data/lib/deliver/options.rb +126 -0
- data/lib/deliver/runner.rb +75 -0
- data/lib/deliver/setup.rb +84 -0
- data/lib/deliver/submit_for_review.rb +60 -0
- data/lib/deliver/upload_assets.rb +22 -0
- data/lib/deliver/upload_metadata.rb +100 -0
- data/lib/deliver/upload_price_tier.rb +21 -0
- data/lib/deliver/upload_screenshots.rb +63 -0
- data/lib/deliver/version.rb +2 -1
- metadata +37 -62
- data/lib/assets/DeliverLanguageMapping.json +0 -187
- data/lib/assets/DeliverfileExample +0 -38
- data/lib/deliver/app.rb +0 -167
- data/lib/deliver/app_metadata.rb +0 -419
- data/lib/deliver/app_metadata_screenshots.rb +0 -189
- data/lib/deliver/deliver_process.rb +0 -426
- data/lib/deliver/deliverer.rb +0 -138
- data/lib/deliver/deliverfile/deliverfile.rb +0 -35
- data/lib/deliver/deliverfile/deliverfile_creator.rb +0 -135
- data/lib/deliver/deliverfile/dsl.rb +0 -142
- data/lib/deliver/dependency_checker.rb +0 -19
- data/lib/deliver/ipa_file_analyser.rb +0 -44
- data/lib/deliver/ipa_uploader.rb +0 -148
- data/lib/deliver/itunes_connect/itunes_connect.rb +0 -12
- data/lib/deliver/itunes_connect/itunes_connect_additional.rb +0 -105
- data/lib/deliver/itunes_connect/itunes_connect_app_icon.rb +0 -41
- data/lib/deliver/itunes_connect/itunes_connect_app_rating.rb +0 -90
- data/lib/deliver/itunes_connect/itunes_connect_apple_watch_app_icon.rb +0 -42
- data/lib/deliver/itunes_connect/itunes_connect_information.rb +0 -34
- data/lib/deliver/itunes_connect/itunes_connect_new_version.rb +0 -67
- data/lib/deliver/itunes_connect/itunes_connect_reader.rb +0 -46
- data/lib/deliver/itunes_connect/itunes_connect_screenshot_fetcher.rb +0 -54
- data/lib/deliver/itunes_connect/itunes_connect_submission.rb +0 -282
- data/lib/deliver/itunes_transporter.rb +0 -221
- data/lib/deliver/metadata_item.rb +0 -94
- data/lib/deliver/testflight.rb +0 -27
@@ -1,189 +0,0 @@
|
|
1
|
-
module Deliver
|
2
|
-
class AppMetadata
|
3
|
-
#####################################################
|
4
|
-
# @!group Screenshot related
|
5
|
-
#####################################################
|
6
|
-
|
7
|
-
# Removes all currently enabled screenshots for the given language.
|
8
|
-
# @param (String) language The language, which has to be in this list: {FastlaneCore::Languages}.
|
9
|
-
def clear_all_screenshots(language)
|
10
|
-
raise AppMetadataParameterError.new(INVALID_LANGUAGE_ERROR) unless FastlaneCore::Languages::ALL_LANGUAGES.include?language
|
11
|
-
|
12
|
-
update_localized_value('software_screenshots', {language => {}}) do |field, useless, language|
|
13
|
-
field.children.remove # remove all the screenshots
|
14
|
-
end
|
15
|
-
information[language][:screenshots] = []
|
16
|
-
true
|
17
|
-
end
|
18
|
-
|
19
|
-
# Appends another screenshot to the already existing ones
|
20
|
-
# @param (String) language The language, which has to be in this list: {FastlaneCore::Languages}.
|
21
|
-
# @param (Deliver::AppScreenshot) app_screenshot The screenshot you want to add to the app metadata.
|
22
|
-
# @raise (AppMetadataTooManyScreenshotsError) When there are already 5 screenshots (MAXIMUM_NUMBER_OF_SCREENSHOTS).
|
23
|
-
|
24
|
-
def add_screenshot(language, app_screenshot)
|
25
|
-
raise AppMetadataParameterError.new(INVALID_LANGUAGE_ERROR) unless FastlaneCore::Languages::ALL_LANGUAGES.include?language
|
26
|
-
|
27
|
-
create_locale_if_not_exists(language)
|
28
|
-
|
29
|
-
# Fetch the 'software_screenshots' node (array) for the specific locale
|
30
|
-
locales = self.fetch_value("//x:locale[@name='#{language}']")
|
31
|
-
|
32
|
-
screenshots = self.fetch_value("//x:locale[@name='#{language}']/x:software_screenshots").first
|
33
|
-
|
34
|
-
if not screenshots or screenshots.children.count == 0
|
35
|
-
screenshots.remove if screenshots
|
36
|
-
|
37
|
-
# First screenshot ever
|
38
|
-
screenshots = Nokogiri::XML::Node.new('software_screenshots', @data)
|
39
|
-
locales.first << screenshots
|
40
|
-
|
41
|
-
node_set = Nokogiri::XML::NodeSet.new(@data)
|
42
|
-
node_set << app_screenshot.create_xml_node(@data, 1)
|
43
|
-
screenshots.children = node_set
|
44
|
-
else
|
45
|
-
# There is already at least one screenshot
|
46
|
-
next_index = 1
|
47
|
-
screenshots.children.each do |screen|
|
48
|
-
if screen['display_target'] == app_screenshot.screen_size
|
49
|
-
next_index += 1
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
if next_index > MAXIMUM_NUMBER_OF_SCREENSHOTS
|
54
|
-
raise AppMetadataTooManyScreenshotsError.new("Only #{MAXIMUM_NUMBER_OF_SCREENSHOTS} screenshots are allowed per language per device type (#{app_screenshot.screen_size})")
|
55
|
-
end
|
56
|
-
|
57
|
-
# Ready for storing the screenshot into the metadata.xml now
|
58
|
-
screenshots.children.after(app_screenshot.create_xml_node(@data, next_index))
|
59
|
-
end
|
60
|
-
|
61
|
-
information[language][:screenshots] << app_screenshot
|
62
|
-
|
63
|
-
app_screenshot.store_file_inside_package(@package_path)
|
64
|
-
end
|
65
|
-
|
66
|
-
# This method will clear all screenshots and set the new ones you pass
|
67
|
-
# @param new_screenshots
|
68
|
-
# +code+
|
69
|
-
# {
|
70
|
-
# 'de-DE' => [
|
71
|
-
# AppScreenshot.new('path/screenshot1.png', Deliver::ScreenSize::IOS_35),
|
72
|
-
# AppScreenshot.new('path/screenshot2.png', Deliver::ScreenSize::IOS_40),
|
73
|
-
# AppScreenshot.new('path/screenshot3.png', Deliver::ScreenSize::IOS_IPAD)
|
74
|
-
# ]
|
75
|
-
# }
|
76
|
-
# This method uses {#clear_all_screenshots} and {#add_screenshot} under the hood.
|
77
|
-
# @return [bool] true if everything was successful
|
78
|
-
# @raise [AppMetadataParameterError] error is raised when parameters are invalid
|
79
|
-
def set_all_screenshots(new_screenshots)
|
80
|
-
error_text = "Please pass a hash, containing an array of AppScreenshot objects"
|
81
|
-
raise AppMetadataParameterError.new(error_text) unless new_screenshots.kind_of?Hash
|
82
|
-
|
83
|
-
new_screenshots.each do |key, value|
|
84
|
-
if key.kind_of?String and value.kind_of?Array and value.count > 0 and value.first.kind_of?AppScreenshot
|
85
|
-
|
86
|
-
self.clear_all_screenshots(key)
|
87
|
-
|
88
|
-
value.each do |screen|
|
89
|
-
add_screenshot(key, screen)
|
90
|
-
end
|
91
|
-
else
|
92
|
-
raise AppMetadataParameterError.new(error_text)
|
93
|
-
end
|
94
|
-
end
|
95
|
-
true
|
96
|
-
end
|
97
|
-
|
98
|
-
# Automatically add all screenshots contained in the given directory to the app.
|
99
|
-
#
|
100
|
-
# This method will automatically detect which device type each screenshot is.
|
101
|
-
#
|
102
|
-
# This will also clear all existing screenshots before setting the new ones.
|
103
|
-
# @param (Hash) hash A hash containing a different path for each locale ({FastlaneCore::Languages::ALL_LANGUAGES})
|
104
|
-
# @param (Bool) Use the framed screenshots? Only use it if you use frameit 2.0
|
105
|
-
|
106
|
-
def set_screenshots_for_each_language(hash, use_framed = false)
|
107
|
-
raise AppMetadataParameterError.new("Parameter needs to be an hash, containg strings with the new description") unless hash.kind_of?Hash
|
108
|
-
hash.each do |language, current_path|
|
109
|
-
resulting_path = "#{current_path}/**/*.{png,jpg,jpeg}"
|
110
|
-
|
111
|
-
raise AppMetadataParameterError.new(INVALID_LANGUAGE_ERROR) unless FastlaneCore::Languages::ALL_LANGUAGES.include?language
|
112
|
-
|
113
|
-
# https://stackoverflow.com/questions/21688855/
|
114
|
-
# File::FNM_CASEFOLD = ignore case
|
115
|
-
if Dir.glob(resulting_path, File::FNM_CASEFOLD).count == 0
|
116
|
-
Helper.log.error("No screenshots found at the given path '#{resulting_path}'")
|
117
|
-
else
|
118
|
-
self.clear_all_screenshots(language)
|
119
|
-
|
120
|
-
Dir.glob(resulting_path, File::FNM_CASEFOLD).sort.each do |path|
|
121
|
-
# When frameit is enabled, we only want to upload the framed screenshots
|
122
|
-
if use_framed
|
123
|
-
# Except for Watch screenshots, they are okay without _framed
|
124
|
-
is_apple_watch = ((AppScreenshot.new(path).screen_size == AppScreenshot::ScreenSize::IOS_APPLE_WATCH) rescue false)
|
125
|
-
unless is_apple_watch
|
126
|
-
next unless path.include?"_framed."
|
127
|
-
end
|
128
|
-
else
|
129
|
-
next if path.include?"_framed."
|
130
|
-
end
|
131
|
-
|
132
|
-
begin
|
133
|
-
add_screenshot(language, Deliver::AppScreenshot.new(path))
|
134
|
-
rescue AppMetadataTooManyScreenshotsError => ex
|
135
|
-
# We just use the first 5 ones
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
true
|
142
|
-
end
|
143
|
-
|
144
|
-
# This method will run through all the available locales, check if there is
|
145
|
-
# a folder for this language (e.g. 'en-US') and use all screenshots in there
|
146
|
-
# @param (String) path A path to the folder, which contains a folder for each locale
|
147
|
-
# @param (Bool) Use the framed screenshots? Only use it if you use frameit 2.0
|
148
|
-
def set_all_screenshots_from_path(path, use_framed = false)
|
149
|
-
raise AppMetadataParameterError.new("Parameter needs to be a path (string)") unless path.kind_of?String
|
150
|
-
|
151
|
-
found = false
|
152
|
-
FastlaneCore::Languages::ALL_LANGUAGES.each do |language|
|
153
|
-
full_path = File.join(path, language)
|
154
|
-
if File.directory?(full_path)
|
155
|
-
found = true
|
156
|
-
set_screenshots_for_each_language({
|
157
|
-
language => full_path
|
158
|
-
}, use_framed)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# Legacy:
|
163
|
-
# We also want to support the "legacy" language format (ja-JP instead of just ja)
|
164
|
-
FastlaneCore::Languages::ALL_LANGUAGES_LEGACY.each do |language|
|
165
|
-
full_path = File.join(path, language)
|
166
|
-
if File.directory?(full_path)
|
167
|
-
|
168
|
-
if FastlaneCore::Languages::ALL_LANGUAGES.include?language
|
169
|
-
# We're all good, this language code is still supported
|
170
|
-
else
|
171
|
-
# This language code was changed - need to modify that
|
172
|
-
short_code = language.match(/(\w\w)\-.*/)
|
173
|
-
if short_code and short_code.length == 2
|
174
|
-
Helper.log.info "Using language code #{short_code[1]} instead of #{language}"
|
175
|
-
language = short_code[1]
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
found = true
|
180
|
-
set_screenshots_for_each_language({
|
181
|
-
language => full_path
|
182
|
-
}, use_framed)
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
return found
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
@@ -1,426 +0,0 @@
|
|
1
|
-
module Deliver
|
2
|
-
# This class takes care of verifying all inputs and triggering the upload process
|
3
|
-
class DeliverProcess
|
4
|
-
|
5
|
-
# DeliverUnitTestsError is triggered, when the unit tests of the given block failed.
|
6
|
-
class DeliverUnitTestsError < StandardError
|
7
|
-
end
|
8
|
-
|
9
|
-
# @return (Deliver::App) The App that is currently being edited.
|
10
|
-
attr_accessor :app
|
11
|
-
|
12
|
-
# @return (Deliver::IpaUploader) The IPA uploader that is currently being used.
|
13
|
-
attr_accessor :ipa
|
14
|
-
|
15
|
-
# @return (Hash) All the updated/new information we got from the Deliverfile.
|
16
|
-
# is used to store the deploy information until the Deliverfile finished running.
|
17
|
-
attr_accessor :deploy_information
|
18
|
-
|
19
|
-
# @return (String): The app identifier of the currently used app (e.g. com.krausefx.app)
|
20
|
-
attr_accessor :app_identifier
|
21
|
-
|
22
|
-
def initialize(deploy_information = nil)
|
23
|
-
@deploy_information = deploy_information || {}
|
24
|
-
@deploy_information[:blocks] ||= {}
|
25
|
-
end
|
26
|
-
|
27
|
-
def run
|
28
|
-
begin
|
29
|
-
fetch_information_from_ipa_file
|
30
|
-
pre_load_default_values
|
31
|
-
|
32
|
-
unless metadata_only?
|
33
|
-
run_unit_tests
|
34
|
-
end
|
35
|
-
|
36
|
-
Helper.log.info("Got all information needed to deploy a new update ('#{app_version}') for app '#{app_identifier}'")
|
37
|
-
|
38
|
-
verify_app_on_itunesconnect unless metadata_only?
|
39
|
-
|
40
|
-
|
41
|
-
if is_beta_build?
|
42
|
-
Helper.log.info "Beta builds don't upload new metadata to iTunesConnect".yellow
|
43
|
-
else
|
44
|
-
upload_metadata
|
45
|
-
end
|
46
|
-
|
47
|
-
# Always upload a new ipa (except if none was given)
|
48
|
-
trigger_ipa_upload unless metadata_only?
|
49
|
-
|
50
|
-
call_success_block
|
51
|
-
rescue => ex
|
52
|
-
call_error_block(ex)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def upload_metadata
|
57
|
-
if ready_for_sale?
|
58
|
-
raise "Cannot update metadata of apps 'Ready for Sale'. You can dupe: http://www.openradar.appspot.com/18263306".red
|
59
|
-
end
|
60
|
-
|
61
|
-
load_metadata_from_config_json_folder # the json file generated from the quick start # deprecated
|
62
|
-
load_metadata_folder # this is the new way of defining app metadata
|
63
|
-
set_app_metadata
|
64
|
-
set_screenshots
|
65
|
-
|
66
|
-
verify_pdf_file
|
67
|
-
|
68
|
-
additional_itc_information # e.g. copyright, age rating
|
69
|
-
|
70
|
-
trigger_metadata_upload
|
71
|
-
end
|
72
|
-
|
73
|
-
#####################################################
|
74
|
-
# @!group Getters
|
75
|
-
#####################################################
|
76
|
-
|
77
|
-
def app
|
78
|
-
return @app if @app
|
79
|
-
|
80
|
-
@app = Deliver::App.new(app_identifier: app_identifier,
|
81
|
-
apple_id: @deploy_information[Deliverer::ValKey::APPLE_ID]) # apple_id can be nil, will be fetched automatically
|
82
|
-
end
|
83
|
-
|
84
|
-
def app_version
|
85
|
-
return @app_version if @app_version
|
86
|
-
|
87
|
-
if Helper.is_test?
|
88
|
-
raise "No App Version given"
|
89
|
-
end
|
90
|
-
|
91
|
-
@app_version ||= ask("Which version number should be updated? ")
|
92
|
-
end
|
93
|
-
|
94
|
-
def app_identifier
|
95
|
-
return @app_identifier if @app_identifier
|
96
|
-
|
97
|
-
if Helper.is_test?
|
98
|
-
raise "No App Identifier given"
|
99
|
-
end
|
100
|
-
|
101
|
-
Helper.log.info "No App Identifier found. Pass one using `app_identifier` in your Deliverfile".yellow
|
102
|
-
@app_identifier = ask("App Identifier (e.g. com.krausefx.app): ")
|
103
|
-
end
|
104
|
-
|
105
|
-
# Preloads default values from the given hashes + Appfile
|
106
|
-
def pre_load_default_values
|
107
|
-
@app_identifier ||= @deploy_information[Deliverer::ValKey::APP_IDENTIFIER]
|
108
|
-
@app_identifier ||= (CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier) rescue nil)
|
109
|
-
@app_identifier ||= (@ipa.fetch_app_identifier rescue nil) # since ipa might be nil
|
110
|
-
|
111
|
-
@app_version ||= @deploy_information[Deliverer::ValKey::APP_VERSION]
|
112
|
-
@app_version ||= ENV["DELIVER_VERSION"] if ENV["DELIVER_VERSION"].to_s.length > 0
|
113
|
-
@app_version ||= (@ipa.fetch_app_version rescue nil) # since ipa might be nil
|
114
|
-
@app_version ||= (app.get_live_version rescue nil) # pull the latest version from iTunes Connect
|
115
|
-
end
|
116
|
-
|
117
|
-
#####################################################
|
118
|
-
# @!group What kind of release
|
119
|
-
#####################################################
|
120
|
-
|
121
|
-
# Deployment = Submission of the binary
|
122
|
-
def skip_deployment?
|
123
|
-
@deploy_information[Deliverer::ValKey::SKIP_DEPLOY]
|
124
|
-
end
|
125
|
-
|
126
|
-
# Release = App Store and not TestFlight
|
127
|
-
def is_release_build?
|
128
|
-
is_beta_build? == false
|
129
|
-
end
|
130
|
-
|
131
|
-
# TestFlight Buil
|
132
|
-
def is_beta_build?
|
133
|
-
@deploy_information[Deliverer::ValKey::IS_BETA_IPA]
|
134
|
-
end
|
135
|
-
|
136
|
-
# Only upload metadata and no binary
|
137
|
-
def metadata_only?
|
138
|
-
ENV["DELIVER_SKIP_BINARY"]
|
139
|
-
end
|
140
|
-
|
141
|
-
# Is the app already ready for sale?
|
142
|
-
# if so, we can't update the app metadata: http://www.openradar.appspot.com/18263306
|
143
|
-
def ready_for_sale?
|
144
|
-
return false if Helper.is_test?
|
145
|
-
return @ready if @checked_for_ready
|
146
|
-
|
147
|
-
@checked_for_ready = true
|
148
|
-
@ready = (app.get_app_status == App::AppStatus::READY_FOR_SALE)
|
149
|
-
end
|
150
|
-
|
151
|
-
#####################################################
|
152
|
-
# @!group All the methods
|
153
|
-
#####################################################
|
154
|
-
|
155
|
-
def run_unit_tests
|
156
|
-
if @deploy_information[:blocks][:unit_tests]
|
157
|
-
result = @deploy_information[:blocks][:unit_tests].call
|
158
|
-
if result
|
159
|
-
Helper.log.debug("Unit tests successful".green)
|
160
|
-
else
|
161
|
-
raise DeliverUnitTestsError.new("Unit tests failed. Got result: '#{result}'. Need 'true' or 1 to succeed.".red)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
def fetch_information_from_ipa_file
|
167
|
-
used_ipa_file = ENV["IPA_OUTPUT_PATH"]# if (ENV["IPA_OUTPUT_PATH"] and File.exists?(ENV["IPA_OUTPUT_PATH"]))
|
168
|
-
|
169
|
-
if is_release_build?
|
170
|
-
used_ipa_file = @deploy_information[:ipa] if @deploy_information[:ipa]
|
171
|
-
elsif is_beta_build?
|
172
|
-
used_ipa_file = @deploy_information[:beta_ipa] if @deploy_information[:beta_ipa]
|
173
|
-
end
|
174
|
-
|
175
|
-
if used_ipa_file.kind_of?Proc
|
176
|
-
# The user provided a block. We only want to execute the block now, since it might be a long build step
|
177
|
-
used_ipa_file = used_ipa_file.call
|
178
|
-
|
179
|
-
Deliverfile::Deliverfile::DSL.validate_ipa!(used_ipa_file)
|
180
|
-
end
|
181
|
-
|
182
|
-
if (used_ipa_file || '').length == 0 and is_beta_build?
|
183
|
-
# Beta Release but no ipa given
|
184
|
-
used_ipa_file = Dir["*.ipa"].first
|
185
|
-
|
186
|
-
unless used_ipa_file
|
187
|
-
raise "Could not find an ipa file for 'beta' mode. Provide one using `beta_ipa do ... end` in your Deliverfile.".red
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
191
|
-
ENV["DELIVER_IPA_PATH"] = used_ipa_file
|
192
|
-
|
193
|
-
if used_ipa_file
|
194
|
-
upload_strategy = Deliver::IPA_UPLOAD_STRATEGY_APP_STORE
|
195
|
-
if is_beta_build?
|
196
|
-
upload_strategy = Deliver::IPA_UPLOAD_STRATEGY_BETA_BUILD
|
197
|
-
end
|
198
|
-
if skip_deployment?
|
199
|
-
upload_strategy = Deliver::IPA_UPLOAD_STRATEGY_JUST_UPLOAD
|
200
|
-
Helper.log.info "Skipping submission of app update"
|
201
|
-
end
|
202
|
-
|
203
|
-
@ipa = Deliver::IpaUploader.new(Deliver::App.new, '/tmp/', used_ipa_file, upload_strategy)
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def verify_app_on_itunesconnect
|
208
|
-
if (@ipa and is_release_build?) or !@ipa
|
209
|
-
# This is a real release, which should also upload the ipa file onto production
|
210
|
-
app.create_new_version!(app_version) unless Helper.is_test?
|
211
|
-
app.metadata.verify_version(app_version) if @ipa
|
212
|
-
end
|
213
|
-
end
|
214
|
-
|
215
|
-
def options_mapping
|
216
|
-
{
|
217
|
-
'title' => Deliverer::ValKey::TITLE,
|
218
|
-
'description' => Deliverer::ValKey::DESCRIPTION,
|
219
|
-
'version_whats_new' => Deliverer::ValKey::CHANGELOG,
|
220
|
-
'keywords' => Deliverer::ValKey::KEYWORDS,
|
221
|
-
'privacy_url' => Deliverer::ValKey::PRIVACY_URL,
|
222
|
-
'software_url' => Deliverer::ValKey::MARKETING_URL,
|
223
|
-
'support_url' => Deliverer::ValKey::SUPPORT_URL
|
224
|
-
}
|
225
|
-
end
|
226
|
-
|
227
|
-
def load_metadata_from_config_json_folder
|
228
|
-
return unless @deploy_information[Deliverer::ValKey::CONFIG_JSON_FOLDER]
|
229
|
-
|
230
|
-
file_path = @deploy_information[:config_json_folder]
|
231
|
-
unless file_path.split("/").last.include?"metadata.json"
|
232
|
-
file_path += "/metadata.json"
|
233
|
-
end
|
234
|
-
|
235
|
-
raise "Could not find metadatafile at path '#{file_path}'".red unless File.exists?file_path
|
236
|
-
|
237
|
-
content = JSON.parse(File.read(file_path))
|
238
|
-
content.each do |language, current|
|
239
|
-
|
240
|
-
options_mapping.each do |key, value|
|
241
|
-
if current[key]
|
242
|
-
@deploy_information[value] ||= {}
|
243
|
-
@deploy_information[value][language] ||= current[key]
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def load_metadata_folder
|
250
|
-
# Fetch the information from the ./metadata folder if it exists
|
251
|
-
metadata_folder = './metadata'
|
252
|
-
return unless File.exists?metadata_folder
|
253
|
-
|
254
|
-
Dir[File.join(metadata_folder, '*')].each do |language_folder|
|
255
|
-
language = File.basename(language_folder)
|
256
|
-
|
257
|
-
options_mapping.each do |key, value|
|
258
|
-
content = File.read(File.join(language_folder, "#{key}.txt")) rescue nil
|
259
|
-
next unless content
|
260
|
-
content = content.split("\n") if key == 'keywords'
|
261
|
-
content = content.strip if ['privacy_url', 'software_url', 'support_url'].include?key
|
262
|
-
@deploy_information[value] ||= {}
|
263
|
-
@deploy_information[value][language] ||= content
|
264
|
-
|
265
|
-
Helper.log.info "Successfully loaded content from '#{key}.txt' for language #{language_folder}"
|
266
|
-
end
|
267
|
-
end
|
268
|
-
end
|
269
|
-
|
270
|
-
def set_app_metadata
|
271
|
-
app.metadata.update_title(@deploy_information[Deliverer::ValKey::TITLE]) if @deploy_information[Deliverer::ValKey::TITLE]
|
272
|
-
app.metadata.update_description(@deploy_information[Deliverer::ValKey::DESCRIPTION]) if @deploy_information[Deliverer::ValKey::DESCRIPTION]
|
273
|
-
|
274
|
-
app.metadata.update_support_url(@deploy_information[Deliverer::ValKey::SUPPORT_URL]) if @deploy_information[Deliverer::ValKey::SUPPORT_URL]
|
275
|
-
app.metadata.update_changelog(@deploy_information[Deliverer::ValKey::CHANGELOG]) if @deploy_information[Deliverer::ValKey::CHANGELOG]
|
276
|
-
app.metadata.update_marketing_url(@deploy_information[Deliverer::ValKey::MARKETING_URL]) if @deploy_information[Deliverer::ValKey::MARKETING_URL]
|
277
|
-
app.metadata.update_privacy_url(@deploy_information[Deliverer::ValKey::PRIVACY_URL]) if @deploy_information[Deliverer::ValKey::PRIVACY_URL]
|
278
|
-
|
279
|
-
app.metadata.update_keywords(@deploy_information[Deliverer::ValKey::KEYWORDS]) if @deploy_information[Deliverer::ValKey::KEYWORDS]
|
280
|
-
|
281
|
-
app.metadata.update_price_tier(@deploy_information[Deliverer::ValKey::PRICE_TIER]) if @deploy_information[Deliverer::ValKey::PRICE_TIER]
|
282
|
-
end
|
283
|
-
|
284
|
-
def screenshots_path
|
285
|
-
return @screens_path if @screens_path
|
286
|
-
|
287
|
-
@screens_path = @deploy_information[Deliverer::ValKey::SCREENSHOTS_PATH]
|
288
|
-
if (ENV["DELIVER_SCREENSHOTS_PATH"] || '').length > 0
|
289
|
-
Helper.log.warn "Overwriting screenshots path from config (#{@screens_path}) with (#{ENV["DELIVER_SCREENSHOTS_PATH"]})".yellow
|
290
|
-
@screens_path = ENV["DELIVER_SCREENSHOTS_PATH"]
|
291
|
-
end
|
292
|
-
|
293
|
-
@screens_path ||= "./screenshots/" # default value
|
294
|
-
|
295
|
-
return @screens_path
|
296
|
-
end
|
297
|
-
|
298
|
-
def set_screenshots
|
299
|
-
screens_path = screenshots_path
|
300
|
-
if screens_path
|
301
|
-
# Not using Snapfile. Not a good user.
|
302
|
-
if not app.metadata.set_all_screenshots_from_path(screens_path, use_framed_screenshots?)
|
303
|
-
# This path does not contain folders for each language
|
304
|
-
if screens_path.kind_of?String
|
305
|
-
if @deploy_information[Deliverer::ValKey::DEFAULT_LANGUAGE]
|
306
|
-
screens_path = { @deploy_information[Deliverer::ValKey::DEFAULT_LANGUAGE] => screens_path } # use the default language
|
307
|
-
@deploy_information[Deliverer::ValKey::SCREENSHOTS_PATH] = screens_path
|
308
|
-
else
|
309
|
-
Helper.log.error "You must have folders for the screenshots (#{screens_path}) for each language (e.g. en-US, de-DE)."
|
310
|
-
screens_path = nil
|
311
|
-
end
|
312
|
-
end
|
313
|
-
app.metadata.set_screenshots_for_each_language(screens_path, use_framed_screenshots?) if screens_path
|
314
|
-
end
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
# Should _framed screenshots be used for the screenshot upload?
|
319
|
-
# This will only be true if there is a Framefile, as this makes the screenshots valid
|
320
|
-
# since the resolution is only correct when using a background + title using frameit 2.0
|
321
|
-
def use_framed_screenshots?
|
322
|
-
return Dir[screenshots_path + "**/Framefile.json"].count > 0
|
323
|
-
end
|
324
|
-
|
325
|
-
def verify_pdf_file
|
326
|
-
if @deploy_information[Deliverer::ValKey::SKIP_PDF]
|
327
|
-
Helper.log.debug "PDF verify was skipped"
|
328
|
-
else
|
329
|
-
# Everything is prepared for the upload
|
330
|
-
# We may have to ask the user if that's okay
|
331
|
-
html_path = HtmlGenerator.new.render(self)
|
332
|
-
unless Helper.is_test?
|
333
|
-
puts "----------------------------------------------------------------------------"
|
334
|
-
puts "Verifying the upload via the HTML file can be disabled by either adding"
|
335
|
-
puts "'skip_pdf true' to your Deliverfile or using the flag --force."
|
336
|
-
puts "----------------------------------------------------------------------------"
|
337
|
-
|
338
|
-
system("open '#{html_path}'")
|
339
|
-
okay = agree("Does the Preview on path '#{html_path}' look okay for you? (blue = updated) (y/n)", true)
|
340
|
-
|
341
|
-
unless okay
|
342
|
-
dir ||= app.get_metadata_directory
|
343
|
-
dir += "/#{app.apple_id}.itmsp"
|
344
|
-
FileUtils.rm_rf(dir) unless Helper.is_test?
|
345
|
-
raise "Did not upload the metadata, because the HTML file was rejected by the user".yellow
|
346
|
-
end
|
347
|
-
end
|
348
|
-
end
|
349
|
-
end
|
350
|
-
|
351
|
-
def trigger_metadata_upload
|
352
|
-
result = app.metadata.upload!
|
353
|
-
raise "Error uploading app metadata".red unless result == true
|
354
|
-
end
|
355
|
-
|
356
|
-
def itc
|
357
|
-
@itc ||= ItunesConnect.new
|
358
|
-
end
|
359
|
-
|
360
|
-
def additional_itc_information
|
361
|
-
# e.g. rating or copyright
|
362
|
-
itc.set_copyright!(app, @deploy_information[Deliverer::ValKey::COPYRIGHT]) if @deploy_information[Deliverer::ValKey::COPYRIGHT]
|
363
|
-
itc.set_app_review_information!(app, @deploy_information[Deliverer::ValKey::APP_REVIEW_INFORMATION]) if @deploy_information[Deliverer::ValKey::APP_REVIEW_INFORMATION]
|
364
|
-
itc.set_release_after_approval!(app, @deploy_information[Deliverer::ValKey::AUTOMATIC_RELEASE]) if @deploy_information[Deliverer::ValKey::AUTOMATIC_RELEASE] != nil
|
365
|
-
|
366
|
-
# Categories
|
367
|
-
primary = @deploy_information[Deliverer::ValKey::PRIMARY_CATEGORY]
|
368
|
-
secondary = @deploy_information[Deliverer::ValKey::SECONDARY_CATEGORY]
|
369
|
-
primary_subcategories = @deploy_information[Deliverer::ValKey::PRIMARY_SUBCATEGORIES]
|
370
|
-
secondary_subcategories = @deploy_information[Deliverer::ValKey::SECONDARY_SUBCATEGORIES]
|
371
|
-
itc.set_categories!(app, primary, secondary, primary_subcategories, secondary_subcategories) if (primary or secondary)
|
372
|
-
|
373
|
-
# App Rating
|
374
|
-
itc.set_app_rating!(app, @deploy_information[Deliverer::ValKey::RATINGS_CONFIG_PATH]) if @deploy_information[Deliverer::ValKey::RATINGS_CONFIG_PATH]
|
375
|
-
|
376
|
-
# App Icon
|
377
|
-
itc.upload_app_icon!(app, @deploy_information[Deliverer::ValKey::APP_ICON]) if @deploy_information[Deliverer::ValKey::APP_ICON]
|
378
|
-
|
379
|
-
# Apple Watch App Icon
|
380
|
-
itc.upload_apple_watch_app_icon!(app, @deploy_information[Deliverer::ValKey::APPLE_WATCH_APP_ICON]) if @deploy_information[Deliverer::ValKey::APPLE_WATCH_APP_ICON]
|
381
|
-
end
|
382
|
-
|
383
|
-
def trigger_ipa_upload
|
384
|
-
if @ipa
|
385
|
-
@ipa.app = app # we now have the resulting app
|
386
|
-
result = @ipa.upload! # Important: this will also actually deploy the app on iTunesConnect
|
387
|
-
raise "Error uploading ipa file".red unless result == true
|
388
|
-
else
|
389
|
-
Helper.log.warn "No IPA file given. Only the metadata was uploaded. If you want to deploy a full update, provide an ipa file."
|
390
|
-
end
|
391
|
-
end
|
392
|
-
|
393
|
-
def call_success_block
|
394
|
-
if @deploy_information[:blocks][:success]
|
395
|
-
@deploy_information[:blocks][:success].call(hash_for_callback)
|
396
|
-
end
|
397
|
-
end
|
398
|
-
|
399
|
-
def call_error_block(ex)
|
400
|
-
if @deploy_information[:blocks][:error]
|
401
|
-
# Custom error handling, we just call this one
|
402
|
-
@deploy_information[:blocks][:error].call(hash_for_callback(ex))
|
403
|
-
end
|
404
|
-
|
405
|
-
# Re-Raise the exception
|
406
|
-
raise ex
|
407
|
-
end
|
408
|
-
|
409
|
-
private
|
410
|
-
#####################################################
|
411
|
-
# @!group All the helper methods
|
412
|
-
#####################################################
|
413
|
-
|
414
|
-
def hash_for_callback(error = nil)
|
415
|
-
{
|
416
|
-
error: error,
|
417
|
-
app_version: (app_version rescue nil),
|
418
|
-
app_identifier: (app_identifier rescue nil),
|
419
|
-
skipped_deploy: skip_deployment?,
|
420
|
-
is_release_build: is_release_build?,
|
421
|
-
is_beta_build: is_beta_build?,
|
422
|
-
ipa_path: ENV["DELIVER_IPA_PATH"]
|
423
|
-
}
|
424
|
-
end
|
425
|
-
end
|
426
|
-
end
|