deliver 0.13.5 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -208
  3. data/bin/deliver +1 -1
  4. data/lib/assets/DeliverfileDefault +2 -22
  5. data/lib/assets/summary.html.erb +27 -39
  6. data/lib/deliver.rb +16 -14
  7. data/lib/deliver/app_screenshot.rb +43 -33
  8. data/lib/deliver/commands_generator.rb +30 -108
  9. data/lib/deliver/detect_values.rb +23 -0
  10. data/lib/deliver/download_screenshots.rb +30 -9
  11. data/lib/deliver/html_generator.rb +7 -8
  12. data/lib/deliver/options.rb +126 -0
  13. data/lib/deliver/runner.rb +75 -0
  14. data/lib/deliver/setup.rb +84 -0
  15. data/lib/deliver/submit_for_review.rb +60 -0
  16. data/lib/deliver/upload_assets.rb +22 -0
  17. data/lib/deliver/upload_metadata.rb +100 -0
  18. data/lib/deliver/upload_price_tier.rb +21 -0
  19. data/lib/deliver/upload_screenshots.rb +63 -0
  20. data/lib/deliver/version.rb +2 -1
  21. metadata +37 -62
  22. data/lib/assets/DeliverLanguageMapping.json +0 -187
  23. data/lib/assets/DeliverfileExample +0 -38
  24. data/lib/deliver/app.rb +0 -167
  25. data/lib/deliver/app_metadata.rb +0 -419
  26. data/lib/deliver/app_metadata_screenshots.rb +0 -189
  27. data/lib/deliver/deliver_process.rb +0 -426
  28. data/lib/deliver/deliverer.rb +0 -138
  29. data/lib/deliver/deliverfile/deliverfile.rb +0 -35
  30. data/lib/deliver/deliverfile/deliverfile_creator.rb +0 -135
  31. data/lib/deliver/deliverfile/dsl.rb +0 -142
  32. data/lib/deliver/dependency_checker.rb +0 -19
  33. data/lib/deliver/ipa_file_analyser.rb +0 -44
  34. data/lib/deliver/ipa_uploader.rb +0 -148
  35. data/lib/deliver/itunes_connect/itunes_connect.rb +0 -12
  36. data/lib/deliver/itunes_connect/itunes_connect_additional.rb +0 -105
  37. data/lib/deliver/itunes_connect/itunes_connect_app_icon.rb +0 -41
  38. data/lib/deliver/itunes_connect/itunes_connect_app_rating.rb +0 -90
  39. data/lib/deliver/itunes_connect/itunes_connect_apple_watch_app_icon.rb +0 -42
  40. data/lib/deliver/itunes_connect/itunes_connect_information.rb +0 -34
  41. data/lib/deliver/itunes_connect/itunes_connect_new_version.rb +0 -67
  42. data/lib/deliver/itunes_connect/itunes_connect_reader.rb +0 -46
  43. data/lib/deliver/itunes_connect/itunes_connect_screenshot_fetcher.rb +0 -54
  44. data/lib/deliver/itunes_connect/itunes_connect_submission.rb +0 -282
  45. data/lib/deliver/itunes_transporter.rb +0 -221
  46. data/lib/deliver/metadata_item.rb +0 -94
  47. data/lib/deliver/testflight.rb +0 -27
@@ -1,221 +0,0 @@
1
- require 'pty'
2
- require 'shellwords'
3
- require 'credentials_manager/password_manager'
4
-
5
-
6
- module Deliver
7
- # The TransporterInputError occurs when you passed wrong inputs to the {Deliver::ItunesTransporter}
8
- class TransporterInputError < StandardError
9
- end
10
- # The TransporterTransferError occurs when some error happens
11
- # while uploading or downloading something from/to iTC
12
- class TransporterTransferError < StandardError
13
- end
14
-
15
- class ItunesTransporter
16
- ERROR_REGEX = />\s*ERROR:\s+(.+)/
17
- WARNING_REGEX = />\s*WARN:\s+(.+)/
18
- OUTPUT_REGEX = />\s+(.+)/
19
- RETURN_VALUE_REGEX = />\sDBG-X:\sReturning\s+(\d+)/
20
-
21
- SKIP_ERRORS = [ "ERROR: An exception has occurred: Scheduling automatic restart in 1 minute" ]
22
-
23
- private_constant :ERROR_REGEX, :WARNING_REGEX, :OUTPUT_REGEX, :RETURN_VALUE_REGEX, :SKIP_ERRORS
24
-
25
- # This will be called from the Deliverfile, and disables the logging of the transporter output
26
- def self.hide_transporter_output
27
- @@hide_transporter_output = true
28
- end
29
-
30
- # Returns a new instance of the iTunesTransporter.
31
- # If no username or password given, it will be taken from
32
- # the #{CredentialsManager::PasswordManager}
33
- def initialize(user = nil, password = nil)
34
- @user = (user || CredentialsManager::PasswordManager.shared_manager.username)
35
- @password = (password || CredentialsManager::PasswordManager.shared_manager.password)
36
- end
37
-
38
- # Downloads the latest version of the app metadata package from iTC.
39
- # @param app [Deliver::App] The app you want to download the data for
40
- # @param dir [String] the path to the package file
41
- # @return (Bool) True if everything worked fine
42
- # @raise [Deliver::TransporterTransferError] when something went wrong
43
- # when transfering
44
- # @raise [Deliver::TransporterInputError] when passing wrong inputs
45
- def download(app, dir = nil)
46
- dir ||= "/tmp"
47
- raise TransporterInputError.new("No valid Deliver::App given") unless app.kind_of?Deliver::App
48
-
49
- Helper.log.info "Going to download app metadata from iTunesConnect"
50
- dir ||= app.get_metadata_directory
51
- command = build_download_command(@user, @password, app.apple_id, dir)
52
-
53
- result = execute_transporter(command)
54
-
55
- itmsp_path = File.join(dir, "#{app.apple_id}.itmsp")
56
- if result and File.directory?itmsp_path
57
- Helper.log.info "Successfully downloaded the latest package from iTunesConnect.".green
58
- else
59
- unless /^[0-9a-zA-Z\.\$\_]*$/ === @password
60
- Helper.log.error "Password contains special characters, which may not be handled properly by iTMSTransporter. If you experience problems uploading to iTunes Connect, please consider changing your password to something with only alphanumeric characters."
61
- end
62
- Helper.log.fatal "Could not download metadata from iTunes Connect! It's probably related to your password or your internet connection."
63
- end
64
-
65
- result
66
- end
67
-
68
- # Uploads the modified package back to iTunesConnect
69
- # @param app [Deliver::App] The app you want to download the data for
70
- # @param dir [String] the path in which the package file is located
71
- # @return (Bool) True if everything worked fine
72
- # @raise [Deliver::TransporterTransferError] when something went wrong
73
- # when transfering
74
- # @raise [Deliver::TransporterInputError] when passing wrong inputs
75
- def upload(app, dir)
76
- raise TransporterInputError.new("No valid Deliver::App given") unless app.kind_of?Deliver::App
77
-
78
- dir ||= app.get_metadata_directory
79
- dir += "/#{app.apple_id}.itmsp"
80
-
81
- Helper.log.info "Going to upload updated app to iTunesConnect"
82
- Helper.log.info "This might take a few minutes, please don't interrupt the script".green
83
-
84
- command = build_upload_command(@user, @password, dir)
85
- result = execute_transporter(command)
86
-
87
- if result
88
- Helper.log.info(("-" * 102).green)
89
- Helper.log.info("Successfully uploaded package to iTunesConnect. It might take a few minutes until it's visible online.".green)
90
- Helper.log.info(("-" * 102).green)
91
-
92
- FileUtils.rm_rf(dir) unless Helper.is_test? # we don't need the package any more, since the upload was successful
93
- end
94
-
95
- result
96
- end
97
-
98
- private
99
- def execute_transporter(command)
100
- @errors = []
101
- @warnings = []
102
-
103
- if defined?@@hide_transporter_output
104
- # Show a one time message instead
105
- Helper.log.info "Waiting for iTunes Connect transporter to be finished.".green
106
- Helper.log.info "iTunes Transporter progress... this might take a few minutes...".green
107
- end
108
-
109
- begin
110
- PTY.spawn(command) do |stdin, stdout, pid|
111
- stdin.each do |line|
112
- parse_line(line) # this is where the parsing happens
113
- end
114
- end
115
- rescue => ex
116
- Helper.log.fatal(ex.to_s)
117
- @errors << ex.to_s
118
- end
119
-
120
- if @warnings.count > 0
121
- Helper.log.warn(@warnings.join("\n"))
122
- end
123
-
124
- if @errors.count > 0
125
- Helper.log.error(@errors.join("\n"))
126
- return false
127
- end
128
-
129
- true
130
- end
131
-
132
- def parse_line(line)
133
- # Taken from https://github.com/sshaw/itunes_store_transporter/blob/master/lib/itunes/store/transporter/output_parser.rb
134
-
135
- output_done = false
136
-
137
- re = Regexp.union(SKIP_ERRORS)
138
- if line.match(re)
139
- # Those lines will not be handle like errors or warnings
140
-
141
- elsif line =~ ERROR_REGEX
142
- @errors << $1
143
- Helper.log.error "[Transporter Error Output]: #{$1}".red
144
-
145
- # Check if it's a login error
146
- if $1.include?"Your Apple ID or password was entered incorrectly" or
147
- $1.include?"This Apple ID has been locked for security reasons"
148
-
149
- CredentialsManager::PasswordManager.shared_manager.password_seems_wrong unless Helper.is_test?
150
- elsif $1.include?"Redundant Binary Upload. There already exists a binary upload with build"
151
- Helper.log.fatal $1
152
- Helper.log.fatal "You have to change the build number of your app to upload your ipa file"
153
- end
154
-
155
- output_done = true
156
- elsif line =~ WARNING_REGEX
157
- @warnings << $1
158
- Helper.log.warn "[Transporter Warning Output]: #{$1}".yellow
159
- output_done = true
160
- end
161
-
162
- if line =~ RETURN_VALUE_REGEX
163
- if $1.to_i != 0
164
- Helper.log.fatal "Transporter transfer failed.".red
165
- Helper.log.warn(@warnings.join("\n").yellow)
166
- Helper.log.error(@errors.join("\n").red)
167
- raise "Return status of iTunes Transporter was #{$1}: #{@errors.join('\n')}".red
168
- else
169
- Helper.log.info "iTunes Transporter successfully finished its job".green
170
- end
171
- end
172
-
173
- if not defined?@@hide_transporter_output and line =~ OUTPUT_REGEX
174
- # General logging for debug purposes
175
- unless output_done
176
- Helper.log.debug "[Transporter]: #{$1}"
177
- end
178
- end
179
- end
180
-
181
- def build_download_command(username, password, apple_id, destination = "/tmp")
182
- [
183
- '"' + Helper.transporter_path + '"',
184
- "-m lookupMetadata",
185
- "-u \"#{username}\"",
186
- "-p '#{escaped_password(password)}'",
187
- "-apple_id #{apple_id}",
188
- "-destination '#{destination}'",
189
- "-subitemtype None"
190
- ].join(' ')
191
-
192
- # The subitemtype defines that we don't want to download in-app purchases and gamecenter things
193
- # Allowed values:
194
- # - GameCenterLeaderboard
195
- # - GameCenterAchievement
196
- # - InAppPurchase
197
- # - None
198
- end
199
-
200
- def build_upload_command(username, password, source = "/tmp")
201
- parts = [
202
- '"' + Helper.transporter_path + '"',
203
- "-m upload",
204
- "-u \"#{username}\"",
205
- "-p '#{escaped_password(password)}'",
206
- "-f '#{source}'",
207
- ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"], # that's here, because the user might overwrite the -t option
208
- "-k 100000"
209
- ]
210
-
211
- parts << "-t 'Signiant'" unless parts.join(" ").include?"-t"
212
-
213
- parts.join(' ')
214
- end
215
-
216
- def escaped_password(password)
217
- Shellwords.escape(password)
218
- end
219
-
220
- end
221
- end
@@ -1,94 +0,0 @@
1
- require 'nokogiri'
2
-
3
- module Deliver
4
- # This class represents a file, included in the metadata.xml
5
- #
6
- # It takes care of calculating the file size and md5 value.
7
- class MetadataItem
8
- # @return [String] The path to this particular asset
9
- attr_accessor :path
10
-
11
- # Returns a new instance of MetadataItem
12
- # @param path [String] the path to the real world file
13
- # @param custom_node_name [String] You can set a custom name
14
- # for the newly created node.
15
- def initialize(path, custom_node_name = nil)
16
- raise "File not found at path '#{path}'" unless File.exists?path
17
-
18
- self.path = path
19
- @custom_node_name = custom_node_name
20
- end
21
-
22
- # This method is called when storing this item into the metadata.xml file
23
- #
24
- # This method will calculate the md5 hash and exact file size
25
- # Generates XML code that looks something like this
26
- # +code+
27
- # <data_file>
28
- # <size>11463227</size>
29
- # <file_name>myapp.54.56.ipa</file_name>
30
- # <checksum type="md5">9d6b7b0e20bde9a3c831db89563e949f</checksum>
31
- # </data_file>
32
- # Take a look at the subclass {Deliver::AppScreenshot#create_xml_node} for a
33
- # screenshot specific implementation
34
- # @param doc [Nokogiri::XML::Document] The document this node
35
- # should be added to
36
- # @return [Nokogiri::XML::Node] the resulting XML node
37
- def create_xml_node(doc)
38
- screenshot = Nokogiri::XML::Node.new(name_for_xml_node, doc)
39
-
40
- node_set = Nokogiri::XML::NodeSet.new(doc)
41
-
42
- # File Size
43
- size = Nokogiri::XML::Node.new('size', doc)
44
- size.content = File.size(self.path)
45
- node_set << size
46
-
47
- # File Name
48
- file_name = Nokogiri::XML::Node.new('file_name', doc)
49
- file_name.content = resulting_file_name
50
- node_set << file_name
51
-
52
- # md5 Checksum
53
- checksum = Nokogiri::XML::Node.new('checksum', doc)
54
- checksum.content = md5_value
55
- checksum['type'] = 'md5'
56
- node_set << checksum
57
-
58
-
59
- screenshot.children = node_set
60
-
61
- return screenshot
62
- end
63
-
64
- # We also have to copy the file itself, since it has to be *inside* the package
65
- # You don't have to call this method manually.
66
- def store_file_inside_package(path_to_package)
67
- # This will also rename the resulting file to not have any spaces or other
68
- # illegal characters in the file name
69
-
70
- FileUtils.cp(self.path, "#{path_to_package}/#{resulting_file_name}")
71
- end
72
-
73
- private
74
- def name_for_xml_node
75
- @custom_node_name || 'data_file'
76
- end
77
-
78
- # The file name which is used inside the package
79
- def resulting_file_name
80
- extension = File.extname(self.path)
81
- "#{file_name_for_element}#{extension}"
82
- end
83
-
84
- def md5_value
85
- Digest::MD5.hexdigest(File.read(self.path))
86
- end
87
-
88
- # This method will also take some other things into account to generate a truly unique
89
- # file name. This will enable using the same screenshots multiple times
90
- def file_name_for_element
91
- Digest::MD5.hexdigest([File.read(self.path), self.path].join("-"))
92
- end
93
- end
94
- end
@@ -1,27 +0,0 @@
1
- module Deliver
2
- class Testflight
3
-
4
- # Uploads a new build to Apple TestFlight
5
- # @param ipa_path (String) a path to the IPA to upload
6
- # @param app_id (String) optional, the app ID
7
- # @param skip_deploy (boolean) Should the submission be skipped?
8
- def self.upload!(ipa_path, app_id, skip_deploy)
9
- ItunesTransporter.hide_transporter_output
10
-
11
- app_identifier = IpaFileAnalyser.fetch_app_identifier(ipa_path)
12
- app_identifier ||= ENV["TESTFLIGHT_APP_IDENTITIFER"] || ask("Could not automatically find the app identifier, please enter the app's bundle identifier: ")
13
- app_id ||= (FastlaneCore::ItunesSearchApi.fetch_by_identifier(app_identifier)['trackId'] rescue nil)
14
- app_id ||= (FastlaneCore::ItunesConnect.new.find_apple_id(app_identifier) rescue nil)
15
- app_id ||= ENV["TESTFLIGHT_APPLE_ID"] || ask("Could not automatically find the app ID, please enter it here (e.g. 956814360): ")
16
- strategy = (skip_deploy ? Deliver::IPA_UPLOAD_STRATEGY_JUST_UPLOAD : Deliver::IPA_UPLOAD_STRATEGY_BETA_BUILD)
17
-
18
- Helper.log.info "Ready to upload new build to TestFlight (#{app_identifier} - #{app_id})".green
19
-
20
- # Got everything to ready to deploy
21
- app = App.new(app_identifier: app_identifier, apple_id: app_id)
22
- ipa = IpaUploader.new(app, '/tmp/', ipa_path, strategy)
23
- result = ipa.upload!
24
- raise "Error distributing new beta version!".red unless result == true
25
- end
26
- end
27
- end