fastlane_core 0.41.0 → 0.41.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f0e03d2e729260672a1852127c864f711c9e7a58
4
- data.tar.gz: 911a1c50cf3dbbcff3ece7c5ee269f84d15edacd
3
+ metadata.gz: 44801fe477ef2ece37a3950c2183bf38132bdb7a
4
+ data.tar.gz: 87c3ceb4bd30e0cb8e4f78bd1d457ca26f99fb1c
5
5
  SHA512:
6
- metadata.gz: e8526b80e97ba23ed0fa53069c13c2e4441c91f744d91fdf5d3feb1558519e2a26823ce79d0d85f42f9cf14e551f42051ba6076f41f392b67b80130cbe092c57
7
- data.tar.gz: 40907d5e49a11682a880b5e9fb8880ad114b8d1049f190d4aa76adedf76f6c575c6304fd07ae4b140a719276cccc70fd800242ffe1852f65ea38392623d4ff57
6
+ metadata.gz: 00620ff82620ab06c7e3f0e640538fed09b0678d3e1daa88096cad316330f833cbea8d7884de6c4c6e7c27c08c3c47ed7f272ea48ba1cbefe97b753ee4f4ff68
7
+ data.tar.gz: 38576f178ff6eb0494774420e14b1ca94bf0bf3ee750e6c9132b1a6981236d1c6773827aa42415c0d4956ef8f24342fe33af2772392b0da979efb5c21c9f0f3c
@@ -124,15 +124,40 @@ module FastlaneCore
124
124
  @xcode_version
125
125
  end
126
126
 
127
+ def self.transporter_java_executable_path
128
+ return File.join(self.transporter_java_path, 'bin', 'java')
129
+ end
130
+
131
+ def self.transporter_java_ext_dir
132
+ return File.join(self.transporter_java_path, 'lib', 'ext')
133
+ end
134
+
135
+ def self.transporter_java_jar_path
136
+ return File.join(self.itms_path, 'lib', 'itmstransporter-launcher.jar')
137
+ end
138
+
139
+ def self.transporter_user_dir
140
+ return File.join(self.itms_path, 'bin')
141
+ end
142
+
143
+ def self.transporter_java_path
144
+ return File.join(self.itms_path, 'java')
145
+ end
146
+
127
147
  # @return the full path to the iTMSTransporter executable
128
148
  def self.transporter_path
149
+ return File.join(self.itms_path, 'bin', 'iTMSTransporter')
150
+ end
151
+
152
+ # @return the full path to the iTMSTransporter executable
153
+ def self.itms_path
129
154
  return '' unless self.is_mac? # so tests work on Linx too
130
155
 
131
156
  [
132
- "../Applications/Application Loader.app/Contents/MacOS/itms/bin/iTMSTransporter",
133
- "../Applications/Application Loader.app/Contents/itms/bin/iTMSTransporter"
157
+ "../Applications/Application Loader.app/Contents/MacOS/itms",
158
+ "../Applications/Application Loader.app/Contents/itms"
134
159
  ].each do |path|
135
- result = File.join(self.xcode_path, path)
160
+ result = File.expand_path(File.join(self.xcode_path, path))
136
161
  return result if File.exist?(result)
137
162
  end
138
163
  UI.user_error!("Could not find transporter at #{self.xcode_path}. Please make sure you set the correct path to your Xcode installation.")
@@ -1,5 +1,6 @@
1
1
  require 'pty'
2
2
  require 'shellwords'
3
+ require 'fileutils'
3
4
  require 'credentials_manager/account_manager'
4
5
 
5
6
  module FastlaneCore
@@ -11,7 +12,8 @@ module FastlaneCore
11
12
  class TransporterTransferError < StandardError
12
13
  end
13
14
 
14
- class ItunesTransporter
15
+ # Base class for executing the iTMSTransporter
16
+ class TransporterExecutor
15
17
  ERROR_REGEX = />\s*ERROR:\s+(.+)/
16
18
  WARNING_REGEX = />\s*WARN:\s+(.+)/
17
19
  OUTPUT_REGEX = />\s+(.+)/
@@ -21,93 +23,13 @@ module FastlaneCore
21
23
 
22
24
  private_constant :ERROR_REGEX, :WARNING_REGEX, :OUTPUT_REGEX, :RETURN_VALUE_REGEX, :SKIP_ERRORS
23
25
 
24
- # This will be called from the Deliverfile, and disables the logging of the transporter output
25
- def self.hide_transporter_output
26
- @hide_transporter_output = true
27
-
28
- @hide_transporter_output = false if $verbose
29
- end
30
-
31
- # Returns a new instance of the iTunesTransporter.
32
- # If no username or password given, it will be taken from
33
- # the #{CredentialsManager::AccountManager}
34
- def initialize(user = nil, password = nil)
35
- data = CredentialsManager::AccountManager.new(user: user, password: password)
36
- @user = data.user
37
- @password = data.password
38
- end
39
-
40
- # Downloads the latest version of the app metadata package from iTC.
41
- # @param app_id [Integer] The unique App ID
42
- # @param dir [String] the path in which the package file should be stored
43
- # @return (Bool) True if everything worked fine
44
- # @raise [Deliver::TransporterTransferError] when something went wrong
45
- # when transfering
46
- def download(app_id, dir = nil)
47
- dir ||= "/tmp"
48
-
49
- UI.message("Going to download app metadata from iTunes Connect")
50
- command = build_download_command(@user, @password, app_id, dir)
51
- UI.verbose(build_download_command(@user, 'YourPassword', app_id, dir)) if $verbose
52
-
53
- result = execute_transporter(command)
54
-
55
- itmsp_path = File.join(dir, "#{app_id}.itmsp")
56
- if result and File.directory? itmsp_path
57
- UI.success("Successfully downloaded the latest package from iTunes Connect.")
58
- else
59
- handle_error(@password)
60
- end
61
-
62
- result
63
- end
64
-
65
- # Uploads the modified package back to iTunes Connect
66
- # @param app_id [Integer] The unique App ID
67
- # @param dir [String] the path in which the package file is located
68
- # @return (Bool) True if everything worked fine
69
- # @raise [Deliver::TransporterTransferError] when something went wrong
70
- # when transfering
71
- def upload(app_id, dir)
72
- dir = File.join(dir, "#{app_id}.itmsp")
73
-
74
- UI.message("Going to upload updated app to iTunes Connect")
75
- UI.success("This might take a few minutes, please don't interrupt the script")
76
-
77
- command = build_upload_command(@user, @password, dir)
78
- UI.verbose(build_upload_command(@user, 'YourPassword', dir)) if $verbose
26
+ def execute(command, hide_output)
27
+ return command if Helper.is_test?
79
28
 
80
- result = execute_transporter(command)
81
-
82
- if result
83
- UI.success("-" * 102)
84
- UI.success("Successfully uploaded package to iTunes Connect. It might take a few minutes until it's visible online.")
85
- UI.success("-" * 102)
86
-
87
- FileUtils.rm_rf(dir) unless Helper.is_test? # we don't need the package any more, since the upload was successful
88
- else
89
- handle_error(@password)
90
- end
91
-
92
- result
93
- end
94
-
95
- private
96
-
97
- def handle_error(password)
98
- # rubocop:disable Style/CaseEquality
99
- unless /^[0-9a-zA-Z\.\$\_]*$/ === password
100
- UI.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.")
101
- end
102
- # rubocop:enable Style/CaseEquality
103
- UI.error("Could not download/upload from iTunes Connect! It's probably related to your password or your internet connection.")
104
- end
105
-
106
- def execute_transporter(command)
107
29
  @errors = []
108
30
  @warnings = []
109
31
 
110
- if defined?@hide_transporter_output
32
+ if hide_output
111
33
  # Show a one time message instead
112
34
  UI.success("Waiting for iTunes Connect transporter to be finished.")
113
35
  UI.success("iTunes Transporter progress... this might take a few minutes...")
@@ -116,7 +38,7 @@ module FastlaneCore
116
38
  begin
117
39
  PTY.spawn(command) do |stdin, stdout, pid|
118
40
  stdin.each do |line|
119
- parse_line(line) # this is where the parsing happens
41
+ parse_line(line, hide_output) # this is where the parsing happens
120
42
  end
121
43
  end
122
44
  rescue => ex
@@ -136,7 +58,9 @@ module FastlaneCore
136
58
  true
137
59
  end
138
60
 
139
- def parse_line(line)
61
+ private
62
+
63
+ def parse_line(line, hide_output)
140
64
  # Taken from https://github.com/sshaw/itunes_store_transporter/blob/master/lib/itunes/store/transporter/output_parser.rb
141
65
 
142
66
  output_done = false
@@ -180,38 +104,43 @@ module FastlaneCore
180
104
  end
181
105
  end
182
106
 
183
- if !defined?@hide_transporter_output and line =~ OUTPUT_REGEX
107
+ if !hide_output and line =~ OUTPUT_REGEX
184
108
  # General logging for debug purposes
185
109
  unless output_done
186
110
  UI.verbose("[Transporter]: #{$1}")
187
111
  end
188
112
  end
189
113
  end
114
+ end
190
115
 
191
- def build_download_command(username, password, apple_id, destination = "/tmp")
116
+ # Generates commands and executes the iTMSTransporter through the shell script it provides by the same name
117
+ class ShellScriptTransporterExecutor < TransporterExecutor
118
+ def build_upload_command(username, password, source = "/tmp")
192
119
  [
193
120
  '"' + Helper.transporter_path + '"',
194
- "-m lookupMetadata",
121
+ "-m upload",
195
122
  "-u \"#{username}\"",
196
123
  "-p #{shell_escaped_password(password)}",
197
- "-apple_id #{apple_id}",
198
- "-destination '#{destination}'"
124
+ "-f '#{source}'",
125
+ ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"], # that's here, because the user might overwrite the -t option
126
+ "-t 'Signiant'",
127
+ "-k 100000"
199
128
  ].join(' ')
200
129
  end
201
130
 
202
- def build_upload_command(username, password, source = "/tmp")
131
+ def build_download_command(username, password, apple_id, destination = "/tmp")
203
132
  [
204
133
  '"' + Helper.transporter_path + '"',
205
- "-m upload",
134
+ "-m lookupMetadata",
206
135
  "-u \"#{username}\"",
207
136
  "-p #{shell_escaped_password(password)}",
208
- "-f '#{source}'",
209
- ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"], # that's here, because the user might overwrite the -t option
210
- "-t 'Signiant'",
211
- "-k 100000"
137
+ "-apple_id #{apple_id}",
138
+ "-destination '#{destination}'"
212
139
  ].join(' ')
213
140
  end
214
141
 
142
+ private
143
+
215
144
  def shell_escaped_password(password)
216
145
  # because the shell handles passwords with single-quotes incorrectly, use gsub to replace ShellEscape'd single-quotes of this form:
217
146
  # \'
@@ -227,4 +156,157 @@ module FastlaneCore
227
156
  "'" + password + "'"
228
157
  end
229
158
  end
159
+
160
+ # Generates commands and executes the iTMSTransporter by invoking its Java app directly, to avoid the crazy parameter
161
+ # escaping problems in its accompanying shell script.
162
+ class JavaTransporterExecutor < TransporterExecutor
163
+ def build_upload_command(username, password, source = "/tmp")
164
+ [
165
+ Helper.transporter_java_executable_path.shellescape,
166
+ "-Djava.ext.dirs=#{Helper.transporter_java_ext_dir.shellescape}",
167
+ '-XX:NewSize=2m',
168
+ '-Xms32m',
169
+ '-Xmx1024m',
170
+ '-Xms1024m',
171
+ '-Djava.awt.headless=true',
172
+ '-Dsun.net.http.retryPost=false',
173
+ "-classpath #{Helper.transporter_java_jar_path.shellescape}",
174
+ 'com.apple.transporter.Application',
175
+ '-m upload',
176
+ "-u #{username.shellescape}",
177
+ "-p #{password.shellescape}",
178
+ "-f #{source.shellescape}",
179
+ ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"], # that's here, because the user might overwrite the -t option
180
+ '-t Signiant',
181
+ '-k 100000',
182
+ '2>&1' # cause stderr to be written to stdout
183
+ ].compact.join(' ') # compact gets rid of the possibly nil ENV value
184
+ end
185
+
186
+ def build_download_command(username, password, apple_id, destination = "/tmp")
187
+ [
188
+ Helper.transporter_java_executable_path.shellescape,
189
+ "-Djava.ext.dirs=#{Helper.transporter_java_ext_dir.shellescape}",
190
+ '-XX:NewSize=2m',
191
+ '-Xms32m',
192
+ '-Xmx1024m',
193
+ '-Xms1024m',
194
+ '-Djava.awt.headless=true',
195
+ '-Dsun.net.http.retryPost=false',
196
+ "-classpath #{Helper.transporter_java_jar_path.shellescape}",
197
+ 'com.apple.transporter.Application',
198
+ '-m lookupMetadata',
199
+ "-u #{username.shellescape}",
200
+ "-p #{password.shellescape}",
201
+ "-apple_id #{apple_id.shellescape}",
202
+ "-destination #{destination.shellescape}",
203
+ '2>&1' # cause stderr to be written to stdout
204
+ ].join(' ')
205
+ end
206
+
207
+ def execute(command, hide_output)
208
+ # The Java command needs to be run starting in a working directory in the iTMSTransporter
209
+ # file area. The shell script takes care of changing directories over to there, but we'll
210
+ # handle it manually here for this strategy.
211
+ FileUtils.cd(Helper.itms_path) do
212
+ return super(command, hide_output)
213
+ end
214
+ end
215
+ end
216
+
217
+ class ItunesTransporter
218
+ # This will be called from the Deliverfile, and disables the logging of the transporter output
219
+ def self.hide_transporter_output
220
+ @hide_transporter_output = !$verbose
221
+ end
222
+
223
+ def self.hide_transporter_output?
224
+ @hide_transporter_output
225
+ end
226
+
227
+ # Returns a new instance of the iTunesTransporter.
228
+ # If no username or password given, it will be taken from
229
+ # the #{CredentialsManager::AccountManager}
230
+ def initialize(user = nil, password = nil, avoid_shell_script = false)
231
+ avoid_shell_script ||= !ENV['FASTLANE_EXPERIMENTAL_TRANSPORTER_AVOID_SHELL_SCRIPT'].nil?
232
+ data = CredentialsManager::AccountManager.new(user: user, password: password)
233
+
234
+ @user = data.user
235
+ @password = data.password
236
+ @transporter_executor = avoid_shell_script ? JavaTransporterExecutor.new : ShellScriptTransporterExecutor.new
237
+ end
238
+
239
+ # Downloads the latest version of the app metadata package from iTC.
240
+ # @param app_id [Integer] The unique App ID
241
+ # @param dir [String] the path in which the package file should be stored
242
+ # @return (Bool) True if everything worked fine
243
+ # @raise [Deliver::TransporterTransferError] when something went wrong
244
+ # when transfering
245
+ def download(app_id, dir = nil)
246
+ dir ||= "/tmp"
247
+
248
+ UI.message("Going to download app metadata from iTunes Connect")
249
+ command = @transporter_executor.build_download_command(@user, @password, app_id, dir)
250
+ UI.verbose(@transporter_executor.build_download_command(@user, 'YourPassword', app_id, dir))
251
+
252
+ result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?)
253
+ return result if Helper.is_test?
254
+
255
+ itmsp_path = File.join(dir, "#{app_id}.itmsp")
256
+ successful = result && File.directory?(itmsp_path)
257
+
258
+ if successful
259
+ UI.success("✅ Successfully downloaded the latest package from iTunes Connect to #{itmsp_path}")
260
+ else
261
+ handle_error(@password)
262
+ end
263
+
264
+ successful
265
+ end
266
+
267
+ # Uploads the modified package back to iTunes Connect
268
+ # @param app_id [Integer] The unique App ID
269
+ # @param dir [String] the path in which the package file is located
270
+ # @return (Bool) True if everything worked fine
271
+ # @raise [Deliver::TransporterTransferError] when something went wrong
272
+ # when transfering
273
+ def upload(app_id, dir)
274
+ dir = File.join(dir, "#{app_id}.itmsp")
275
+
276
+ UI.message("Going to upload updated app to iTunes Connect")
277
+ UI.success("This might take a few minutes, please don't interrupt the script")
278
+
279
+ command = @transporter_executor.build_upload_command(@user, @password, dir)
280
+
281
+ UI.verbose(@transporter_executor.build_upload_command(@user, 'YourPassword', dir))
282
+
283
+ result = @transporter_executor.execute(command, ItunesTransporter.hide_transporter_output?)
284
+
285
+ if result
286
+ UI.success("-" * 102)
287
+ UI.success("Successfully uploaded package to iTunes Connect. It might take a few minutes until it's visible online.")
288
+ UI.success("-" * 102)
289
+
290
+ FileUtils.rm_rf(dir) unless Helper.is_test? # we don't need the package any more, since the upload was successful
291
+ else
292
+ handle_error(@password)
293
+ end
294
+
295
+ result
296
+ end
297
+
298
+ private
299
+
300
+ def handle_error(password)
301
+ # rubocop:disable Style/CaseEquality
302
+ unless /^[0-9a-zA-Z\.\$\_]*$/ === password
303
+ UI.error([
304
+ "Password contains special characters, which may not be handled properly by iTMSTransporter.",
305
+ "If you experience problems uploading to iTunes Connect, please consider changing your password to something with only alphanumeric characters."
306
+ ].join(' '))
307
+ end
308
+ # rubocop:enable Style/CaseEquality
309
+ UI.error("Could not download/upload from iTunes Connect! It's probably related to your password or your internet connection.")
310
+ end
311
+ end
230
312
  end
@@ -1,3 +1,3 @@
1
1
  module FastlaneCore
2
- VERSION = "0.41.0".freeze
2
+ VERSION = "0.41.1".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane_core
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.41.0
4
+ version: 0.41.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-31 00:00:00.000000000 Z
11
+ date: 2016-04-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -399,7 +399,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
399
399
  version: '0'
400
400
  requirements: []
401
401
  rubyforge_project:
402
- rubygems_version: 2.4.8
402
+ rubygems_version: 2.4.5.1
403
403
  signing_key:
404
404
  specification_version: 4
405
405
  summary: Contains all shared code/dependencies of the fastlane.tools