deliver 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +37 -10
- data/.rspec +1 -0
- data/.travis.yml +8 -0
- data/.yardopts +1 -0
- data/Gemfile.lock +106 -0
- data/LICENSE +21 -0
- data/README.md +268 -17
- data/Rakefile +3 -0
- data/assets/PDFExample.png +0 -0
- data/assets/SubmitForReviewInformation.png +0 -0
- data/assets/deliver.png +0 -0
- data/assets/deliver.pxm +0 -0
- data/assets/deliverFullSize.png +0 -0
- data/bin/deliver +32 -0
- data/deliver.gemspec +15 -9
- data/lib/assets/DeliverfileDefault +47 -0
- data/lib/assets/DeliverfileExample +62 -0
- data/lib/assets/ScreenshotsHelp +4 -0
- data/lib/deliver.rb +20 -1
- data/lib/deliver/app.rb +146 -0
- data/lib/deliver/app_metadata.rb +487 -0
- data/lib/deliver/app_screenshot.rb +119 -0
- data/lib/deliver/commands.rb +4 -0
- data/lib/deliver/commands/init.rb +12 -0
- data/lib/deliver/commands/run.rb +20 -0
- data/lib/deliver/deliver_process.rb +241 -0
- data/lib/deliver/deliverer.rb +112 -0
- data/lib/deliver/deliverfile/deliverfile.rb +35 -0
- data/lib/deliver/deliverfile/deliverfile_creator.rb +115 -0
- data/lib/deliver/deliverfile/dsl.rb +124 -0
- data/lib/deliver/dependency_checker.rb +32 -0
- data/lib/deliver/helper.rb +55 -0
- data/lib/deliver/ipa_uploader.rb +160 -0
- data/lib/deliver/itunes_connect.rb +514 -0
- data/lib/deliver/itunes_search_api.rb +48 -0
- data/lib/deliver/itunes_transporter.rb +154 -0
- data/lib/deliver/languages.rb +6 -0
- data/lib/deliver/metadata_item.rb +94 -0
- data/lib/deliver/password_manager.rb +86 -0
- data/lib/deliver/pdf_generator.rb +131 -0
- data/lib/deliver/version.rb +1 -1
- data/spec/app_metadata_spec.rb +350 -0
- data/spec/app_screenshot_spec.rb +88 -0
- data/spec/app_spec.rb +85 -0
- data/spec/deliverer_spec.rb +48 -0
- data/spec/deliverfile_creator_spec.rb +73 -0
- data/spec/example_deliver_files_spec.rb +227 -0
- data/spec/fixtures/Deliverfiles/DeliverfileCallbacks +14 -0
- data/spec/fixtures/Deliverfiles/DeliverfileCallbacksFailingTests +14 -0
- data/spec/fixtures/Deliverfiles/DeliverfileCallbacksNoErrorBlock +6 -0
- data/spec/fixtures/Deliverfiles/DeliverfileDefaultLanguageNotOnTop +8 -0
- data/spec/fixtures/Deliverfiles/DeliverfileDuplicateIpa +2 -0
- data/spec/fixtures/Deliverfiles/DeliverfileLocales +16 -0
- data/spec/fixtures/Deliverfiles/DeliverfileMetadataJson +6 -0
- data/spec/fixtures/Deliverfiles/DeliverfileMissingAppVersion +1 -0
- data/spec/fixtures/Deliverfiles/DeliverfileMissingBlockForTests +7 -0
- data/spec/fixtures/Deliverfiles/DeliverfileMissingIdentifier +1 -0
- data/spec/fixtures/Deliverfiles/DeliverfileMissingLanguage +1 -0
- data/spec/fixtures/Deliverfiles/DeliverfileMissingValue +3 -0
- data/spec/fixtures/Deliverfiles/DeliverfileMixed +37 -0
- data/spec/fixtures/Deliverfiles/DeliverfileNoVersion +3 -0
- data/spec/fixtures/Deliverfiles/DeliverfileScreenshots +6 -0
- data/spec/fixtures/Deliverfiles/DeliverfileScreenshotsFallbackDefaultLanguage +7 -0
- data/spec/fixtures/Deliverfiles/DeliverfileSimple +8 -0
- data/spec/fixtures/Deliverfiles/DeliverfileVersionMismatchPackage +8 -0
- data/spec/fixtures/Deliverfiles/DeliverfileWrongIdentifier +5 -0
- data/spec/fixtures/Deliverfiles/DeliverfileWrongVersion +5 -0
- data/spec/fixtures/Deliverfiles/metadata.json +24 -0
- data/spec/fixtures/example1.itmsp/metadata.xml +121 -0
- data/spec/fixtures/example2.itmsp/metadata.xml +54 -0
- data/spec/fixtures/ipas/Example1.ipa +0 -0
- data/spec/fixtures/metadata/ipa_result.xml +12 -0
- data/spec/fixtures/metadata/ipa_result2.xml +12 -0
- data/spec/fixtures/packages/464686641.itmsp/metadata.xml +104 -0
- data/spec/fixtures/packages/794902327.itmsp/metadata.xml +107 -0
- data/spec/fixtures/packages/878567776.itmsp/metadata.xml +104 -0
- data/spec/fixtures/screenshots/de-DE/iPhone4.png +0 -0
- data/spec/fixtures/screenshots/de-DE/iPhone6.png +0 -0
- data/spec/fixtures/screenshots/de-DE/iPhone6Plus1.png +0 -0
- data/spec/fixtures/screenshots/de-DE/iPhone6Plus2.png +0 -0
- data/spec/fixtures/screenshots/de-DE/screenshot1.png +0 -0
- data/spec/fixtures/screenshots/de-DE/screenshot2.png +0 -0
- data/spec/fixtures/screenshots/de-DE/screenshot3.png +0 -0
- data/spec/fixtures/screenshots/de-DE/screenshot5.png +0 -0
- data/spec/fixtures/screenshots/en-US/english.png +0 -0
- data/spec/fixtures/screenshots/iPhone4.png +0 -0
- data/spec/fixtures/screenshots/invalidImage.png +0 -0
- data/spec/fixtures/screenshots/screenshot1.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4 2.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4 copy 2.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4 copy 3.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4 copy 4.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4 copy 5.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4 copy 6.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4 copy.png +0 -0
- data/spec/fixtures/screenshots/tooMany/de-DE/iPhone4.png +0 -0
- data/spec/helper_spec.rb +16 -0
- data/spec/ipa_uploader_spec.rb +61 -0
- data/spec/itunes_connect_spec.rb +12 -0
- data/spec/itunes_search_api_spec.rb +24 -0
- data/spec/itunes_transporter_spec.rb +52 -0
- data/spec/languages_spec.rb +7 -0
- data/spec/metadata_item_spec.rb +36 -0
- data/spec/mocking/transporter_mocking.rb +40 -0
- data/spec/mocking/webmocking.rb +31 -0
- data/spec/password_manager_spec.rb +27 -0
- data/spec/responses/itunesLookup-.json +4 -0
- data/spec/responses/itunesLookup-0.json +4 -0
- data/spec/responses/itunesLookup-284882215.json +106 -0
- data/spec/responses/itunesLookup-at.felixkrause.iTanky.json +8 -0
- data/spec/responses/itunesLookup-com.facebook.Facebook.json +106 -0
- data/spec/responses/itunesLookup-invalid.json +4 -0
- data/spec/responses/itunesLookup-net.sunapps.invalid.json +4 -0
- data/spec/responses/transporter/download_invalid_apple_id.txt +35 -0
- data/spec/responses/transporter/download_valid_apple_id.txt +32 -0
- data/spec/responses/transporter/upload_invalid.txt +174 -0
- data/spec/responses/transporter/upload_valid.txt +290 -0
- data/spec/spec_helper.rb +23 -0
- data/tasks/rspec.rake +3 -0
- metadata +242 -8
- data/LICENSE.txt +0 -22
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'fastimage'
|
2
|
+
|
3
|
+
|
4
|
+
module Deliver
|
5
|
+
# AppScreenshot represents one screenshots for one specific locale and
|
6
|
+
# device type.
|
7
|
+
class AppScreenshot < MetadataItem
|
8
|
+
module ScreenSize
|
9
|
+
# iPhone 4
|
10
|
+
IOS_35 = "iOS-3.5-in"
|
11
|
+
# iPhone 5
|
12
|
+
IOS_40 = "iOS-4-in"
|
13
|
+
# iPhone 6
|
14
|
+
IOS_47 = "iOS-4.7-in"
|
15
|
+
# iPhone 6 Plus
|
16
|
+
IOS_55 = "iOS-5.5-in"
|
17
|
+
# iPad
|
18
|
+
IOS_IPAD = "iOS-iPad"
|
19
|
+
end
|
20
|
+
|
21
|
+
# @return [Deliver::ScreenSize] the screen size (device type)
|
22
|
+
# specified at {Deliver::ScreenSize}
|
23
|
+
attr_accessor :screen_size
|
24
|
+
|
25
|
+
# @param path (String) path to the screenshot file
|
26
|
+
# @param screen_size (Deliver::AppScreenshot::ScreenSize) the screen size, which
|
27
|
+
# will automatically be calculated when you don't set it.
|
28
|
+
def initialize(path, screen_size = nil)
|
29
|
+
super(path)
|
30
|
+
|
31
|
+
screen_size ||= self.class.calculate_screen_size(path)
|
32
|
+
|
33
|
+
self.screen_size = screen_size
|
34
|
+
|
35
|
+
Helper.log.error "Looks like the screenshot given (#{path}) does not match the requirements of #{screen_size}" unless self.is_valid?
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_xml_node(doc, order_index)
|
39
|
+
node = super(doc)
|
40
|
+
|
41
|
+
# Screenshots have a slightly different xml code
|
42
|
+
|
43
|
+
# <software_screenshot display_target="iOS-4-in" position="1">
|
44
|
+
# <size>295276</size>
|
45
|
+
# <file_name>1-en-4-StartScreen.png</file_name>
|
46
|
+
# <checksum type="md5">c00bd122a3ffbc79e26f1ae6210c7efd</checksum>
|
47
|
+
# </software_screenshot>
|
48
|
+
|
49
|
+
|
50
|
+
node['display_target'] = self.screen_size
|
51
|
+
node['position'] = order_index
|
52
|
+
|
53
|
+
return node
|
54
|
+
end
|
55
|
+
|
56
|
+
def name_for_xml_node
|
57
|
+
'software_screenshot'
|
58
|
+
end
|
59
|
+
|
60
|
+
# Validates the given screenshots (size and format)
|
61
|
+
def is_valid?
|
62
|
+
return false unless self.path.split(".").last == "png"
|
63
|
+
|
64
|
+
size = FastImage.size(self.path)
|
65
|
+
|
66
|
+
return self.screen_size == self.class.calculate_screen_size(self.path)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.calculate_screen_size(path)
|
70
|
+
size = FastImage.size(path)
|
71
|
+
|
72
|
+
raise "Could not find or parse file at path '#{path}'" if (size == nil or size.count == 0)
|
73
|
+
|
74
|
+
devices = {
|
75
|
+
ScreenSize::IOS_55 => [
|
76
|
+
[1080, 1920],
|
77
|
+
[1242, 2208]
|
78
|
+
],
|
79
|
+
ScreenSize::IOS_47 => [
|
80
|
+
[750, 1334]
|
81
|
+
],
|
82
|
+
ScreenSize::IOS_40 => [
|
83
|
+
[640, 1136],
|
84
|
+
[640, 1096],
|
85
|
+
[1136, 600] # landscape status bar is smaller
|
86
|
+
],
|
87
|
+
ScreenSize::IOS_35 => [
|
88
|
+
[640, 960],
|
89
|
+
[640, 920],
|
90
|
+
[960, 600] # landscape status bar is smaller
|
91
|
+
],
|
92
|
+
ScreenSize::IOS_IPAD => [
|
93
|
+
[1024, 748],
|
94
|
+
[1024, 768],
|
95
|
+
[2048, 1496],
|
96
|
+
[2048, 1536],
|
97
|
+
[768, 1004],
|
98
|
+
[768, 1024],
|
99
|
+
[1536, 2008],
|
100
|
+
[1536, 2048]
|
101
|
+
]
|
102
|
+
}
|
103
|
+
|
104
|
+
devices.each do |device_type, array|
|
105
|
+
array.each do |resolution|
|
106
|
+
if (size[0] == resolution[0] and size[1] == resolution[1]) or # portrait
|
107
|
+
(size[1] == resolution[0] and size[0] == resolution[1]) # landscape
|
108
|
+
return device_type
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
error = "Unsupported screen size #{size} for path '#{path}'"
|
114
|
+
raise error
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
ScreenSize = AppScreenshot::ScreenSize
|
119
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
command :init do |c|
|
4
|
+
c.syntax = 'deliver init'
|
5
|
+
c.description = "Creates a new Deliverfile in the current directory"
|
6
|
+
|
7
|
+
c.action do |args, options|
|
8
|
+
Deliver::DependencyChecker.check_dependencies
|
9
|
+
|
10
|
+
Deliver::DeliverfileCreator.create(enclosed_directory)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
command :run do |c|
|
4
|
+
c.syntax = 'deliver'
|
5
|
+
c.description = 'Run a deploy process using the Deliverfile in the current folder'
|
6
|
+
c.option '--force', 'Runs a deployment without verifying any information (PDF file). This can be used for build servers.'
|
7
|
+
c.action do |args, options|
|
8
|
+
Deliver::DependencyChecker.check_dependencies
|
9
|
+
|
10
|
+
if File.exists?(deliver_path)
|
11
|
+
# Everything looks alright, use the given Deliverfile
|
12
|
+
Deliver::Deliverer.new(deliver_path, force: options.force)
|
13
|
+
else
|
14
|
+
Deliver::Helper.log.warn("No Deliverfile found at path '#{deliver_path}'.")
|
15
|
+
if agree("Do you want to create a new Deliverfile at the current directory? (y/n)", true)
|
16
|
+
Deliver::DeliverfileCreator.create(enclosed_directory)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,241 @@
|
|
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 (Hash) All the updated/new information we got from the Deliverfile.
|
13
|
+
# is used to store the deploy information until the Deliverfile finished running.
|
14
|
+
attr_accessor :deploy_information
|
15
|
+
|
16
|
+
def initialize(deploy_information = nil)
|
17
|
+
@deploy_information = deploy_information || {}
|
18
|
+
@deploy_information[:blocks] ||= {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
begin
|
23
|
+
run_unit_tests
|
24
|
+
fetch_information_from_ipa_file
|
25
|
+
|
26
|
+
Helper.log.info("Got all information needed to deploy a new update ('#{@app_version}') for app '#{@app_identifier}'")
|
27
|
+
|
28
|
+
verify_ipa_file
|
29
|
+
create_app
|
30
|
+
verify_app_on_itunesconnect
|
31
|
+
|
32
|
+
load_metadata_from_config_json_folder # the json file generated from the quick start
|
33
|
+
set_app_metadata
|
34
|
+
set_screenshots
|
35
|
+
|
36
|
+
verify_pdf_file
|
37
|
+
|
38
|
+
trigger_metadata_upload
|
39
|
+
trigger_ipa_upload
|
40
|
+
|
41
|
+
call_success_block
|
42
|
+
rescue Exception => ex
|
43
|
+
call_error_block(ex)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#####################################################
|
48
|
+
# @!group All the methods
|
49
|
+
#####################################################
|
50
|
+
|
51
|
+
def run_unit_tests
|
52
|
+
if @deploy_information[:blocks][:unit_tests]
|
53
|
+
result = @deploy_information[:blocks][:unit_tests].call
|
54
|
+
if result
|
55
|
+
Helper.log.debug("Unit tests successful".green)
|
56
|
+
else
|
57
|
+
raise DeliverUnitTestsError.new("Unit tests failed. Got result: '#{result}'. Need 'true' or 1 to succeed.".red)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def fetch_information_from_ipa_file
|
63
|
+
@app_version = @deploy_information[Deliverer::ValKey::APP_VERSION]
|
64
|
+
@app_identifier = @deploy_information[Deliverer::ValKey::APP_IDENTIFIER]
|
65
|
+
|
66
|
+
used_ipa_file = @deploy_information[:ipa] || @deploy_information[:beta_ipa]
|
67
|
+
|
68
|
+
if used_ipa_file
|
69
|
+
@ipa = Deliver::IpaUploader.new(Deliver::App.new, '/tmp/', used_ipa_file, is_beta_build?)
|
70
|
+
|
71
|
+
# We are able to fetch some metadata directly from the ipa file
|
72
|
+
# If they were also given in the Deliverfile, we will compare the values
|
73
|
+
@app_identifier = verify_app_identifier(@app_identifier)
|
74
|
+
@app_version = verify_app_version(@app_version)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def verify_ipa_file
|
79
|
+
raise Deliverfile::Deliverfile::DeliverfileDSLError.new(Deliverfile::Deliverfile::MISSING_APP_IDENTIFIER_MESSAGE.red) unless @app_identifier
|
80
|
+
raise Deliverfile::Deliverfile::DeliverfileDSLError.new(Deliverfile::Deliverfile::MISSING_VERSION_NUMBER_MESSAGE.red) unless @app_version
|
81
|
+
if (@deploy_information[Deliverer::ValKey::IPA] and @deploy_information[Deliverer::ValKey::BETA_IPA])
|
82
|
+
raise Deliverfile::Deliverfile::DeliverfileDSLError.new("You can not set both ipa and beta_ipa in one file. Either it's a beta build or a release build".red)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_app
|
87
|
+
@app = Deliver::App.new(app_identifier: @app_identifier,
|
88
|
+
apple_id: @deploy_information[Deliverer::ValKey::APPLE_ID])
|
89
|
+
end
|
90
|
+
|
91
|
+
def verify_app_on_itunesconnect
|
92
|
+
if @ipa and not is_beta_build?
|
93
|
+
# This is a real release, which should also upload the ipa file onto production
|
94
|
+
@app.create_new_version!(@app_version) unless Helper.is_test?
|
95
|
+
@app.metadata.verify_version(@app_version)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def load_metadata_from_config_json_folder
|
100
|
+
return unless @deploy_information[Deliverer::ValKey::CONFIG_JSON_FOLDER]
|
101
|
+
|
102
|
+
matching = {
|
103
|
+
'title' => Deliverer::ValKey::TITLE,
|
104
|
+
'description' => Deliverer::ValKey::DESCRIPTION,
|
105
|
+
'version_whats_new' => Deliverer::ValKey::CHANGELOG,
|
106
|
+
'keywords' => Deliverer::ValKey::KEYWORDS,
|
107
|
+
'privacy_url' => Deliverer::ValKey::PRIVACY_URL,
|
108
|
+
'software_url' => Deliverer::ValKey::MARKETING_URL,
|
109
|
+
'support_url' => Deliverer::ValKey::SUPPORT_URL
|
110
|
+
}
|
111
|
+
|
112
|
+
file_path = @deploy_information[:config_json_folder]
|
113
|
+
unless file_path.split("/").last.include?"metadata.json"
|
114
|
+
file_path += "/metadata.json"
|
115
|
+
end
|
116
|
+
|
117
|
+
raise "Could not find metadatafile at path '#{file_path}'".red unless File.exists?file_path
|
118
|
+
|
119
|
+
content = JSON.parse(File.read(file_path))
|
120
|
+
content.each do |language, current|
|
121
|
+
|
122
|
+
matching.each do |key, value|
|
123
|
+
if current[key]
|
124
|
+
@deploy_information[value] ||= {}
|
125
|
+
@deploy_information[value][language] = current[key]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def set_app_metadata
|
132
|
+
@app.metadata.update_title(@deploy_information[Deliverer::ValKey::TITLE]) if @deploy_information[Deliverer::ValKey::TITLE]
|
133
|
+
@app.metadata.update_description(@deploy_information[Deliverer::ValKey::DESCRIPTION]) if @deploy_information[Deliverer::ValKey::DESCRIPTION]
|
134
|
+
|
135
|
+
@app.metadata.update_support_url(@deploy_information[Deliverer::ValKey::SUPPORT_URL]) if @deploy_information[Deliverer::ValKey::SUPPORT_URL]
|
136
|
+
@app.metadata.update_changelog(@deploy_information[Deliverer::ValKey::CHANGELOG]) if @deploy_information[Deliverer::ValKey::CHANGELOG]
|
137
|
+
@app.metadata.update_marketing_url(@deploy_information[Deliverer::ValKey::MARKETING_URL]) if @deploy_information[Deliverer::ValKey::MARKETING_URL]
|
138
|
+
@app.metadata.update_privacy_url(@deploy_information[Deliverer::ValKey::PRIVACY_URL]) if @deploy_information[Deliverer::ValKey::PRIVACY_URL]
|
139
|
+
|
140
|
+
@app.metadata.update_keywords(@deploy_information[Deliverer::ValKey::KEYWORDS]) if @deploy_information[Deliverer::ValKey::KEYWORDS]
|
141
|
+
end
|
142
|
+
|
143
|
+
def set_screenshots
|
144
|
+
screens_path = @deploy_information[Deliverer::ValKey::SCREENSHOTS_PATH]
|
145
|
+
if screens_path
|
146
|
+
if not @app.metadata.set_all_screenshots_from_path(screens_path)
|
147
|
+
# This path does not contain folders for each language
|
148
|
+
if screens_path.kind_of?String
|
149
|
+
if @deploy_information[Deliverer::ValKey::DEFAULT_LANGUAGE]
|
150
|
+
screens_path = { @deploy_information[Deliverer::ValKey::DEFAULT_LANGUAGE] => screens_path } # use the default language
|
151
|
+
@deploy_information[Deliverer::ValKey::SCREENSHOTS_PATH] = screens_path
|
152
|
+
else
|
153
|
+
Helper.log.error "You must have folders for the screenshots (#{screens_path}) for each language (e.g. en-US, de-DE)."
|
154
|
+
screens_path = nil
|
155
|
+
end
|
156
|
+
end
|
157
|
+
@app.metadata.set_screenshots_for_each_language(screens_path) if screens_path
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def verify_pdf_file
|
163
|
+
if @deploy_information[Deliverer::ValKey::SKIP_PDF] or is_beta_build?
|
164
|
+
Helper.log.debug "PDF verify was skipped"
|
165
|
+
else
|
166
|
+
# Everything is prepared for the upload
|
167
|
+
# We may have to ask the user if that's okay
|
168
|
+
pdf_path = PdfGenerator.new.render(self)
|
169
|
+
unless Helper.is_test?
|
170
|
+
puts "----------------------------------------------------------------------------"
|
171
|
+
puts "Verifying the upload via the PDF file can be disabled by either adding"
|
172
|
+
puts "'skip_pdf true' to your Deliverfile or using the flag --force."
|
173
|
+
puts "----------------------------------------------------------------------------"
|
174
|
+
|
175
|
+
system("open '#{pdf_path}'")
|
176
|
+
okay = agree("Does the PDF on path '#{pdf_path}' look okay for you? (blue = updated) (y/n)", true)
|
177
|
+
raise "Did not upload the metadata, because the PDF file was rejected by the user".yellow unless okay
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def trigger_metadata_upload
|
183
|
+
result = @app.metadata.upload!
|
184
|
+
raise "Error uploading app metadata".red unless result == true
|
185
|
+
end
|
186
|
+
|
187
|
+
def trigger_ipa_upload
|
188
|
+
if @ipa
|
189
|
+
@ipa.app = @app # we now have the resulting app
|
190
|
+
result = @ipa.upload! # Important: this will also actually deploy the app on iTunesConnect
|
191
|
+
raise "Error uploading ipa file".red unless result == true
|
192
|
+
else
|
193
|
+
Helper.log.warn "No IPA file given. Only the metadata was uploaded. If you want to deploy a full update, provide an ipa file."
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def call_success_block
|
198
|
+
@deploy_information[:blocks][:success].call if @deploy_information[:blocks][:success]
|
199
|
+
end
|
200
|
+
|
201
|
+
def call_error_block(ex)
|
202
|
+
if @deploy_information[:blocks][:error]
|
203
|
+
# Custom error handling, we just call this one
|
204
|
+
@deploy_information[:blocks][:error].call(ex)
|
205
|
+
else
|
206
|
+
# Re-Raise the exception
|
207
|
+
raise ex
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
private
|
212
|
+
#####################################################
|
213
|
+
# @!group All the helper methods
|
214
|
+
#####################################################
|
215
|
+
def verify_app_identifier(app_identifier)
|
216
|
+
if app_identifier
|
217
|
+
if @ipa.fetch_app_identifier and app_identifier != @ipa.fetch_app_identifier
|
218
|
+
raise Deliver::Deliverfile::Deliverfile::DeliverfileDSLError.new("App Identifier of IPA does not match with the given one ('#{app_identifier}' != '#{@ipa.fetch_app_identifier}')".red)
|
219
|
+
end
|
220
|
+
else
|
221
|
+
app_identifier = @ipa.fetch_app_identifier
|
222
|
+
end
|
223
|
+
return app_identifier
|
224
|
+
end
|
225
|
+
|
226
|
+
def verify_app_version(app_version)
|
227
|
+
if app_version
|
228
|
+
if @ipa.fetch_app_version and app_version != @ipa.fetch_app_version
|
229
|
+
raise Deliver::Deliverfile::Deliverfile::DeliverfileDSLError.new("App Version of IPA does not match with the given one (#{app_version} != #{@ipa.fetch_app_version})".red)
|
230
|
+
end
|
231
|
+
else
|
232
|
+
app_version = @ipa.fetch_app_version
|
233
|
+
end
|
234
|
+
return app_version
|
235
|
+
end
|
236
|
+
|
237
|
+
def is_beta_build?
|
238
|
+
@deploy_information[Deliverer::ValKey::BETA_IPA] != nil
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module Deliver
|
2
|
+
# This class will collect the deploy data from different places
|
3
|
+
# This will trigger:
|
4
|
+
#
|
5
|
+
# - Parsing the Deliverfile
|
6
|
+
# - Temporary storing all the information got from the file, until the file finished executing
|
7
|
+
# - Triggering the upload process itself using the DeliverProcess class
|
8
|
+
class Deliverer
|
9
|
+
# @return (Deliver::Deliverfile::Deliverfile) A reference
|
10
|
+
# to the Deliverfile which is currently being used.
|
11
|
+
attr_accessor :deliver_file
|
12
|
+
|
13
|
+
# @return (Deliver::DeliverProcess) The class which handels the deployment process itself
|
14
|
+
attr_accessor :deliver_process
|
15
|
+
|
16
|
+
module ValKey
|
17
|
+
APP_IDENTIFIER = :app_identifier
|
18
|
+
APPLE_ID = :apple_id
|
19
|
+
APP_VERSION = :version
|
20
|
+
IPA = :ipa
|
21
|
+
BETA_IPA = :beta_ipa
|
22
|
+
DESCRIPTION = :description
|
23
|
+
TITLE = :title
|
24
|
+
CHANGELOG = :changelog
|
25
|
+
SUPPORT_URL = :support_url
|
26
|
+
PRIVACY_URL = :privacy_url
|
27
|
+
MARKETING_URL = :marketing_url
|
28
|
+
KEYWORDS = :keywords
|
29
|
+
SCREENSHOTS_PATH = :screenshots_path
|
30
|
+
DEFAULT_LANGUAGE = :default_language
|
31
|
+
CONFIG_JSON_FOLDER = :config_json_folder # Path to a folder containing a configuration file and including screenshots
|
32
|
+
SKIP_PDF = :skip_pdf
|
33
|
+
SUBMIT_FURTHER_INFORMATION = :submit_further_information # export compliance, content rights and advertising identifier
|
34
|
+
end
|
35
|
+
|
36
|
+
module AllBlocks
|
37
|
+
UNIT_TESTS = :unit_tests
|
38
|
+
SUCCESS = :success
|
39
|
+
ERROR = :error
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
# Start a new deployment process based on the given Deliverfile
|
44
|
+
# @param (String) path The path to the Deliverfile.
|
45
|
+
# @param (Hash) hash You can pass a hash instead of a path to basically
|
46
|
+
# give all the information required (see {Deliverer::ValKey} for available options)
|
47
|
+
# @param (Bool) force Runs a deployment without verifying any information. This can be
|
48
|
+
# used for build servers. If this is set to false a PDF summary will be generated and opened
|
49
|
+
def initialize(path = nil, hash: nil, force: false)
|
50
|
+
@deliver_process = DeliverProcess.new
|
51
|
+
@deliver_process.deploy_information[ValKey::SKIP_PDF] = true if force
|
52
|
+
|
53
|
+
if hash
|
54
|
+
hash.each do |key, value|
|
55
|
+
# we still call this interface to verify the inputs correctly
|
56
|
+
set_new_value(key, value)
|
57
|
+
end
|
58
|
+
|
59
|
+
finished_executing_deliver_file
|
60
|
+
else
|
61
|
+
@deliver_file = Deliver::Deliverfile::Deliverfile.new(self, path)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Do not put code here...
|
65
|
+
end
|
66
|
+
|
67
|
+
# This method is internally called from the Deliverfile DSL
|
68
|
+
# to set a value for a given key. This method will also verify if
|
69
|
+
# the key is valid.
|
70
|
+
def set_new_value(key, value)
|
71
|
+
unless self.class.all_available_keys_to_set.include?key
|
72
|
+
raise "Invalid key '#{key}', must be contained in Deliverer::ValKey.".red
|
73
|
+
end
|
74
|
+
|
75
|
+
if @deliver_process.deploy_information[key]
|
76
|
+
Helper.log.warn("You already set a value for key '#{key}'. Overwriting value '#{value}' with new value.")
|
77
|
+
end
|
78
|
+
|
79
|
+
@deliver_process.deploy_information[key] = value
|
80
|
+
end
|
81
|
+
|
82
|
+
# Sets a new block for a specific key
|
83
|
+
def set_new_block(key, block)
|
84
|
+
@deliver_process.deploy_information[:blocks][key] = block
|
85
|
+
end
|
86
|
+
|
87
|
+
# An array of all available options to be set a deployment_information.
|
88
|
+
#
|
89
|
+
# Is used to verify user inputs
|
90
|
+
# @return (Hash) The array of symbols
|
91
|
+
def self.all_available_keys_to_set
|
92
|
+
Deliverer::ValKey.constants.collect { |a| Deliverer::ValKey.const_get(a) }
|
93
|
+
end
|
94
|
+
|
95
|
+
# An array of all available blocks to be set for a deployment
|
96
|
+
#
|
97
|
+
# Is used to verify user inputs
|
98
|
+
# @return (Hash) The array of symbols
|
99
|
+
def self.all_available_blocks_to_set
|
100
|
+
Deliverer::AllBlocks.constants.collect { |a| Deliverer::AllBlocks.const_get(a) }
|
101
|
+
end
|
102
|
+
|
103
|
+
# This method will take care of the actual deployment process, after we
|
104
|
+
# received all information from the Deliverfile.
|
105
|
+
#
|
106
|
+
# This method will be called from the {Deliver::Deliverfile} after
|
107
|
+
# it is finished executing the Ruby script.
|
108
|
+
def finished_executing_deliver_file
|
109
|
+
deliver_process.run
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|