fastlane_core 0.9.2 → 0.10.0

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: 7a48aa42d30f71cc7c58d5d68c67490a38bfb8de
4
- data.tar.gz: 3eee24f17bccfa4027c22789a43cb6fa5acd4463
3
+ metadata.gz: f8b0ac651f60fbd9ab9eda7a9842a524de056726
4
+ data.tar.gz: 25b61598ef0442e59fb1f3356f1ef9935dd8a780
5
5
  SHA512:
6
- metadata.gz: 070d7472451929a304fd66af537435af89245197529ebc258d76ecbcf26df9653d7e61baca02af94b7e025f3b8ae205f5413d6e1143852271c8c8628c393fd79
7
- data.tar.gz: c444b6ceab4590c0b53d962cf411126247560fdc863d8852b5afdb8df0380df506590b470d1751611efd3e39dd410c877cbc3c0f407c8e522757fb6e56c3528f
6
+ metadata.gz: 12022fab57b9c45321648fbe1493e59ed605829af2bd75eb3067f32ad5b37e834cd3f74baef12c95164f9f8cccf39ffe58c83df9f955ce33c9a524f30e8ec6b4
7
+ data.tar.gz: a53ebc857fead387a86b07385772121d705f77ce929513bcfc74a2c9df9bec5ceee30b052f622507520c144b8ed37b6b3cdb79493c2def2f7ed0bac8ff778e17
data/lib/fastlane_core.rb CHANGED
@@ -6,6 +6,8 @@ require 'fastlane_core/update_checker'
6
6
  require 'fastlane_core/languages'
7
7
  require 'fastlane_core/itunes_search_api'
8
8
  require 'fastlane_core/cert_checker'
9
+ require 'fastlane_core/ipa_file_analyser'
10
+ require 'fastlane_core/itunes_transporter'
9
11
 
10
12
  # Third Party code
11
13
  require 'colored'
@@ -0,0 +1,46 @@
1
+ require 'zip'
2
+
3
+ module FastlaneCore
4
+ class IpaFileAnalyser
5
+
6
+ # Fetches the app identifier (e.g. com.facebook.Facebook) from the given ipa file.
7
+ def self.fetch_app_identifier(path)
8
+ plist = IpaFileAnalyser.fetch_info_plist_file(path)
9
+ return plist['CFBundleIdentifier'] if plist
10
+ return nil
11
+ end
12
+
13
+ # Fetches the app version from the given ipa file.
14
+ def self.fetch_app_version(path)
15
+ plist = IpaFileAnalyser.fetch_info_plist_file(path)
16
+ return plist['CFBundleShortVersionString'] if plist
17
+ return nil
18
+ end
19
+
20
+ def self.fetch_info_plist_file(path)
21
+ Zip::File.open(path) do |zipfile|
22
+ zipfile.each do |file|
23
+ if file.name.include?'.plist' and not ['.bundle', '.framework'].any? { |a| file.name.include?a }
24
+ # We can not be completely sure, that's the correct plist file, so we have to try
25
+ begin
26
+ # The XML file has to be properly unpacked first
27
+ tmp_path = "/tmp/deploytmp.plist"
28
+ File.write(tmp_path, zipfile.read(file))
29
+ system("plutil -convert xml1 #{tmp_path}")
30
+ result = Plist::parse_xml(tmp_path)
31
+ File.delete(tmp_path)
32
+
33
+ if result['CFBundleIdentifier'] or result['CFBundleVersion']
34
+ return result
35
+ end
36
+ rescue
37
+ # We don't really care, look for another XML file
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ nil
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,208 @@
1
+ require 'pty'
2
+ require 'shellwords'
3
+ require 'credentials_manager/password_manager'
4
+
5
+
6
+ module FastlaneCore
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
+
29
+ @@hide_transporter_output = false if $verbose
30
+ end
31
+
32
+ # Returns a new instance of the iTunesTransporter.
33
+ # If no username or password given, it will be taken from
34
+ # the #{CredentialsManager::PasswordManager}
35
+ def initialize(user = nil, password = nil)
36
+ @user = (user || CredentialsManager::PasswordManager.shared_manager.username)
37
+ @password = (password || CredentialsManager::PasswordManager.shared_manager.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
+ Helper.log.info "Going to download app metadata from iTunesConnect"
50
+ command = build_download_command(@user, @password, app_id, dir)
51
+ Helper.log.debug 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
+ 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_id [Integer] The unique App ID
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
+ def upload(app_id, dir)
75
+ dir = File.join(dir, "#{app_id}.itmsp")
76
+
77
+ Helper.log.info "Going to upload updated app to iTunesConnect"
78
+ Helper.log.info "This might take a few minutes, please don't interrupt the script".green
79
+
80
+ command = build_upload_command(@user, @password, dir)
81
+ Helper.log.debug build_upload_command(@user, 'YourPassword', dir) if $verbose
82
+
83
+ result = execute_transporter(command)
84
+
85
+ if result
86
+ Helper.log.info(("-" * 102).green)
87
+ Helper.log.info("Successfully uploaded package to iTunesConnect. It might take a few minutes until it's visible online.".green)
88
+ Helper.log.info(("-" * 102).green)
89
+
90
+ FileUtils.rm_rf(dir) unless Helper.is_test? # we don't need the package any more, since the upload was successful
91
+ end
92
+
93
+ result
94
+ end
95
+
96
+ private
97
+ def execute_transporter(command)
98
+ @errors = []
99
+ @warnings = []
100
+
101
+ if defined?@@hide_transporter_output
102
+ # Show a one time message instead
103
+ Helper.log.info "Waiting for iTunes Connect transporter to be finished.".green
104
+ Helper.log.info "iTunes Transporter progress... this might take a few minutes...".green
105
+ end
106
+
107
+ begin
108
+ PTY.spawn(command) do |stdin, stdout, pid|
109
+ stdin.each do |line|
110
+ parse_line(line) # this is where the parsing happens
111
+ end
112
+ end
113
+ rescue => ex
114
+ Helper.log.fatal(ex.to_s)
115
+ @errors << ex.to_s
116
+ end
117
+
118
+ if @warnings.count > 0
119
+ Helper.log.warn(@warnings.join("\n"))
120
+ end
121
+
122
+ if @errors.count > 0
123
+ Helper.log.error(@errors.join("\n"))
124
+ return false
125
+ end
126
+
127
+ true
128
+ end
129
+
130
+ def parse_line(line)
131
+ # Taken from https://github.com/sshaw/itunes_store_transporter/blob/master/lib/itunes/store/transporter/output_parser.rb
132
+
133
+ output_done = false
134
+
135
+ re = Regexp.union(SKIP_ERRORS)
136
+ if line.match(re)
137
+ # Those lines will not be handle like errors or warnings
138
+
139
+ elsif line =~ ERROR_REGEX
140
+ @errors << $1
141
+ Helper.log.error "[Transporter Error Output]: #{$1}".red
142
+
143
+ # Check if it's a login error
144
+ if $1.include?"Your Apple ID or password was entered incorrectly" or
145
+ $1.include?"This Apple ID has been locked for security reasons"
146
+
147
+ CredentialsManager::PasswordManager.shared_manager.password_seems_wrong unless Helper.is_test?
148
+ elsif $1.include?"Redundant Binary Upload. There already exists a binary upload with build"
149
+ Helper.log.fatal $1
150
+ Helper.log.fatal "You have to change the build number of your app to upload your ipa file"
151
+ end
152
+
153
+ output_done = true
154
+ elsif line =~ WARNING_REGEX
155
+ @warnings << $1
156
+ Helper.log.warn "[Transporter Warning Output]: #{$1}".yellow
157
+ output_done = true
158
+ end
159
+
160
+ if line =~ RETURN_VALUE_REGEX
161
+ if $1.to_i != 0
162
+ Helper.log.fatal "Transporter transfer failed.".red
163
+ Helper.log.warn(@warnings.join("\n").yellow)
164
+ Helper.log.error(@errors.join("\n").red)
165
+ raise "Return status of iTunes Transporter was #{$1}: #{@errors.join('\n')}".red
166
+ else
167
+ Helper.log.info "iTunes Transporter successfully finished its job".green
168
+ end
169
+ end
170
+
171
+ if not defined?@@hide_transporter_output and line =~ OUTPUT_REGEX
172
+ # General logging for debug purposes
173
+ unless output_done
174
+ Helper.log.debug "[Transporter]: #{$1}"
175
+ end
176
+ end
177
+ end
178
+
179
+ def build_download_command(username, password, apple_id, destination = "/tmp")
180
+ [
181
+ '"' + Helper.transporter_path + '"',
182
+ "-m lookupMetadata",
183
+ "-u \"#{username}\"",
184
+ "-p '#{escaped_password(password)}'",
185
+ "-apple_id #{apple_id}",
186
+ "-destination '#{destination}'"
187
+ ].join(' ')
188
+ end
189
+
190
+ def build_upload_command(username, password, source = "/tmp")
191
+ [
192
+ '"' + Helper.transporter_path + '"',
193
+ "-m upload",
194
+ "-u \"#{username}\"",
195
+ "-p '#{escaped_password(password)}'",
196
+ "-f '#{source}'",
197
+ ENV["DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS"], # that's here, because the user might overwrite the -t option
198
+ "-t 'Signiant'",
199
+ "-k 100000"
200
+ ].join(' ')
201
+ end
202
+
203
+ def escaped_password(password)
204
+ Shellwords.escape(password)
205
+ end
206
+
207
+ end
208
+ end
@@ -1,15 +1,16 @@
1
- require 'open-uri'
1
+ require 'excon'
2
2
 
3
3
  module FastlaneCore
4
4
  # Verifies, the user runs the latest version of this gem
5
5
  class UpdateChecker
6
-
7
6
  # This web service is fully open source: https://github.com/fastlane/refresher
8
7
  UPDATE_URL = "https://fastlane-refresher.herokuapp.com/"
9
8
 
10
9
  def self.start_looking_for_update(gem_name)
11
10
  return if Helper.is_test?
12
11
  return if ENV["FASTLANE_SKIP_UPDATE_CHECK"]
12
+
13
+ @start_time = Time.now
13
14
 
14
15
  Thread.new do
15
16
  begin
@@ -19,15 +20,32 @@ module FastlaneCore
19
20
  end
20
21
  end
21
22
 
22
- def self.show_update_status(gem_name, current_version)
23
+ def self.server_results
24
+ @@results ||= {}
25
+ end
26
+
27
+ def self.update_available?(gem_name, current_version)
23
28
  latest = server_results[gem_name]
24
- if latest and Gem::Version.new(latest) > Gem::Version.new(current_version)
25
- show_update_message(gem_name, latest, current_version)
29
+ return (latest and Gem::Version.new(latest) > Gem::Version.new(current_version))
30
+ end
31
+
32
+ def self.show_update_status(gem_name, current_version)
33
+ t = Thread.new do
34
+ begin
35
+ finished_running(gem_name)
36
+ rescue
37
+ end
26
38
  end
39
+
40
+ if update_available?(gem_name, current_version)
41
+ show_update_message(gem_name, current_version)
42
+ end
43
+
44
+ t.join(3)
27
45
  end
28
46
 
29
- def self.show_update_message(gem_name, available, current_version)
30
- v = fetch_latest(gem_name)
47
+ def self.show_update_message(gem_name, current_version)
48
+ available = server_results[gem_name]
31
49
  puts ""
32
50
  puts '#######################################################################'.green
33
51
  puts "# #{gem_name} #{available} is available. You are on #{current_version}.".green
@@ -37,30 +55,19 @@ module FastlaneCore
37
55
  puts '#######################################################################'.green
38
56
  end
39
57
 
40
- def self.server_results
41
- @@results ||= {}
42
- end
43
-
44
- # Legacy Code:
45
- #
46
- # Is a new official release available (this does not include pre-releases)
47
- def self.update_available?(gem_name, current_version)
48
- begin
49
- latest = fetch_latest(gem_name)
50
- if latest and Gem::Version.new(latest) > Gem::Version.new(current_version)
51
- return true
52
- end
53
- rescue => ex
54
- Helper.log.error("Could not check if '#{gem_name}' is up to date.")
55
- end
56
- return false
57
- end
58
-
59
- # Relevant code
60
58
  def self.fetch_latest(gem_name)
61
59
  url = UPDATE_URL + gem_name
62
60
  url += "?ci=1" if Helper.is_ci?
63
- JSON.parse(open(url).read)["version"]
61
+ JSON.parse(Excon.post(url).body).fetch("version", nil)
62
+ end
63
+
64
+ def self.finished_running(gem_name)
65
+ time = (Time.now - @start_time).to_i
66
+
67
+ url = UPDATE_URL + "time/#{gem_name}"
68
+ url += "?time=#{time}"
69
+ url += "&ci=1" if Helper.is_ci?
70
+ output = Excon.post(url)
64
71
  end
65
72
  end
66
73
  end
@@ -1,3 +1,3 @@
1
1
  module FastlaneCore
2
- VERSION = "0.9.2"
2
+ VERSION = "0.10.0"
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.9.2
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-06 00:00:00.000000000 Z
11
+ date: 2015-07-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - "~>"
109
109
  - !ruby/object:Gem::Version
110
110
  version: 0.45.0
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubyzip
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: 1.1.6
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: 1.1.6
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: credentials_manager
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -280,11 +294,13 @@ files:
280
294
  - lib/fastlane_core/developer_center/developer_center_helper.rb
281
295
  - lib/fastlane_core/developer_center/developer_center_login.rb
282
296
  - lib/fastlane_core/helper.rb
297
+ - lib/fastlane_core/ipa_file_analyser.rb
283
298
  - lib/fastlane_core/itunes_connect/itunes_connect.rb
284
299
  - lib/fastlane_core/itunes_connect/itunes_connect_apple_id.rb
285
300
  - lib/fastlane_core/itunes_connect/itunes_connect_helper.rb
286
301
  - lib/fastlane_core/itunes_connect/itunes_connect_login.rb
287
302
  - lib/fastlane_core/itunes_search_api.rb
303
+ - lib/fastlane_core/itunes_transporter.rb
288
304
  - lib/fastlane_core/languages.rb
289
305
  - lib/fastlane_core/update_checker.rb
290
306
  - lib/fastlane_core/version.rb