gitlab-dangerfiles 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- docs_paths_to_review = helper.changes_by_category[:docs]
4
-
5
- return if docs_paths_to_review.empty?
6
-
7
- message 'This merge request adds or changes files that require a review ' \
8
- 'from the Technical Writing team.'
9
-
10
- return unless helper.ci?
11
-
12
- markdown(<<~MARKDOWN)
13
- ## Documentation review
14
-
15
- The following files require a review from a technical writer:
16
-
17
- * #{docs_paths_to_review.map { |path| "`#{path}`" }.join("\n* ")}
18
-
19
- The review does not need to block merging this merge request. See the:
20
-
21
- - [Technical Writers assignments](https://about.gitlab.com/handbook/engineering/technical-writing/#designated-technical-writers) for the appropriate technical writer for this review.
22
- - [Documentation workflows](https://docs.gitlab.com/ee/development/documentation/workflow.html) for information on when to assign a merge request for review.
23
- MARKDOWN
24
-
25
- unless gitlab.mr_labels.include?('documentation')
26
- gitlab.api.update_merge_request(gitlab.mr_json['project_id'],
27
- gitlab.mr_json['iid'],
28
- labels: (gitlab.mr_labels + ['documentation']).join(','))
29
- end
@@ -1,29 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- return unless helper.all_changed_files.include?('yarn.lock')
4
-
5
- duplicate = `node_modules/.bin/yarn-deduplicate --list --strategy fewer yarn.lock`
6
- .split(/$/)
7
- .map(&:strip)
8
- .reject(&:empty?)
9
-
10
- return if duplicate.empty?
11
-
12
- warn 'This merge request has introduced duplicated yarn dependencies.'
13
-
14
- if helper.ci?
15
- markdown(<<~MARKDOWN)
16
- ## Duplicate yarn dependencies
17
-
18
- The following dependencies should be de-duplicated:
19
-
20
- * #{duplicate.map { |path| "`#{path}`" }.join("\n* ")}
21
-
22
- Please run the following command and commit the changes to `yarn.lock`:
23
-
24
- ```
25
- node_modules/.bin/yarn-deduplicate --strategy fewer yarn.lock \\
26
- && yarn install
27
- ```
28
- MARKDOWN
29
- end
@@ -1,31 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- def get_eslint_files(files)
4
- files.select do |file|
5
- file.end_with?('.js', '.vue') &&
6
- File.read(file).include?('/* eslint-disable')
7
- end
8
- end
9
-
10
- eslint_candidates = get_eslint_files(helper.all_changed_files)
11
-
12
- return if eslint_candidates.empty?
13
-
14
- warn 'This merge request changed files with disabled eslint rules. Please consider fixing them.'
15
-
16
- if helper.ci?
17
- markdown(<<~MARKDOWN)
18
- ## Disabled eslint rules
19
-
20
- The following files have disabled `eslint` rules. Please consider fixing them:
21
-
22
- * #{eslint_candidates.map { |path| "`#{path}`" }.join("\n* ")}
23
-
24
- Run the following command for more details
25
-
26
- ```
27
- node_modules/.bin/eslint --report-unused-disable-directives --no-inline-config \\
28
- #{eslint_candidates.map { |path| " '#{path}'" }.join(" \\\n")}
29
- ```
30
- MARKDOWN
31
- end
@@ -1,28 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- FILE_EXTENSION = ".rb"
4
- MAGIC_COMMENT = "# frozen_string_literal: true"
5
-
6
- def get_files_with_no_magic_comment(files)
7
- files.select do |file|
8
- file.end_with?(FILE_EXTENSION) &&
9
- !File.open(file, &:gets)&.start_with?(MAGIC_COMMENT)
10
- end
11
- end
12
-
13
- files_to_fix = get_files_with_no_magic_comment(git.added_files)
14
-
15
- if files_to_fix.any?
16
- warn 'This merge request adds files that do not enforce frozen string literal. ' \
17
- 'See https://gitlab.com/gitlab-org/gitlab-foss/issues/47424 for more information.'
18
-
19
- if helper.ci?
20
- markdown(<<~MARKDOWN)
21
- ## Enable Frozen String Literal
22
-
23
- The following files should have `#{MAGIC_COMMENT}` on the first line:
24
-
25
- * #{files_to_fix.map { |path| "`#{path}`" }.join("\n* ")}
26
- MARKDOWN
27
- end
28
- end
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
- # rubocop:disable Style/SignalException
3
-
4
- def get_karma_files(files)
5
- files.select do |file|
6
- file.start_with?('ee/spec/javascripts', 'spec/javascripts') &&
7
- file.end_with?('_spec.js') &&
8
- !file.end_with?('browser_spec.js')
9
- end
10
- end
11
-
12
- new_karma_files = get_karma_files(git.added_files.to_a)
13
-
14
- unless new_karma_files.empty?
15
-
16
- if helper.ci?
17
- markdown(<<~MARKDOWN)
18
- ## New karma spec file
19
-
20
- New frontend specs ([except `browser_specs`](https://gitlab.com/gitlab-org/gitlab/blob/3b6fe2f1077eedb0b8aff02a7350234f0b7dc4f9/spec/javascripts/lib/utils/browser_spec.js#L2)) should be
21
- [written in jest](https://docs.gitlab.com/ee/development/testing_guide/frontend_testing.html#jest).
22
-
23
- You have created the following tests, please migrate them over to jest:
24
-
25
- * #{new_karma_files.map { |path| "`#{path}`" }.join("\n* ")}
26
- MARKDOWN
27
- end
28
-
29
- fail "You have created a new karma spec file"
30
-
31
- end
32
-
33
- changed_karma_files = get_karma_files(helper.all_changed_files) - new_karma_files
34
-
35
- return if changed_karma_files.empty?
36
-
37
- warn 'You have edited karma spec files. Please consider migrating them to jest.'
38
-
39
- if helper.ci?
40
- markdown(<<~MARKDOWN)
41
- ## Edited karma files
42
-
43
- You have edited the following karma spec files. Please consider migrating them to jest:
44
-
45
- * #{changed_karma_files.map { |path| "`#{path}`" }.join("\n* ")}
46
-
47
- In order to align with our Iteration value, migration can also be done as a follow-up.
48
-
49
- For more information: [Jestodus epic](https://gitlab.com/groups/gitlab-org/-/epics/895)
50
- MARKDOWN
51
- end
@@ -1,50 +0,0 @@
1
- # rubocop:disable Style/SignalException
2
-
3
- THROUGHPUT_LABELS = [
4
- 'Community contribution',
5
- 'security',
6
- 'bug',
7
- 'backstage', # To be removed by https://gitlab.com/gitlab-org/gitlab/-/issues/222360.
8
- 'feature',
9
- 'feature::addition',
10
- 'feature::maintenance',
11
- 'tooling',
12
- 'tooling::pipelines',
13
- 'tooling::workflow',
14
- 'documentation'
15
- ].freeze
16
-
17
- if gitlab.mr_body.size < 5
18
- fail "Please provide a proper merge request description."
19
- end
20
-
21
- if gitlab.mr_labels.empty?
22
- fail "Please add labels to this merge request."
23
- end
24
-
25
- if (THROUGHPUT_LABELS & gitlab.mr_labels).empty?
26
- warn 'Please add a [throughput label](https://about.gitlab.com/handbook/engineering/management/throughput/#implementation) to this merge request.'
27
- end
28
-
29
- unless gitlab.mr_json["assignee"]
30
- warn "This merge request does not have any assignee yet. Setting an assignee clarifies who needs to take action on the merge request at any given time."
31
- end
32
-
33
- has_milestone = !gitlab.mr_json["milestone"].nil?
34
-
35
- unless has_milestone
36
- warn "This merge request does not refer to an existing milestone.", sticky: false
37
- end
38
-
39
- has_pick_into_stable_label = gitlab.mr_labels.find { |label| label.start_with?('Pick into') }
40
-
41
- if gitlab.branch_for_base != "master" && !has_pick_into_stable_label && !helper.security_mr?
42
- warn "Most of the time, merge requests should target `master`. Otherwise, please set the relevant `Pick into X.Y` label."
43
- end
44
-
45
- if gitlab.mr_json['title'].length > 72
46
- warn 'The title of this merge request is longer than 72 characters and ' \
47
- 'would violate our commit message rules when using the Squash on Merge ' \
48
- 'feature. Please consider adjusting the title, or rebase the ' \
49
- "commits manually and don't use Squash on Merge."
50
- end
@@ -1,55 +0,0 @@
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
@@ -1,41 +0,0 @@
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
@@ -1,97 +0,0 @@
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
@@ -1,27 +0,0 @@
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