gitlab-dangerfiles 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.gitlab-ci.yml +43 -0
- data/.gitlab/merge_request_templates/Release.md +35 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +7 -0
- data/Guardfile +70 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/fixtures/emojis/aliases.json +542 -0
- data/fixtures/emojis/digests.json +12553 -0
- data/gitlab-dangerfiles.gemspec +38 -0
- data/lib/danger/changelog.rb +39 -0
- data/lib/danger/helper.rb +260 -0
- data/lib/danger/roulette.rb +135 -0
- data/lib/danger/sidekiq_queues.rb +37 -0
- data/lib/gitlab-dangerfiles.rb +1 -0
- data/lib/gitlab/Dangerfile +1 -0
- data/lib/gitlab/dangerfiles.rb +40 -0
- data/lib/gitlab/dangerfiles/bundle_size/Dangerfile +38 -0
- data/lib/gitlab/dangerfiles/ce_ee_vue_templates/Dangerfile +56 -0
- data/lib/gitlab/dangerfiles/changelog/Dangerfile +90 -0
- data/lib/gitlab/dangerfiles/changes_size/Dangerfile +17 -0
- data/lib/gitlab/dangerfiles/commit_linter.rb +226 -0
- data/lib/gitlab/dangerfiles/commit_messages/Dangerfile +135 -0
- data/lib/gitlab/dangerfiles/database/Dangerfile +67 -0
- data/lib/gitlab/dangerfiles/documentation/Dangerfile +29 -0
- data/lib/gitlab/dangerfiles/duplicate_yarn_dependencies/Dangerfile +29 -0
- data/lib/gitlab/dangerfiles/emoji_checker.rb +45 -0
- data/lib/gitlab/dangerfiles/eslint/Dangerfile +31 -0
- data/lib/gitlab/dangerfiles/frozen_string/Dangerfile +28 -0
- data/lib/gitlab/dangerfiles/karma/Dangerfile +51 -0
- data/lib/gitlab/dangerfiles/metadata/Dangerfile +50 -0
- data/lib/gitlab/dangerfiles/popen.rb +55 -0
- data/lib/gitlab/dangerfiles/prettier/Dangerfile +41 -0
- data/lib/gitlab/dangerfiles/roulette/Dangerfile +97 -0
- data/lib/gitlab/dangerfiles/sidekiq_queues/Dangerfile +27 -0
- data/lib/gitlab/dangerfiles/specs/Dangerfile +42 -0
- data/lib/gitlab/dangerfiles/tasks.rb +19 -0
- data/lib/gitlab/dangerfiles/teammate.rb +106 -0
- data/lib/gitlab/dangerfiles/telemetry/Dangerfile +32 -0
- data/lib/gitlab/dangerfiles/utility_css/Dangerfile +51 -0
- data/lib/gitlab/dangerfiles/version.rb +5 -0
- metadata +191 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "open3"
|
5
|
+
|
6
|
+
module Gitlab
|
7
|
+
module Dangerfiles
|
8
|
+
class Popen
|
9
|
+
Result = Struct.new(:cmd, :stdout, :stderr, :status, :duration)
|
10
|
+
|
11
|
+
# Returns [stdout + stderr, status]
|
12
|
+
def popen(cmd, path = nil, vars = {}, &block)
|
13
|
+
result = popen_with_detail(cmd, path, vars, &block)
|
14
|
+
|
15
|
+
["#{result.stdout}#{result.stderr}", result.status&.exitstatus]
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns Result
|
19
|
+
def popen_with_detail(cmd, path = nil, vars = {})
|
20
|
+
unless cmd.is_a?(Array)
|
21
|
+
raise "System commands must be given as an array of strings"
|
22
|
+
end
|
23
|
+
|
24
|
+
path ||= Dir.pwd
|
25
|
+
vars["PWD"] = path
|
26
|
+
options = { chdir: path }
|
27
|
+
|
28
|
+
unless File.directory?(path)
|
29
|
+
FileUtils.mkdir_p(path)
|
30
|
+
end
|
31
|
+
|
32
|
+
cmd_stdout = ""
|
33
|
+
cmd_stderr = ""
|
34
|
+
cmd_status = nil
|
35
|
+
start = Time.now
|
36
|
+
|
37
|
+
Open3.popen3(vars, *cmd, options) do |stdin, stdout, stderr, wait_thr|
|
38
|
+
# stderr and stdout pipes can block if stderr/stdout aren't drained: https://bugs.ruby-lang.org/issues/9082
|
39
|
+
# Mimic what Ruby does with capture3: https://github.com/ruby/ruby/blob/1ec544695fa02d714180ef9c34e755027b6a2103/lib/open3.rb#L257-L273
|
40
|
+
out_reader = Thread.new { stdout.read }
|
41
|
+
err_reader = Thread.new { stderr.read }
|
42
|
+
|
43
|
+
yield(stdin) if block_given?
|
44
|
+
stdin.close
|
45
|
+
|
46
|
+
cmd_stdout = out_reader.value
|
47
|
+
cmd_stderr = err_reader.value
|
48
|
+
cmd_status = wait_thr.value
|
49
|
+
end
|
50
|
+
|
51
|
+
Result.new(cmd, cmd_stdout, cmd_stderr, cmd_status, Time.now - start)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
def get_prettier_files(files)
|
4
|
+
files.select do |file|
|
5
|
+
file.end_with?('.js', '.scss', '.vue')
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
prettier_candidates = get_prettier_files(helper.all_changed_files)
|
10
|
+
|
11
|
+
return if prettier_candidates.empty?
|
12
|
+
|
13
|
+
unpretty = `node_modules/prettier/bin-prettier.js --list-different #{prettier_candidates.join(" ")}`
|
14
|
+
.split(/$/)
|
15
|
+
.map(&:strip)
|
16
|
+
.reject(&:empty?)
|
17
|
+
|
18
|
+
return if unpretty.empty?
|
19
|
+
|
20
|
+
warn 'This merge request changed frontend files without pretty printing them.'
|
21
|
+
|
22
|
+
if helper.ci?
|
23
|
+
markdown(<<~MARKDOWN)
|
24
|
+
## Pretty print Frontend files
|
25
|
+
|
26
|
+
The following files should have been pretty printed with `prettier`:
|
27
|
+
|
28
|
+
* #{unpretty.map { |path| "`#{path}`" }.join("\n* ")}
|
29
|
+
|
30
|
+
Please run
|
31
|
+
|
32
|
+
```
|
33
|
+
node_modules/.bin/prettier --write \\
|
34
|
+
#{unpretty.map { |path| " '#{path}'" }.join(" \\\n")}
|
35
|
+
```
|
36
|
+
|
37
|
+
Also consider auto-formatting [on-save].
|
38
|
+
|
39
|
+
[on-save]: https://docs.gitlab.com/ee/development/fe_guide/tooling.html#formatting-with-prettier
|
40
|
+
MARKDOWN
|
41
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
MESSAGE = <<MARKDOWN
|
6
|
+
## Reviewer roulette
|
7
|
+
|
8
|
+
Changes that require review have been detected! A merge request is normally
|
9
|
+
reviewed by both a reviewer and a maintainer in its primary category (e.g.
|
10
|
+
~frontend or ~backend), and by a maintainer in all other categories.
|
11
|
+
MARKDOWN
|
12
|
+
|
13
|
+
CATEGORY_TABLE_HEADER = <<MARKDOWN
|
14
|
+
|
15
|
+
To spread load more evenly across eligible reviewers, Danger has picked a candidate for each
|
16
|
+
review slot, based on their timezone. Feel free to
|
17
|
+
[override these selections](https://about.gitlab.com/handbook/engineering/projects/#gitlab)
|
18
|
+
if you think someone else would be better-suited, or the chosen person is unavailable.
|
19
|
+
|
20
|
+
To read more on how to use the reviewer roulette, please take a look at the
|
21
|
+
[Engineering workflow](https://about.gitlab.com/handbook/engineering/workflow/#basics)
|
22
|
+
and [code review guidelines](https://docs.gitlab.com/ee/development/code_review.html).
|
23
|
+
Please consider assigning a reviewer or maintainer who is a
|
24
|
+
[domain expert](https://about.gitlab.com/handbook/engineering/projects/#gitlab) in the area of the merge request.
|
25
|
+
|
26
|
+
Once you've decided who will review this merge request, mention them as you
|
27
|
+
normally would! Danger does not automatically notify them for you.
|
28
|
+
|
29
|
+
| Category | Reviewer | Maintainer |
|
30
|
+
| -------- | -------- | ---------- |
|
31
|
+
MARKDOWN
|
32
|
+
|
33
|
+
UNKNOWN_FILES_MESSAGE = <<MARKDOWN
|
34
|
+
|
35
|
+
These files couldn't be categorised, so Danger was unable to suggest a reviewer.
|
36
|
+
Please consider creating a merge request to
|
37
|
+
[add support](https://gitlab.com/gitlab-org/gitlab-dangerfiles/blob/master/lib/danger/helper.rb)
|
38
|
+
for them.
|
39
|
+
MARKDOWN
|
40
|
+
|
41
|
+
OPTIONAL_REVIEW_TEMPLATE = "%{role} review is optional for %{category}".freeze
|
42
|
+
NOT_AVAILABLE_TEMPLATE = 'No %{role} available'.freeze
|
43
|
+
TIMEZONE_EXPERIMENT = true
|
44
|
+
|
45
|
+
def mr_author
|
46
|
+
roulette.team.find { |person| person.username == gitlab.mr_author }
|
47
|
+
end
|
48
|
+
|
49
|
+
def note_for_category_role(spin, role)
|
50
|
+
if spin.optional_role == role
|
51
|
+
return OPTIONAL_REVIEW_TEMPLATE % { role: role.capitalize, category: helper.label_for_category(spin.category) }
|
52
|
+
end
|
53
|
+
|
54
|
+
spin.public_send(role)&.markdown_name(timezone_experiment: TIMEZONE_EXPERIMENT, author: mr_author) || NOT_AVAILABLE_TEMPLATE % { role: role } # rubocop:disable GitlabSecurity/PublicSend
|
55
|
+
end
|
56
|
+
|
57
|
+
def markdown_row_for_spin(spin)
|
58
|
+
reviewer_note = note_for_category_role(spin, :reviewer)
|
59
|
+
maintainer_note = note_for_category_role(spin, :maintainer)
|
60
|
+
|
61
|
+
"| #{helper.label_for_category(spin.category)} | #{reviewer_note} | #{maintainer_note} |"
|
62
|
+
end
|
63
|
+
|
64
|
+
changes = helper.changes_by_category
|
65
|
+
|
66
|
+
# Ignore any files that are known but uncategorized. Prompt for any unknown files
|
67
|
+
changes.delete(:none)
|
68
|
+
# To reinstate roulette for documentation, remove this line.
|
69
|
+
changes.delete(:docs)
|
70
|
+
categories = changes.keys - [:unknown]
|
71
|
+
|
72
|
+
# Ensure to spin for database reviewer/maintainer when ~database is applied (e.g. to review SQL queries)
|
73
|
+
categories << :database if gitlab.mr_labels.include?('database') && !categories.include?(:database)
|
74
|
+
|
75
|
+
if changes.any?
|
76
|
+
project = helper.project_name
|
77
|
+
branch_name = gitlab.mr_json['source_branch']
|
78
|
+
|
79
|
+
markdown(MESSAGE)
|
80
|
+
|
81
|
+
roulette_spins = roulette.spin(project, categories, branch_name, timezone_experiment: TIMEZONE_EXPERIMENT)
|
82
|
+
rows = roulette_spins.map do |spin|
|
83
|
+
# MR includes QA changes, but also other changes, and author isn't an SET
|
84
|
+
if spin.category == :qa && categories.size > 1 && !mr_author.reviewer?(project, spin.category, [])
|
85
|
+
spin.optional_role = :maintainer
|
86
|
+
end
|
87
|
+
|
88
|
+
spin.optional_role = :maintainer if spin.category == :test
|
89
|
+
|
90
|
+
markdown_row_for_spin(spin)
|
91
|
+
end
|
92
|
+
|
93
|
+
markdown(CATEGORY_TABLE_HEADER + rows.join("\n")) unless rows.empty?
|
94
|
+
|
95
|
+
unknown = changes.fetch(:unknown, [])
|
96
|
+
markdown(UNKNOWN_FILES_MESSAGE + helper.markdown_list(unknown)) unless unknown.empty?
|
97
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
SCALABILITY_REVIEW_MESSAGE = <<~MSG
|
4
|
+
## Sidekiq queue changes
|
5
|
+
|
6
|
+
This merge request contains changes to Sidekiq queues. Please follow the [documentation on changing a queue's urgency](https://docs.gitlab.com/ee/development/sidekiq_style_guide.html#changing-a-queues-urgency).
|
7
|
+
MSG
|
8
|
+
|
9
|
+
ADDED_QUEUES_MESSAGE = <<~MSG
|
10
|
+
These queues were added:
|
11
|
+
MSG
|
12
|
+
|
13
|
+
CHANGED_QUEUES_MESSAGE = <<~MSG
|
14
|
+
These queues had their attributes changed:
|
15
|
+
MSG
|
16
|
+
|
17
|
+
if sidekiq_queues.added_queue_names.any? || sidekiq_queues.changed_queue_names.any?
|
18
|
+
markdown(SCALABILITY_REVIEW_MESSAGE)
|
19
|
+
|
20
|
+
if sidekiq_queues.added_queue_names.any?
|
21
|
+
markdown(ADDED_QUEUES_MESSAGE + helper.markdown_list(sidekiq_queues.added_queue_names))
|
22
|
+
end
|
23
|
+
|
24
|
+
if sidekiq_queues.changed_queue_names.any?
|
25
|
+
markdown(CHANGED_QUEUES_MESSAGE + helper.markdown_list(sidekiq_queues.changed_queue_names))
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
NO_SPECS_LABELS = [
|
4
|
+
'backstage', # To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/222360.
|
5
|
+
'tooling',
|
6
|
+
'tooling::pipelines',
|
7
|
+
'tooling::workflow',
|
8
|
+
'documentation',
|
9
|
+
'QA'
|
10
|
+
].freeze
|
11
|
+
NO_NEW_SPEC_MESSAGE = <<~MSG
|
12
|
+
You've made some app changes, but didn't add any tests.
|
13
|
+
That's OK as long as you're refactoring existing code,
|
14
|
+
but please consider adding any of the %<labels>s labels.
|
15
|
+
MSG
|
16
|
+
EE_CHANGE_WITH_FOSS_SPEC_CHANGE_MESSAGE = <<~MSG
|
17
|
+
You've made some EE-specific changes, but only made changes to FOSS tests.
|
18
|
+
This could be a sign that you're testing an EE-specific behavior in a FOSS test.
|
19
|
+
|
20
|
+
Please make sure the spec files pass in AS-IF-FOSS mode either:
|
21
|
+
|
22
|
+
1. Locally with `FOSS_ONLY=1 bin/rspec -- %<spec_files>s`.
|
23
|
+
1. In the MR pipeline by verifying that the `rspec foss-impact` job has passed.
|
24
|
+
1. In the MR pipelines by including `RUN AS-IF-FOSS` in the MR title (you can do it with the ``/title %<mr_title>s [RUN AS-IF-FOSS]`` quick action) and start a new MR pipeline.
|
25
|
+
|
26
|
+
MSG
|
27
|
+
|
28
|
+
has_app_changes = helper.all_changed_files.grep(%r{\A(app|lib|db/(geo/)?(post_)?migrate)/}).any?
|
29
|
+
has_ee_app_changes = helper.all_changed_files.grep(%r{\Aee/(app|lib|db/(geo/)?(post_)?migrate)/}).any?
|
30
|
+
spec_changes = helper.all_changed_files.grep(%r{\Aspec/})
|
31
|
+
has_spec_changes = spec_changes.any?
|
32
|
+
has_ee_spec_changes = helper.all_changed_files.grep(%r{\Aee/spec/}).any?
|
33
|
+
new_specs_needed = (gitlab.mr_labels & NO_SPECS_LABELS).empty?
|
34
|
+
|
35
|
+
if (has_app_changes || has_ee_app_changes) && !(has_spec_changes || has_ee_spec_changes) && new_specs_needed
|
36
|
+
warn format(NO_NEW_SPEC_MESSAGE, labels: helper.labels_list(NO_SPECS_LABELS)), sticky: false
|
37
|
+
end
|
38
|
+
|
39
|
+
# The only changes outside `ee/` are in `spec/`
|
40
|
+
if has_ee_app_changes && has_spec_changes && !(has_app_changes || has_ee_spec_changes)
|
41
|
+
warn format(EE_CHANGE_WITH_FOSS_SPEC_CHANGE_MESSAGE, spec_files: spec_changes.join(" "), mr_title: gitlab.mr_json['title']), sticky: false
|
42
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
desc "Run local Danger rules"
|
4
|
+
task :danger_local do
|
5
|
+
require "gitlab/dangerfiles"
|
6
|
+
require "popen/danger/popen"
|
7
|
+
|
8
|
+
puts("#{Gitlab::Dangerfiles.local_warning_message}\n")
|
9
|
+
|
10
|
+
# _status will _always_ be 0, regardless of failure or success :(
|
11
|
+
output, _status = Gitlab::Dangerfiles::Popen.popen(%w{danger dry_run})
|
12
|
+
|
13
|
+
if output.empty?
|
14
|
+
puts(Gitlab::Dangerfiles.success_message)
|
15
|
+
else
|
16
|
+
puts(output)
|
17
|
+
exit(1)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitlab
|
4
|
+
module Dangerfiles
|
5
|
+
class Teammate
|
6
|
+
attr_reader :username, :name, :role, :projects, :available, :tz_offset_hours
|
7
|
+
|
8
|
+
# The options data are produced by https://gitlab.com/gitlab-org/gitlab-roulette/-/blob/master/lib/team_member.rb
|
9
|
+
def initialize(options = {})
|
10
|
+
@username = options["username"]
|
11
|
+
@name = options["name"]
|
12
|
+
@markdown_name = options["markdown_name"]
|
13
|
+
@role = options["role"]
|
14
|
+
@projects = options["projects"]
|
15
|
+
@available = options["available"]
|
16
|
+
@tz_offset_hours = options["tz_offset_hours"]
|
17
|
+
end
|
18
|
+
|
19
|
+
def in_project?(name)
|
20
|
+
projects&.has_key?(name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Traintainers also count as reviewers
|
24
|
+
def reviewer?(project, category, labels)
|
25
|
+
has_capability?(project, category, :reviewer, labels) ||
|
26
|
+
traintainer?(project, category, labels)
|
27
|
+
end
|
28
|
+
|
29
|
+
def traintainer?(project, category, labels)
|
30
|
+
has_capability?(project, category, :trainee_maintainer, labels)
|
31
|
+
end
|
32
|
+
|
33
|
+
def maintainer?(project, category, labels)
|
34
|
+
has_capability?(project, category, :maintainer, labels)
|
35
|
+
end
|
36
|
+
|
37
|
+
def markdown_name(timezone_experiment: false, author: nil)
|
38
|
+
return @markdown_name unless timezone_experiment
|
39
|
+
|
40
|
+
"#{@markdown_name} (#{utc_offset_text(author)})"
|
41
|
+
end
|
42
|
+
|
43
|
+
def local_hour
|
44
|
+
(Time.now.utc + tz_offset_hours * 3600).hour
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def floored_offset_hours
|
50
|
+
floored_offset = tz_offset_hours.floor(0)
|
51
|
+
|
52
|
+
floored_offset == tz_offset_hours ? floored_offset : tz_offset_hours
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def utc_offset_text(author = nil)
|
58
|
+
offset_text = if floored_offset_hours >= 0
|
59
|
+
"UTC+#{floored_offset_hours}"
|
60
|
+
else
|
61
|
+
"UTC#{floored_offset_hours}"
|
62
|
+
end
|
63
|
+
|
64
|
+
return offset_text unless author
|
65
|
+
|
66
|
+
"#{offset_text}, #{offset_diff_compared_to_author(author)}"
|
67
|
+
end
|
68
|
+
|
69
|
+
def offset_diff_compared_to_author(author)
|
70
|
+
diff = floored_offset_hours - author.floored_offset_hours
|
71
|
+
return "same timezone as `@#{author.username}`" if diff.zero?
|
72
|
+
|
73
|
+
ahead_or_behind = diff < 0 ? "behind" : "ahead"
|
74
|
+
pluralized_hours = pluralize(diff.abs, "hour", "hours")
|
75
|
+
|
76
|
+
"#{pluralized_hours} #{ahead_or_behind} `@#{author.username}`"
|
77
|
+
end
|
78
|
+
|
79
|
+
def has_capability?(project, category, kind, labels)
|
80
|
+
case category
|
81
|
+
when :test
|
82
|
+
area = role[/Software Engineer in Test(?:.*?, (\w+))/, 1]
|
83
|
+
|
84
|
+
area && labels.any?("devops::#{area.downcase}") if kind == :reviewer
|
85
|
+
when :engineering_productivity
|
86
|
+
return false unless role[/Engineering Productivity/]
|
87
|
+
return true if kind == :reviewer
|
88
|
+
|
89
|
+
capabilities(project).include?("#{kind} backend")
|
90
|
+
else
|
91
|
+
capabilities(project).include?("#{kind} #{category}")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def capabilities(project)
|
96
|
+
Array(projects.fetch(project, []))
|
97
|
+
end
|
98
|
+
|
99
|
+
def pluralize(count, singular, plural)
|
100
|
+
word = count == 1 || count.to_s =~ /^1(\.0+)?$/ ? singular : plural
|
101
|
+
|
102
|
+
"#{count || 0} #{word}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
TELEMETRY_CHANGED_FILES_MESSAGE = <<~MSG
|
4
|
+
For the following files, a review from the [Data team and Telemetry team](https://gitlab.com/groups/gitlab-org/growth/telemetry/engineers/-/group_members?with_inherited_permissions=exclude) is recommended
|
5
|
+
Please check the ~telemetry [guide](https://docs.gitlab.com/ee/development/telemetry/usage_ping.html) and reach out to @gitlab-org/growth/telemetry/engineers group for a review.
|
6
|
+
|
7
|
+
%<changed_files>s
|
8
|
+
|
9
|
+
MSG
|
10
|
+
|
11
|
+
tracking_files = [
|
12
|
+
'lib/gitlab/tracking.rb',
|
13
|
+
'spec/lib/gitlab/tracking_spec.rb',
|
14
|
+
'app/helpers/tracking_helper.rb',
|
15
|
+
'spec/helpers/tracking_helper_spec.rb',
|
16
|
+
'app/assets/javascripts/tracking.js',
|
17
|
+
'spec/frontend/tracking_spec.js'
|
18
|
+
]
|
19
|
+
|
20
|
+
usage_data_changed_files = git.modified_files.grep(%r{usage_data})
|
21
|
+
snowplow_events_changed_files = git.modified_files & tracking_files
|
22
|
+
|
23
|
+
changed_files = (usage_data_changed_files + snowplow_events_changed_files)
|
24
|
+
|
25
|
+
if changed_files.any?
|
26
|
+
warn format(TELEMETRY_CHANGED_FILES_MESSAGE, changed_files: helper.markdown_list(changed_files))
|
27
|
+
|
28
|
+
telemetry_labels = ['telemetry']
|
29
|
+
telemetry_labels << 'telemetry::review pending' unless helper.mr_has_labels?('telemetry::reviewed')
|
30
|
+
|
31
|
+
markdown(helper.prepare_labels_for_mr(telemetry_labels))
|
32
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
common = 'app/assets/stylesheets/framework/common.scss'
|
4
|
+
utilities = 'app/assets/stylesheets/utilities.scss'
|
5
|
+
|
6
|
+
def get_css_files(files, common_filepath, utilities_filepath)
|
7
|
+
files.select do |file|
|
8
|
+
file.include?(common_filepath) ||
|
9
|
+
file.include?(utilities_filepath)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
changed_util_files = get_css_files(helper.all_changed_files.to_a, common, utilities)
|
14
|
+
|
15
|
+
unless changed_util_files.empty?
|
16
|
+
|
17
|
+
markdown(<<~MARKDOWN)
|
18
|
+
## Changes to utility SCSS files
|
19
|
+
MARKDOWN
|
20
|
+
|
21
|
+
if changed_util_files.include?(common)
|
22
|
+
|
23
|
+
markdown(<<~MARKDOWN)
|
24
|
+
### Addition to `#{common}`
|
25
|
+
|
26
|
+
You have added a new rule to `#{common}`. Are you sure you need this rule?
|
27
|
+
|
28
|
+
If it is a component class shared across items, could it be added to the component as a utility class or to the component's stylesheet? If not, you can ignore this warning.
|
29
|
+
|
30
|
+
If it is a new utility class, is there another class that shares the same values in either this file or in `#{utilities}`? If not, please add it to `#{utilities}`, following the [Gitlab UI naming style](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss).
|
31
|
+
|
32
|
+
MARKDOWN
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
if changed_util_files.include?(utilities)
|
37
|
+
markdown(<<~MARKDOWN)
|
38
|
+
### Addition to `#{utilities}`
|
39
|
+
|
40
|
+
You have added a new rule to `#{utilities}`. Are you sure you need this rule?
|
41
|
+
|
42
|
+
If it is a component class shared across items, could it be added to the component as a utility class or to the component's stylesheet? If not, consider adding it to `#{common}`
|
43
|
+
|
44
|
+
If it is a new utility class, is there another class that shares the same values in either this file or in `#{utilities}`? If not, please be sure this addition follows the [Gitlab UI naming style](https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss) so it may be removed when these rules are included. See [Include gitlab-ui utility-class library](https://gitlab.com/gitlab-org/gitlab/issues/36857) for more about this project.
|
45
|
+
|
46
|
+
MARKDOWN
|
47
|
+
end
|
48
|
+
|
49
|
+
warn "This merge request adds a new rule to #{common} or #{utilities}."
|
50
|
+
|
51
|
+
end
|