fastlane 2.62.0.beta.20171016010004 → 2.62.0.beta.20171017010003

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e48c62acc810d151573862aff11a7c34322cd3b2
4
- data.tar.gz: 5545f680d045794bb9b749febff528085f748533
3
+ metadata.gz: f14604abb941543613b3505e11bf099dccccf4ab
4
+ data.tar.gz: f62ef3b052d856ec84948d52521321455fedb5be
5
5
  SHA512:
6
- metadata.gz: 6199c80457f0b54f09cc8a86527525ae0f5ffb1ecd375521e04cc2951e21ae116d1dfb1778aaedec59f95c3ec3c4e696371491f77757ce7bcbb6015cfd2ee724
7
- data.tar.gz: 5b2b29177b098219e07f06d10c05605ac3d5237ae471b25cf2d353cca1c381f7a1db1240ce958750c42570b9569792b4260838ef64ce723883f050918b6c8914
6
+ metadata.gz: 03f1513c1a01cc9a51aeb3642907bc93c868f8e1764cee102046f1b4dee88489e6a86ea0e076d8203794d916bc612a31b2198ddd5ffca9a0d88710df27742481
7
+ data.tar.gz: 0318818369814716e8b1f4403276ce4b4d7673e49a2b6ae2aaddda43638ddf89a35d5a61cab5b1656e6e118ebbe1d9e3a8c320d2e830eee39eff0141f4118a00
@@ -150,10 +150,6 @@ module Fastlane
150
150
  # @!group Other things
151
151
  #####################################################
152
152
 
153
- def collector
154
- runner.collector
155
- end
156
-
157
153
  # Is the given key a platform block or a lane?
158
154
  def is_platform_block?(key)
159
155
  UI.crash!('No key given') unless key
@@ -217,8 +213,13 @@ module Fastlane
217
213
  actions_path = File.join(File.expand_path("..", path), 'actions')
218
214
  Fastlane::Actions.load_external_actions(actions_path) if File.directory?(actions_path)
219
215
 
220
- collector.did_launch_action(:import)
221
- parse(File.read(path), path)
216
+ action_launched('import')
217
+
218
+ return_value = parse(File.read(path), path)
219
+
220
+ action_completed('import', status: FastlaneCore::ActionCompletionStatus::SUCCESS)
221
+
222
+ return return_value
222
223
  end
223
224
 
224
225
  # @param url [String] The git URL to clone the repository from
@@ -230,7 +231,7 @@ module Fastlane
230
231
  Actions.execute_action('import_from_git') do
231
232
  require 'tmpdir'
232
233
 
233
- collector.did_launch_action(:import_from_git)
234
+ action_launched('import_from_git')
234
235
 
235
236
  # Checkout the repo
236
237
  repo_name = url.split("/").last
@@ -258,7 +259,11 @@ module Fastlane
258
259
  # We don't care about a failure here, as local actions are optional
259
260
  end
260
261
 
261
- import(File.join(clone_folder, path))
262
+ return_value = import(File.join(clone_folder, path))
263
+
264
+ action_completed('import_from_git', status: FastlaneCore::ActionCompletionStatus::SUCCESS)
265
+
266
+ return return_value
262
267
  end
263
268
  end
264
269
  end
@@ -272,21 +277,36 @@ module Fastlane
272
277
  # Overwrite this, since there is already a 'say' method defined in the Ruby standard library
273
278
  value ||= yield
274
279
  Actions.execute_action('say') do
275
- collector.did_launch_action(:say)
276
- Fastlane::Actions::SayAction.run([value])
280
+ action_launched('say')
281
+ return_value = Fastlane::Actions::SayAction.run([value])
282
+ action_completed('say', status: FastlaneCore::ActionCompletionStatus::SUCCESS)
283
+ return return_value
277
284
  end
278
285
  end
279
286
 
280
287
  def puts(value)
281
288
  # Overwrite this, since there is already a 'puts' method defined in the Ruby standard library
282
289
  value ||= yield if block_given?
283
- collector.did_launch_action(:puts)
284
- Fastlane::Actions::PutsAction.run([value])
290
+
291
+ action_launched('puts')
292
+ return_value = Fastlane::Actions::PutsAction.run([value])
293
+ action_completed('puts', status: FastlaneCore::ActionCompletionStatus::SUCCESS)
294
+ return return_value
285
295
  end
286
296
 
287
297
  def test(params = {})
288
298
  # Overwrite this, since there is already a 'test' method defined in the Ruby standard library
289
299
  self.runner.try_switch_to_lane(:test, [params])
290
300
  end
301
+
302
+ def action_launched(action_name)
303
+ action_launch_context = FastlaneCore::ActionLaunchContext.context_for_action_name(action_name, args: ARGV)
304
+ FastlaneCore.session.action_launched(launch_context: action_launch_context)
305
+ end
306
+
307
+ def action_completed(action_name, status: nil)
308
+ completion_context = FastlaneCore::ActionCompletionContext.context_for_action_name(action_name, args: ARGV, status: status)
309
+ FastlaneCore.session.action_completed(completion_context: completion_context)
310
+ end
291
311
  end
292
312
  end
@@ -38,6 +38,8 @@ module Fastlane
38
38
 
39
39
  platform, lane = choose_lane(ff, platform) unless lane
40
40
 
41
+ FastlaneCore.session.is_fastfile = true
42
+
41
43
  # xcodeproj has a bug in certain versions that causes it to change directories
42
44
  # and not return to the original working directory
43
45
  # https://github.com/CocoaPods/Xcodeproj/issues/426
@@ -76,8 +78,6 @@ module Fastlane
76
78
 
77
79
  # All the finishing up that needs to be done
78
80
  def self.finish_fastlane(ff, duration, error)
79
- ff.runner.did_finish
80
-
81
81
  # Finished with all the lanes
82
82
  Fastlane::JUnitGenerator.generate(Fastlane::Actions.executed_actions)
83
83
  print_table(Fastlane::Actions.executed_actions)
@@ -197,7 +197,10 @@ module Fastlane
197
197
 
198
198
  # Actually switch lane now
199
199
  self.current_lane = new_lane
200
- collector.did_launch_action(:lane_switch)
200
+
201
+ launch_context = FastlaneCore::ActionLaunchContext.context_for_action_name('lane_switch', args: ARGV)
202
+ FastlaneCore.session.action_launched(launch_context: launch_context)
203
+
201
204
  result = block.call(parameters.first || {}) # to always pass a hash
202
205
  self.current_lane = original_lane
203
206
 
@@ -218,11 +221,12 @@ module Fastlane
218
221
  custom_dir ||= ".."
219
222
  end
220
223
 
221
- collector.did_launch_action(method_sym)
222
-
223
224
  verify_supported_os(method_sym, class_ref)
224
225
 
225
226
  begin
227
+ launch_context = FastlaneCore::ActionLaunchContext.context_for_action_name(method_sym.to_s, args: ARGV)
228
+ FastlaneCore.session.action_launched(launch_context: launch_context)
229
+
226
230
  Dir.chdir(custom_dir) do # go up from the fastlane folder, to the project folder
227
231
  # If another action is calling this action, we shouldn't show it in the summary
228
232
  # (see https://github.com/fastlane/fastlane/issues/4546)
@@ -249,7 +253,11 @@ module Fastlane
249
253
  end
250
254
 
251
255
  class_ref.runner = self # needed to call another action form an action
252
- class_ref.run(arguments)
256
+ return_value = class_ref.run(arguments)
257
+
258
+ action_completed(method_sym.to_s, status: FastlaneCore::ActionCompletionStatus::SUCCESS)
259
+
260
+ return return_value
253
261
  end
254
262
  end
255
263
  rescue Interrupt => e
@@ -258,17 +266,25 @@ module Fastlane
258
266
  raise e
259
267
  rescue FastlaneCore::Interface::FastlaneError => e # user_error!
260
268
  FastlaneCore::CrashReporter.report_crash(exception: e)
261
- collector.did_raise_error(method_sym) if e.fastlane_should_report_metrics?
269
+ action_completed(method_sym.to_s, status: FastlaneCore::ActionCompletionStatus::USER_ERROR, exception: e)
262
270
  raise e
263
271
  rescue Exception => e # rubocop:disable Lint/RescueException
264
272
  # high chance this is actually FastlaneCore::Interface::FastlaneCrash, but can be anything else
265
273
  # Catches all exceptions, since some plugins might use system exits to get out
266
274
  FastlaneCore::CrashReporter.report_crash(exception: e)
267
- collector.did_crash(method_sym) if e.fastlane_should_report_metrics?
275
+
276
+ action_completed(method_sym.to_s, status: FastlaneCore::ActionCompletionStatus::FAILED, exception: e)
268
277
  raise e
269
278
  end
270
279
  end
271
280
 
281
+ def action_completed(action_name, status: nil, exception: nil)
282
+ if exception.nil? || exception.fastlane_should_report_metrics?
283
+ action_completion_context = FastlaneCore::ActionCompletionContext.context_for_action_name(action_name, args: ARGV, status: status)
284
+ FastlaneCore.session.action_completed(completion_context: action_completion_context)
285
+ end
286
+ end
287
+
272
288
  def execute_flow_block(block, current_platform, lane, parameters)
273
289
  # Call the platform specific block and default back to the general one
274
290
  block[current_platform].call(lane, parameters) if block[current_platform] && current_platform
@@ -287,15 +303,6 @@ module Fastlane
287
303
  end
288
304
  end
289
305
 
290
- def collector
291
- @collector ||= ActionCollector.new
292
- end
293
-
294
- # Fastfile was finished executing
295
- def did_finish
296
- collector.did_finish
297
- end
298
-
299
306
  # Called internally to setup the runner object
300
307
  #
301
308
 
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.62.0.beta.20171016010004'.freeze
2
+ VERSION = '2.62.0.beta.20171017010003'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  MINIMUM_XCODE_RELEASE = "7.0".freeze
5
5
  end
@@ -40,6 +40,11 @@ require 'fastlane_core/ui/errors/fastlane_crash'
40
40
  require 'fastlane_core/ui/errors/fastlane_shell_error'
41
41
  require 'fastlane_core/ui/errors/fastlane_common_error'
42
42
  require 'fastlane_core/test_parser'
43
+ require 'fastlane_core/analytics/action_completion_context'
44
+ require 'fastlane_core/analytics/action_launch_context'
45
+ require 'fastlane_core/analytics/analytics_event_builder'
46
+ require 'fastlane_core/analytics/analytics_ingester_client'
47
+ require 'fastlane_core/analytics/analytics_session'
43
48
 
44
49
  # Third Party code
45
50
  require 'colored'
@@ -51,6 +56,19 @@ require 'fastlane_core/ui/fastlane_runner' # monkey patch
51
56
  module FastlaneCore
52
57
  ROOT = Pathname.new(File.expand_path('../..', __FILE__))
53
58
 
59
+ # Session is used to report usage metrics.
60
+ # If you opt out, we will not send anything.
61
+ # You can confirm this by observing how we use the environment variable: FASTLANE_OPT_OUT_USAGE
62
+ # Specifically, in AnalyticsSession.finalize_session
63
+ # Learn more at https://github.com/fastlane/fastlane#metrics
64
+ def self.session
65
+ @session ||= AnalyticsSession.new
66
+ end
67
+
68
+ def self.reset_session
69
+ @session = nil
70
+ end
71
+
54
72
  # A directory that's being used to user-wide fastlane configs
55
73
  # This directory is also used for the bundled fastlane
56
74
  # Since we don't want to access FastlaneCore from spaceship
@@ -0,0 +1,29 @@
1
+ module FastlaneCore
2
+ class ActionCompletionStatus
3
+ SUCCESS = 'success'
4
+ FAILED = 'failed' # fastlane crashes unrelated to user_error!
5
+ USER_ERROR = 'user_error' # Anytime a user_error! is triggered
6
+ INTERRUPTED = 'interrupted'
7
+ end
8
+
9
+ class ActionCompletionContext
10
+ attr_accessor :p_hash
11
+ attr_accessor :action_name
12
+ attr_accessor :status
13
+
14
+ def initialize(p_hash: nil, action_name: nil, status: nil)
15
+ @p_hash = p_hash
16
+ @action_name = action_name
17
+ @status = status
18
+ end
19
+
20
+ def self.context_for_action_name(action_name, args: nil, status: nil)
21
+ app_id_guesser = FastlaneCore::AppIdentifierGuesser.new(args: args)
22
+ return self.new(
23
+ action_name: action_name,
24
+ p_hash: app_id_guesser.p_hash,
25
+ status: status
26
+ )
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,34 @@
1
+ require 'fastlane_core/helper'
2
+
3
+ module FastlaneCore
4
+ class ActionLaunchContext
5
+ UNKNOWN_P_HASH = 'unknown'
6
+
7
+ attr_accessor :action_name
8
+ attr_accessor :p_hash
9
+ attr_accessor :platform
10
+
11
+ def initialize(action_name: nil, p_hash: UNKNOWN_P_HASH, platform: nil)
12
+ @action_name = action_name
13
+ @p_hash = p_hash
14
+ @platform = platform
15
+ end
16
+
17
+ def self.context_for_action_name(action_name, args: nil)
18
+ app_id_guesser = FastlaneCore::AppIdentifierGuesser.new(args: args)
19
+ return self.new(
20
+ action_name: action_name,
21
+ p_hash: app_id_guesser.p_hash,
22
+ platform: app_id_guesser.platform
23
+ )
24
+ end
25
+
26
+ def build_tool_version
27
+ if platform == :android
28
+ return 'android'
29
+ else
30
+ return "Xcode #{Helper.xcode_version}"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,50 @@
1
+ module FastlaneCore
2
+ class AnalyticsEventBuilder
3
+ attr_accessor :base_hash
4
+ attr_accessor :action_name
5
+
6
+ def initialize(oauth_app_name: nil, p_hash: nil, session_id: nil, action_name: nil, timestamp_millis: (Time.now.to_f * 1000).to_i)
7
+ @action_name = action_name
8
+ @base_hash = {
9
+ event_source: {
10
+ oauth_app_name: oauth_app_name,
11
+ product: 'fastlane'
12
+ },
13
+ actor: {
14
+ name: p_hash,
15
+ detail: session_id
16
+ },
17
+ millis_since_epoch: timestamp_millis,
18
+ version: 1
19
+ }
20
+ end
21
+
22
+ def launched_event(primary_target_hash: nil, secondary_target_hash: nil)
23
+ return new_event(
24
+ stage: 'launched',
25
+ primary_target_hash: primary_target_hash,
26
+ secondary_target_hash: secondary_target_hash
27
+ )
28
+ end
29
+
30
+ def completed_event(primary_target_hash: nil, secondary_target_hash: nil)
31
+ return new_event(
32
+ stage: 'completed',
33
+ primary_target_hash: primary_target_hash,
34
+ secondary_target_hash: secondary_target_hash
35
+ )
36
+ end
37
+
38
+ def new_event(stage: nil, primary_target_hash: nil, secondary_target_hash: nil)
39
+ raise 'Need at least a primary_target_hash' if primary_target_hash.nil?
40
+ event = base_hash.dup
41
+ event[:action] = {
42
+ name: stage,
43
+ detail: action_name
44
+ }
45
+ event[:primary_target] = primary_target_hash
46
+ event[:secondary_target] = secondary_target_hash unless secondary_target_hash.nil?
47
+ return event
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,45 @@
1
+ module FastlaneCore
2
+ class AnalyticsIngesterClient
3
+ def post_events(events)
4
+ unless Helper.test?
5
+ fork do
6
+ send_request(json: { analytics: events }.to_json)
7
+ end
8
+ end
9
+ return true
10
+ end
11
+
12
+ def send_request(json: nil, retries: 2)
13
+ post_request(body: json)
14
+ rescue
15
+ retries -= 1
16
+ retry if retries >= 0
17
+ end
18
+
19
+ def post_request(body: nil)
20
+ if ENV['METRICS_DEBUG']
21
+ write_json(body)
22
+ end
23
+ url = ENV["FASTLANE_METRICS_URL"] || "https://fastlane-metrics.fabric.io"
24
+
25
+ require 'faraday'
26
+ connection = Faraday.new(url) do |conn|
27
+ conn.adapter Faraday.default_adapter
28
+ if ENV['METRICS_DEBUG']
29
+ conn.proxy = "https://127.0.0.1:8888"
30
+ conn.ssl[:verify_mode] = OpenSSL::SSL::VERIFY_NONE
31
+ end
32
+ end
33
+ connection.post do |req|
34
+ req.url '/public'
35
+ req.headers['Content-Type'] = 'application/json'
36
+ req.body = body
37
+ end
38
+ end
39
+
40
+ # This method is only for debugging purposes
41
+ def write_json(body)
42
+ File.write("#{ENV['HOME']}/Desktop/mock_analytics-#{Time.now.to_i}.json", body)
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,201 @@
1
+ require 'fastlane_core/analytics/analytics_ingester_client'
2
+
3
+ module FastlaneCore
4
+ class AnalyticsSession
5
+ attr_accessor :session_id
6
+ attr_accessor :client
7
+ attr_accessor :events
8
+ attr_accessor :fastfile_id
9
+ attr_accessor :is_fastfile
10
+ alias fastfile? is_fastfile
11
+
12
+ # make this a method so that we can override it in monkey patches
13
+ def oauth_app_name
14
+ return 'fastlane_v2'
15
+ end
16
+
17
+ def initialize(analytics_ingester_client: AnalyticsIngesterClient.new)
18
+ require 'securerandom'
19
+ @session_id = SecureRandom.uuid
20
+ @client = analytics_ingester_client
21
+ @events = []
22
+ @is_fastfile = false
23
+ end
24
+
25
+ def backfill_p_hashes(p_hash: nil)
26
+ return if p_hash.nil? || p_hash == ActionLaunchContext::UNKNOWN_P_HASH || @events.count == 0
27
+ @events.reverse_each do |event|
28
+ # event[:actor][:name] is the field in which we store the p_hash
29
+ # to be sent to analytics ingester.
30
+ # If they are nil, we want to fill them in until we reach
31
+ # an event that already has a p_hash.
32
+ if event[:actor][:name].nil? || event[:actor][:name] == ActionLaunchContext::UNKNOWN_P_HASH
33
+ event[:actor][:name] = p_hash
34
+ else
35
+ break
36
+ end
37
+ end
38
+ end
39
+
40
+ def action_launched(launch_context: nil)
41
+ backfill_p_hashes(p_hash: launch_context.p_hash)
42
+
43
+ builder = AnalyticsEventBuilder.new(
44
+ oauth_app_name: oauth_app_name,
45
+ p_hash: launch_context.p_hash,
46
+ session_id: session_id,
47
+ action_name: launch_context.action_name
48
+ )
49
+
50
+ @events << builder.launched_event(
51
+ primary_target_hash: {
52
+ name: 'fastlane_version',
53
+ detail: fastlane_version
54
+ }
55
+ )
56
+
57
+ @events << builder.launched_event(
58
+ primary_target_hash: {
59
+ name: 'install_method',
60
+ detail: install_method
61
+ }
62
+ )
63
+
64
+ @events << builder.launched_event(
65
+ primary_target_hash: {
66
+ name: 'operating_system',
67
+ detail: operating_system
68
+ },
69
+ secondary_target_hash: {
70
+ name: 'version',
71
+ detail: operating_system_version
72
+ }
73
+ )
74
+
75
+ @events << builder.launched_event(
76
+ primary_target_hash: {
77
+ name: 'build_tool_version',
78
+ detail: launch_context.build_tool_version
79
+ }
80
+ )
81
+
82
+ @events << builder.launched_event(
83
+ primary_target_hash: {
84
+ name: 'ci',
85
+ detail: ci?.to_s
86
+ }
87
+ )
88
+
89
+ @events << builder.launched_event(
90
+ primary_target_hash: {
91
+ name: 'fastfile',
92
+ detail: fastfile?.to_s
93
+ },
94
+ secondary_target_hash: {
95
+ name: 'fastfile_id',
96
+ detail: fastfile_id.to_s
97
+ }
98
+ )
99
+
100
+ @events << builder.launched_event(
101
+ primary_target_hash: {
102
+ name: 'platform',
103
+ detail: launch_context.platform.to_s
104
+ }
105
+ )
106
+
107
+ @events << builder.launched_event(
108
+ primary_target_hash: {
109
+ name: 'ruby_version',
110
+ detail: ruby_version
111
+ }
112
+ )
113
+ end
114
+
115
+ def is_fastfile=(value)
116
+ if value
117
+ # If true, update all of the events to reflect
118
+ # that the execution is running within a Fastfile context.
119
+ # We don't want to update if this is false because once we
120
+ # detect a true value, that is the one to be trusted
121
+ @events.reverse_each do |event|
122
+ event[:primary_target][:name] == 'fastfile' ? event[:primary_target][:detail] = value.to_s : next
123
+ end
124
+ end
125
+ @is_fastfile = value
126
+ end
127
+
128
+ def action_completed(completion_context: nil)
129
+ backfill_p_hashes(p_hash: completion_context.p_hash)
130
+
131
+ builder = AnalyticsEventBuilder.new(
132
+ oauth_app_name: oauth_app_name,
133
+ p_hash: completion_context.p_hash,
134
+ session_id: session_id,
135
+ action_name: completion_context.action_name
136
+ )
137
+
138
+ @events << builder.completed_event(
139
+ primary_target_hash: {
140
+ name: 'status',
141
+ detail: completion_context.status
142
+ }
143
+ )
144
+ end
145
+
146
+ def finalize_session
147
+ # If our users want to opt out of usage metrics, don't post the events.
148
+ # Learn more at https://github.com/fastlane/fastlane#metrics
149
+ return if FastlaneCore::Env.truthy?("FASTLANE_OPT_OUT_USAGE")
150
+
151
+ client.post_events(@events)
152
+ end
153
+
154
+ def fastlane_version
155
+ return Fastlane::VERSION
156
+ end
157
+
158
+ def ruby_version
159
+ patch_level = RUBY_PATCHLEVEL == 0 ? nil : "p#{RUBY_PATCHLEVEL}"
160
+ return "#{RUBY_VERSION}#{patch_level}"
161
+ end
162
+
163
+ def operating_system
164
+ return "macOS" if RUBY_PLATFORM.downcase.include?("darwin")
165
+ return "Windows" if RUBY_PLATFORM.downcase.include?("mswin")
166
+ return "Linux" if RUBY_PLATFORM.downcase.include?("linux")
167
+ return "Unknown"
168
+ end
169
+
170
+ def install_method
171
+ if Helper.rubygems?
172
+ return 'gem'
173
+ elsif Helper.bundler?
174
+ return 'bundler'
175
+ elsif Helper.mac_app?
176
+ return 'mac_app'
177
+ elsif Helper.contained_fastlane?
178
+ return 'standalone'
179
+ elsif Helper.homebrew?
180
+ return 'homebrew'
181
+ else
182
+ return 'unknown'
183
+ end
184
+ end
185
+
186
+ def ci?
187
+ return Helper.is_ci?
188
+ end
189
+
190
+ def operating_system_version
191
+ os = self.operating_system
192
+ case os
193
+ when "macOS"
194
+ return `SW_VERS -productVersion`.strip
195
+ else
196
+ # Need to test in Windows and Linux... not sure this is enough
197
+ return Gem::Platform.local.version
198
+ end
199
+ end
200
+ end
201
+ end
@@ -0,0 +1,64 @@
1
+ require 'fastlane_core/android_package_name_guesser'
2
+ require 'fastlane_core/ios_app_identifier_guesser'
3
+
4
+ module FastlaneCore
5
+ class AppIdentifierGuesser
6
+ attr_accessor :args
7
+ attr_accessor :gem_name
8
+ attr_accessor :platform
9
+ attr_accessor :p_hash
10
+ attr_accessor :app_id
11
+
12
+ def initialize(args: nil, gem_name: 'fastlane')
13
+ @args = args
14
+ @gem_name = gem_name
15
+
16
+ @app_id = android_app_identifier(args, gem_name)
17
+ @platform = nil # since have a state in-between runs
18
+ if @app_id
19
+ @platform = :android
20
+ else
21
+ @app_id = ios_app_identifier(args)
22
+ @platform = :ios if @app_id
23
+ end
24
+
25
+ @p_hash = generate_p_hash(@app_id)
26
+ end
27
+
28
+ # To not count the same projects multiple time for the number of launches
29
+ # Learn more at https://github.com/fastlane/fastlane#metrics
30
+ # Use the `FASTLANE_OPT_OUT_USAGE` variable to opt out
31
+ # The resulting value is e.g. ce12f8371df11ef6097a83bdf2303e4357d6f5040acc4f76019489fa5deeae0d
32
+ def generate_p_hash(app_id)
33
+ unless !FastlaneCore::Env.truthy?("FASTLANE_OPT_OUT_USAGE") && !app_id.nil?
34
+ return nil
35
+ end
36
+
37
+ require 'credentials_manager'
38
+ return Digest::SHA256.hexdigest("p#{app_id}fastlan3_SAlt") # hashed + salted the bundle identifier
39
+ rescue
40
+ return nil # we don't want this method to cause a crash
41
+ end
42
+
43
+ # (optional) Returns the app identifier for the current tool
44
+ def ios_app_identifier(args)
45
+ return FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier(args)
46
+ rescue
47
+ nil # we don't want this method to cause a crash
48
+ end
49
+
50
+ # (optional) Returns the app identifier for the current tool
51
+ # supply and screengrab use different param names and env variable patterns so we have to special case here
52
+ # example:
53
+ # fastlane supply --skip_upload_screenshots -a beta -p com.test.app should return com.test.app
54
+ # screengrab -a com.test.app should return com.test.app
55
+ def android_app_identifier(args, gem_name)
56
+ app_identifier = FastlaneCore::AndroidPackageNameGuesser.guess_package_name(gem_name, args)
57
+
58
+ # Add Android prefix to prevent collisions if there is an iOS app with the same identifier
59
+ app_identifier ? "android_project_#{app_identifier}" : nil
60
+ rescue
61
+ nil # we don't want this method to cause a crash
62
+ end
63
+ end
64
+ end
@@ -60,8 +60,13 @@ module Commander
60
60
  FastlaneCore::UI.user_error!("fastlane requires a minimum version of Xcode #{Fastlane::MINIMUM_XCODE_RELEASE}, please upgrade and make sure to use `sudo xcode-select -s /Applications/Xcode.app`")
61
61
  end
62
62
 
63
- collector.did_launch_action(@program[:name])
64
- run_active_command
63
+ action_launch_context = FastlaneCore::ActionLaunchContext.context_for_action_name(@program[:name], args: ARGV)
64
+ FastlaneCore.session.action_launched(launch_context: action_launch_context)
65
+
66
+ return_value = run_active_command
67
+
68
+ action_completed(@program[:name], status: FastlaneCore::ActionCompletionStatus::SUCCESS)
69
+ return return_value
65
70
  rescue InvalidCommandError => e
66
71
  # calling `abort` makes it likely that tests stop without failing, so
67
72
  # we'll disable that during tests.
@@ -76,6 +81,7 @@ module Commander
76
81
  if FastlaneCore::Globals.verbose?
77
82
  raise e
78
83
  else
84
+ action_completed(@program[:name], status: FastlaneCore::ActionCompletionStatus::INTERRUPTED, exception: e)
79
85
  puts "\nCancelled... use --verbose to show the stack trace"
80
86
  end
81
87
  rescue \
@@ -116,12 +122,15 @@ module Commander
116
122
  rescue => e # high chance this is actually FastlaneCore::Interface::FastlaneCrash, but can be anything else
117
123
  rescue_unknown_error(e)
118
124
  ensure
119
- collector.did_finish
125
+ FastlaneCore.session.finalize_session
120
126
  end
121
127
  end
122
128
 
123
- def collector
124
- @collector ||= FastlaneCore::ToolCollector.new
129
+ def action_completed(action_name, status: nil, exception: nil)
130
+ if exception.nil? || exception.fastlane_should_report_metrics?
131
+ action_completion_context = FastlaneCore::ActionCompletionContext.context_for_action_name(action_name, args: ARGV, status: status)
132
+ FastlaneCore.session.action_completed(completion_context: action_completion_context)
133
+ end
125
134
  end
126
135
 
127
136
  def rescue_file_error(e)
@@ -145,12 +154,15 @@ module Commander
145
154
 
146
155
  def rescue_unknown_error(e)
147
156
  FastlaneCore::CrashReporter.report_crash(exception: e)
148
- collector.did_crash(@program[:name]) if e.fastlane_should_report_metrics?
157
+
158
+ action_completed(@program[:name], status: FastlaneCore::ActionCompletionStatus::FAILED, exception: e)
159
+
149
160
  handle_unknown_error!(e)
150
161
  end
151
162
 
152
163
  def rescue_fastlane_error(e)
153
- collector.did_raise_error(@program[:name]) if e.fastlane_should_report_metrics?
164
+ action_completed(@program[:name], status: FastlaneCore::ActionCompletionStatus::USER_ERROR, exception: e)
165
+
154
166
  show_github_issues(e.message) if e.show_github_issues
155
167
  FastlaneCore::CrashReporter.report_crash(exception: e)
156
168
  display_user_error!(e, e.message)
@@ -247,6 +259,7 @@ module Commander
247
259
  reraise_formatted!(e, message)
248
260
  else
249
261
  # without stack trace
262
+ action_completed(@program[:name], status: FastlaneCore::ActionCompletionStatus::USER_ERROR, exception: e)
250
263
  abort "\n[!] #{message}".red
251
264
  end
252
265
  end
@@ -2,8 +2,7 @@ require 'excon'
2
2
  require 'digest'
3
3
 
4
4
  require 'fastlane_core/update_checker/changelog'
5
- require 'fastlane_core/ios_app_identifier_guesser'
6
- require 'fastlane_core/android_package_name_guesser'
5
+ require 'fastlane_core/analytics/app_identifier_guesser'
7
6
 
8
7
  module FastlaneCore
9
8
  # Verifies, the user runs the latest version of this gem
@@ -121,64 +120,11 @@ module FastlaneCore
121
120
  "https://rubygems.org/api/v1/gems/#{gem_name}.json"
122
121
  end
123
122
 
124
- # (optional) Returns the app identifier for the current tool
125
- def self.ios_app_identifier(args)
126
- return FastlaneCore::IOSAppIdentifierGuesser.guess_app_identifier(args)
127
- rescue
128
- nil # we don't want this method to cause a crash
129
- end
130
-
131
- # (optional) Returns the app identifier for the current tool
132
- # supply and screengrab use different param names and env variable patterns so we have to special case here
133
- # example:
134
- # fastlane supply --skip_upload_screenshots -a beta -p com.test.app should return com.test.app
135
- # screengrab -a com.test.app should return com.test.app
136
- def self.android_app_identifier(args, gem_name)
137
- app_identifier = FastlaneCore::AndroidPackageNameGuesser.guess_package_name(gem_name, args)
138
-
139
- # Add Android prefix to prevent collisions if there is an iOS app with the same identifier
140
- app_identifier ? "android_project_#{app_identifier}" : nil
141
- rescue
142
- nil # we don't want this method to cause a crash
143
- end
144
-
145
- # To not count the same projects multiple time for the number of launches
146
- # Learn more at https://github.com/fastlane/fastlane#metrics
147
- # Use the `FASTLANE_OPT_OUT_USAGE` variable to opt out
148
- # The resulting value is e.g. ce12f8371df11ef6097a83bdf2303e4357d6f5040acc4f76019489fa5deeae0d
149
- def self.p_hash(args, gem_name)
150
- return nil if FastlaneCore::Env.truthy?("FASTLANE_OPT_OUT_USAGE")
151
- require 'credentials_manager'
152
-
153
- app_identifier = app_id(args, gem_name)
154
-
155
- if app_identifier
156
- return Digest::SHA256.hexdigest("p#{app_identifier}fastlan3_SAlt") # hashed + salted the bundle identifier
157
- end
158
-
159
- return nil
160
- rescue
161
- return nil
162
- end
163
-
164
- def self.app_id(args, gem_name)
165
- # check if this is an android project first because some of the same params exist for iOS and Android tools
166
- app_identifier = android_app_identifier(args, gem_name)
167
- @platform = nil # since have a state in-between runs
168
- if app_identifier
169
- @platform = :android
170
- else
171
- app_identifier = ios_app_identifier(args)
172
- @platform = :ios if app_identifier
173
- end
174
- return app_identifier
175
- end
176
-
177
123
  def self.send_launch_analytic_events_for(gem_name)
178
124
  return if FastlaneCore::Env.truthy?("FASTLANE_OPT_OUT_USAGE")
179
-
180
125
  ci = Helper.is_ci?.to_s
181
- project_hash = p_hash(ARGV, gem_name)
126
+ app_id_guesser = FastlaneCore::AppIdentifierGuesser.new(args: ARGV, gem_name: gem_name)
127
+ project_hash = app_id_guesser.p_hash
182
128
  p_hash = project_hash if project_hash
183
129
  platform = @platform if @platform # this has to be called after `p_hash`
184
130
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.62.0.beta.20171016010004
4
+ version: 2.62.0.beta.20171017010003
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felix Krause
@@ -15,7 +15,7 @@ authors:
15
15
  autorequire:
16
16
  bindir: bin
17
17
  cert_chain: []
18
- date: 2017-10-16 00:00:00.000000000 Z
18
+ date: 2017-10-17 00:00:00.000000000 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: slack-notifier
@@ -1171,6 +1171,12 @@ files:
1171
1171
  - fastlane_core/README.md
1172
1172
  - fastlane_core/lib/assets/XMLTemplate.xml.erb
1173
1173
  - fastlane_core/lib/fastlane_core.rb
1174
+ - fastlane_core/lib/fastlane_core/analytics/action_completion_context.rb
1175
+ - fastlane_core/lib/fastlane_core/analytics/action_launch_context.rb
1176
+ - fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb
1177
+ - fastlane_core/lib/fastlane_core/analytics/analytics_ingester_client.rb
1178
+ - fastlane_core/lib/fastlane_core/analytics/analytics_session.rb
1179
+ - fastlane_core/lib/fastlane_core/analytics/app_identifier_guesser.rb
1174
1180
  - fastlane_core/lib/fastlane_core/android_package_name_guesser.rb
1175
1181
  - fastlane_core/lib/fastlane_core/build_watcher.rb
1176
1182
  - fastlane_core/lib/fastlane_core/cert_checker.rb