blob: cb0ca998c0418765085a0239a03e2b31cd025c9a (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
# frozen_string_literal: true
# rubocop:disable Style/SignalException
module Tooling
module Danger
module AnalyticsInstrumentation
METRIC_DIRS = %w[lib/gitlab/usage/metrics/instrumentations ee/lib/gitlab/usage/metrics/instrumentations].freeze
APPROVED_LABEL = 'analytics instrumentation::approved'
REVIEW_LABEL = 'analytics instrumentation::review pending'
CHANGED_FILES_MESSAGE = <<~MSG
For the following files, a review from the [Data team and Analytics Instrumentation team](https://gitlab.com/groups/gitlab-org/analytics-section/analytics-instrumentation/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
Please check the ~"analytics instrumentation" [Service Ping guide](https://docs.gitlab.com/ee/development/service_ping/) or the [Snowplow guide](https://docs.gitlab.com/ee/development/snowplow/).
For MR review guidelines, see the [Internal Analytics review guidelines](https://docs.gitlab.com/ee/development/internal_analytics/review_guidelines.html).
%<changed_files>s
MSG
CHANGED_SCOPE_MESSAGE = <<~MSG
The following metrics could be affected by the modified scopes and require ~"analytics instrumentation" review:
MSG
CHANGED_USAGE_DATA_MESSAGE = <<~MSG
Notice that implementing metrics directly in usage_data.rb has been deprecated.
Please use [Instrumentation Classes](https://docs.gitlab.com/ee/development/service_ping/metrics_instrumentation.html) instead.
MSG
WORKFLOW_LABELS = [
APPROVED_LABEL,
REVIEW_LABEL
].freeze
def check!
analytics_instrumentation_paths_to_review = helper.changes.by_category(:analytics_instrumentation).files
labels_to_add = missing_labels
return if analytics_instrumentation_paths_to_review.empty? || skip_review?
warn format(CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(analytics_instrumentation_paths_to_review)) unless has_approved_label?
helper.labels_to_add.concat(labels_to_add) unless labels_to_add.empty?
end
def check_affected_scopes!
metric_scope_list = metric_scope_affected
return if metric_scope_list.empty?
warn CHANGED_SCOPE_MESSAGE + convert_to_table(metric_scope_list)
helper.labels_to_add.concat(missing_labels) unless missing_labels.empty?
end
def check_usage_data_insertions!
usage_data_changes = helper.changed_lines("lib/gitlab/usage_data.rb")
return if usage_data_changes.none? { |change| change.start_with?("+") }
warn format(CHANGED_USAGE_DATA_MESSAGE)
end
private
def convert_to_table(items)
message = "Scope | Affected files |\n"
message += "--- | ----- |\n"
items.each_key do |scope|
affected_files = items[scope]
message += "`#{scope}`| `#{affected_files[0]}` |\n"
affected_files[1..]&.each do |file_name|
message += " | `#{file_name}` |\n"
end
end
message
end
def metric_scope_affected
select_models(helper.modified_files).each_with_object(Hash.new { |h, k| h[k] = [] }) do |file_name, matched_files|
helper.changed_lines(file_name).each do |mod_line, _i|
next unless /^\+\s+scope :\w+/.match?(mod_line)
affected_scope = mod_line.match(/:\w+/)
next if affected_scope.nil?
affected_class = File.basename(file_name, '.rb').split('_').map(&:capitalize).join
scope_name = "#{affected_class}.#{affected_scope[0][1..]}"
each_metric do |metric_def|
next unless File.read(metric_def).include?("relation { #{scope_name}")
matched_files[scope_name].push(metric_def)
end
end
end
end
def select_models(files)
files.select do |f|
f.start_with?('app/models/', 'ee/app/models/')
end
end
def each_metric(&block)
METRIC_DIRS.each do |dir|
Dir.glob(File.join(dir, '*.rb')).each(&block)
end
end
def missing_labels
return [] unless helper.ci?
labels = []
labels << 'analytics instrumentation' unless helper.mr_has_labels?('analytics instrumentation')
labels << REVIEW_LABEL unless has_workflow_labels?
labels
end
def has_approved_label?
helper.mr_labels.include?(APPROVED_LABEL)
end
def skip_review?
helper.mr_has_labels?('growth experiment')
end
def has_workflow_labels?
(WORKFLOW_LABELS & helper.mr_labels).any?
end
end
end
end
|