fastlane 2.62.0.beta.20171016010004 → 2.62.0.beta.20171017010003
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/fastlane/lib/fastlane/fast_file.rb +32 -12
- data/fastlane/lib/fastlane/lane_manager.rb +2 -2
- data/fastlane/lib/fastlane/runner.rb +22 -15
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane_core/lib/fastlane_core.rb +18 -0
- data/fastlane_core/lib/fastlane_core/analytics/action_completion_context.rb +29 -0
- data/fastlane_core/lib/fastlane_core/analytics/action_launch_context.rb +34 -0
- data/fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb +50 -0
- data/fastlane_core/lib/fastlane_core/analytics/analytics_ingester_client.rb +45 -0
- data/fastlane_core/lib/fastlane_core/analytics/analytics_session.rb +201 -0
- data/fastlane_core/lib/fastlane_core/analytics/app_identifier_guesser.rb +64 -0
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +20 -7
- data/fastlane_core/lib/fastlane_core/update_checker/update_checker.rb +3 -57
- metadata +8 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f14604abb941543613b3505e11bf099dccccf4ab
|
4
|
+
data.tar.gz: f62ef3b052d856ec84948d52521321455fedb5be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
221
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
284
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
|
@@ -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
|
-
|
64
|
-
|
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
|
-
|
125
|
+
FastlaneCore.session.finalize_session
|
120
126
|
end
|
121
127
|
end
|
122
128
|
|
123
|
-
def
|
124
|
-
|
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
|
-
|
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
|
-
|
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/
|
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
|
-
|
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.
|
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-
|
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
|