gitlab-dangerfiles 2.0.0 → 2.1.4

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
  SHA256:
3
- metadata.gz: 0d3407bad03ff3220a55329e625c1fd5a962b4ffe29b4ab1da68a7e998761024
4
- data.tar.gz: a9f31b18452500fa6e437a847b1d726cbbe2c47a1912c5e40fd18196ca3716fa
3
+ metadata.gz: e97286bdfb0262152ab62792bff988f54b6a4c4e518600fc6488868a40aa9e25
4
+ data.tar.gz: dcebdb1e4d4d97a9b6d2c532c976c1c9ce25296aab56de9bcec9444ac7f7847a
5
5
  SHA512:
6
- metadata.gz: 3390ab204b7572654e748198fb1d03b70056ab26b32a8ea29cc2c624e307e59c5cfab5306afb8900c71df62671b984ccdbb21e7c1e9adb16b2ab43a9299774c0
7
- data.tar.gz: '06879db4e54bff63e540793f8c94f3c9412d6481641144bfa80934bb36a82872c76e9693c86aa9b381d78528da06a27795f620ff9127829e4904938807958ede'
6
+ metadata.gz: d117a697f702f3b2c456957b811e850a564281b9190104b552c2784415e8d26505ed1cc300cef281dab94864cb41bd89bdf8c21d9b42c1875222b8b959d43b53
7
+ data.tar.gz: 8e5539c873291b0328cc7a5cc2ac5b6bc1965fd550ba04a0700b2e5a19da89f979d30c56967990d4b41de989cd7a5d58a9e3bf6285e49449668431d04f22fb46
data/.gitignore CHANGED
@@ -9,6 +9,7 @@
9
9
  /pkg/
10
10
  /spec/reports/
11
11
  /tmp/
12
+ /doc/
12
13
 
13
14
  # rspec failure tracking
14
15
  .rspec_status
data/.gitlab-ci.yml CHANGED
@@ -11,7 +11,7 @@ workflow:
11
11
  # For tags, create a pipeline.
12
12
  - if: '$CI_COMMIT_TAG'
13
13
 
14
- default:
14
+ .default:
15
15
  image: ruby:2.7
16
16
  tags:
17
17
  - gitlab-org
@@ -29,15 +29,50 @@ default:
29
29
  policy: pull
30
30
 
31
31
  test:rspec:
32
+ extends: .default
32
33
  stage: test
33
34
  script:
34
35
  - bundle exec rspec
35
36
 
36
37
  test:rufo:
38
+ extends: .default
37
39
  stage: test
38
40
  script:
39
41
  - bundle exec rufo --check .
40
42
 
41
43
  include:
44
+ - template: Security/Dependency-Scanning.gitlab-ci.yml
45
+ - template: Security/License-Scanning.gitlab-ci.yml
46
+ - template: Security/SAST.gitlab-ci.yml
47
+ - template: Security/Secret-Detection.gitlab-ci.yml
42
48
  - project: 'gitlab-org/quality/pipeline-common'
43
49
  file: '/ci/gem-release.yml'
50
+
51
+ # run security jobs on MRs
52
+ # see: https://gitlab.com/gitlab-org/gitlab/-/issues/218444#note_478761991
53
+
54
+ brakeman-sast:
55
+ rules:
56
+ - if: '$CI_MERGE_REQUEST_IID'
57
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
58
+
59
+ gemnasium-dependency_scanning:
60
+ rules:
61
+ - if: '$CI_MERGE_REQUEST_IID'
62
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
63
+
64
+ bundler-audit-dependency_scanning:
65
+ rules:
66
+ - if: '$CI_MERGE_REQUEST_IID'
67
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
68
+
69
+ license_scanning:
70
+ rules:
71
+ - if: '$CI_MERGE_REQUEST_IID'
72
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
73
+
74
+ secret_detection:
75
+ rules:
76
+ - if: '$CI_MERGE_REQUEST_IID'
77
+ - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
78
+
data/README.md CHANGED
@@ -64,6 +64,17 @@ Danger rules are located under `lib/danger/rules`.
64
64
  `:high` is the lines changed threshold which triggers an error, and
65
65
  `:medium` is the lines changed threshold which triggers a warning.
66
66
 
67
+ #### `commit_messages`
68
+
69
+ ##### Available configurations
70
+
71
+ - `max_commits_count`: The maximum number of allowed non-squashed/non-fixup commits for a given MR.
72
+ A warning is triggered if the MR has more commits.
73
+
74
+ ## Documentation
75
+
76
+ Latest documentation can be found at <https://www.rubydoc.info/gems/gitlab-dangerfiles>.
77
+
67
78
  ## Development
68
79
 
69
80
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -283,9 +283,18 @@ module Danger
283
283
  gitlab_helper.mr_json["target_branch"]
284
284
  end
285
285
 
286
+ # @return [Boolean] +true+ when not in the CI context, and whether the MR is set to be squashed otherwise.
287
+ def squash_mr?
288
+ return true unless ci?
289
+
290
+ gitlab.mr_json["squash"]
291
+ end
292
+
286
293
  # @return [Boolean] whether a MR is a Draft or not.
287
294
  def draft_mr?
288
- Gitlab::Dangerfiles::TitleLinting.has_draft_flag?(mr_title)
295
+ return false unless ci?
296
+
297
+ gitlab.mr_json["work_in_progress"]
289
298
  end
290
299
 
291
300
  # @return [Boolean] whether a MR is opened in the security mirror or not.
@@ -34,7 +34,7 @@ module Danger
34
34
  #
35
35
  # @return [Array<Spin>]
36
36
  def spin(project, categories = [nil], timezone_experiment: false)
37
- spins = categories.sort.map do |category|
37
+ spins = categories.sort_by(&:to_s).map do |category|
38
38
  including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(category, timezone_experiment)
39
39
 
40
40
  spin_for_category(project, category, timezone_experiment: including_timezone)
@@ -0,0 +1,138 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../../gitlab/dangerfiles/commit_linter"
4
+ require_relative "../../../gitlab/dangerfiles/merge_request_linter"
5
+
6
+ COMMIT_MESSAGE_GUIDELINES = "https://docs.gitlab.com/ee/development/contributing/merge_request_workflow.html#commit-messages-guidelines"
7
+ MORE_INFO = "For more information, take a look at our [Commit message guidelines](#{COMMIT_MESSAGE_GUIDELINES})."
8
+ THE_DANGER_JOB_TEXT = "the `%<job_name>` job"
9
+ MAX_COMMITS_COUNT = helper.config.max_commits_count
10
+ MAX_COMMITS_COUNT_EXCEEDED_MESSAGE = <<~MSG
11
+ This merge request includes more than %<max_commits_count>d commits. Each commit should meet the following criteria:
12
+
13
+ 1. Have a well-written commit message.
14
+ 1. Has all tests passing when used on its own (e.g. when using git checkout SHA).
15
+ 1. Can be reverted on its own without also requiring the revert of commit that came before it.
16
+ 1. Is small enough that it can be reviewed in isolation in under 30 minutes or so.
17
+
18
+ If this merge request contains commits that do not meet this criteria and/or contains intermediate work, please rebase these commits into a smaller number of commits or split this merge request into multiple smaller merge requests.
19
+ MSG
20
+
21
+ def fail_commit(commit, message, more_info: true)
22
+ self.fail(build_message(commit, message, more_info: more_info))
23
+ end
24
+
25
+ def warn_commit(commit, message, more_info: true)
26
+ self.warn(build_message(commit, message, more_info: more_info))
27
+ end
28
+
29
+ def build_message(commit, message, more_info: true)
30
+ [message].tap do |full_message|
31
+ full_message << ". #{MORE_INFO}" if more_info
32
+ full_message.unshift("#{commit.sha}: ") if commit.sha
33
+ end.join
34
+ end
35
+
36
+ def danger_job_link
37
+ helper.ci? ? "[#{format(THE_DANGER_JOB_TEXT, job_name: ENV["CI_JOB_NAME"])}](#{ENV['CI_JOB_URL']})" : THE_DANGER_JOB_TEXT
38
+ end
39
+
40
+ # Perform various checks against commits. We're not using
41
+ # https://github.com/jonallured/danger-commit_lint because its output is not
42
+ # very helpful, and it doesn't offer the means of ignoring merge commits.
43
+ def lint_commit(commit)
44
+ linter = Gitlab::Dangerfiles::CommitLinter.new(commit)
45
+
46
+ # For now we'll ignore merge commits, as getting rid of those is a problem
47
+ # separate from enforcing good commit messages.
48
+ return linter if linter.merge?
49
+
50
+ # We ignore revert commits as they are well structured by Git already
51
+ return linter if linter.revert?
52
+
53
+ # If MR is set to squash, we ignore fixup commits
54
+ return linter if linter.fixup? && helper.squash_mr?
55
+
56
+ if linter.fixup?
57
+ msg = "Squash or fixup commits must be squashed before merge, or enable squash merge option and re-run #{danger_job_link}."
58
+ if helper.draft_mr? || helper.squash_mr?
59
+ warn_commit(commit, msg, more_info: false)
60
+ else
61
+ fail_commit(commit, msg, more_info: false)
62
+ end
63
+
64
+ # Makes no sense to process other rules for fixup commits, they trigger just more noise
65
+ return linter
66
+ end
67
+
68
+ # Fail if a suggestion commit is used and squash is not enabled
69
+ if linter.suggestion?
70
+ unless helper.squash_mr?
71
+ fail_commit(commit, "If you are applying suggestions, enable squash in the merge request and re-run #{danger_job_link}.", more_info: false)
72
+ end
73
+
74
+ return linter
75
+ end
76
+
77
+ linter.lint
78
+ end
79
+
80
+ def lint_mr_title(mr_title)
81
+ commit = Struct.new(:message, :sha).new(mr_title)
82
+
83
+ Gitlab::Dangerfiles::MergeRequestLinter.new(commit).lint
84
+ end
85
+
86
+ def count_non_fixup_commits(commit_linters)
87
+ commit_linters.count { |commit_linter| !commit_linter.fixup? }
88
+ end
89
+
90
+ def lint_commits(commits)
91
+ commit_linters = commits.map { |commit| lint_commit(commit) }
92
+
93
+ if helper.squash_mr?
94
+ multi_line_commit_linter = commit_linters.detect { |commit_linter| !commit_linter.merge? && commit_linter.multi_line? }
95
+
96
+ if multi_line_commit_linter && multi_line_commit_linter.failed?
97
+ warn_or_fail_commits(multi_line_commit_linter)
98
+ commit_linters.delete(multi_line_commit_linter) # Don't show an error (here) and a warning (below)
99
+ elsif helper.ci? # We don't have access to the MR title locally
100
+ title_linter = lint_mr_title(gitlab.mr_json['title'])
101
+ if title_linter.failed?
102
+ warn_or_fail_commits(title_linter)
103
+ end
104
+ end
105
+ else
106
+ if count_non_fixup_commits(commit_linters) > MAX_COMMITS_COUNT
107
+ self.warn(format(MAX_COMMITS_COUNT_EXCEEDED_MESSAGE, max_commits_count: MAX_COMMITS_COUNT))
108
+ end
109
+ end
110
+
111
+ failed_commit_linters = commit_linters.select { |commit_linter| commit_linter.failed? }
112
+ warn_or_fail_commits(failed_commit_linters, default_to_fail: !helper.squash_mr?)
113
+ end
114
+
115
+ def warn_or_fail_commits(failed_linters, default_to_fail: true)
116
+ level = default_to_fail ? :fail : :warn
117
+
118
+ Array(failed_linters).each do |linter|
119
+ linter.problems.each do |problem_key, problem_desc|
120
+ case problem_key
121
+ when :subject_too_short, :subject_above_warning, :details_too_many_changes, :details_line_too_long
122
+ warn_commit(linter.commit, problem_desc)
123
+ else
124
+ self.__send__("#{level}_commit", linter.commit, problem_desc) # rubocop:disable GitlabSecurity/PublicSend
125
+ end
126
+ end
127
+ end
128
+ end
129
+
130
+ # As part of https://gitlab.com/groups/gitlab-org/-/epics/4826 we are
131
+ # vendoring workhorse commits from the stand-alone gitlab-workhorse
132
+ # repo. There is no point in linting commits that we want to vendor as
133
+ # is.
134
+ def workhorse_changes?
135
+ git.diff.any? { |file| file.path.start_with?('workhorse/') }
136
+ end
137
+
138
+ lint_commits(git.commits) unless workhorse_changes?
@@ -10,6 +10,7 @@ module Gitlab
10
10
  end
11
11
  LOCAL_RULES = %w[
12
12
  changes_size
13
+ commit_messages
13
14
  ].freeze
14
15
  CI_ONLY_RULES = %w[
15
16
  ].freeze
@@ -8,7 +8,11 @@ module Gitlab
8
8
  class CommitLinter < BaseLinter
9
9
  MAX_CHANGED_FILES_IN_COMMIT = 3
10
10
  MAX_CHANGED_LINES_IN_COMMIT = 30
11
- SHORT_REFERENCE_REGEX = %r{([\w\-\/]+)?(?<!`)(#|!|&|%)\d+(?<!`)}.freeze
11
+ # Issue, MR, Epic
12
+ SHORT_REFERENCE_REGEX = %r{([\w\-\/]+)?(?<!`)(#|!|&)\d+(?<!`)}.freeze
13
+ # Milestone
14
+ MS_SHORT_REFERENCE_REGEX = %r{([\w\-\/]+)?(?<!`)%"?\d{1,3}\.\d{1,3}"?(?<!`)}.freeze
15
+ SUGGESTIONS_APPLIED_COMMIT_REGEX = /Apply \d+ suggestion\(s\) to \d+ file\(s\)/.freeze
12
16
 
13
17
  def self.problems_mapping
14
18
  super.merge(
@@ -38,7 +42,7 @@ module Gitlab
38
42
  end
39
43
 
40
44
  def suggestion?
41
- commit.message.start_with?("Apply suggestion to")
45
+ SUGGESTIONS_APPLIED_COMMIT_REGEX.match?(commit.message)
42
46
  end
43
47
 
44
48
  def merge?
@@ -139,7 +143,8 @@ module Gitlab
139
143
  end
140
144
 
141
145
  def message_contains_short_reference?
142
- commit.message.match?(SHORT_REFERENCE_REGEX)
146
+ commit.message.match?(SHORT_REFERENCE_REGEX) ||
147
+ commit.message.match?(MS_SHORT_REFERENCE_REGEX)
143
148
  end
144
149
 
145
150
  def emoji_checker
@@ -7,10 +7,16 @@ module Gitlab
7
7
  # @return [{ high: Integer, medium: Integer }] a hash of the form +{ high: 42, medium: 12 }+ where +:high+ is the lines changed threshold which triggers an error, and +:medium+ is the lines changed threshold which triggers a warning. Also, see +DEFAULT_CHANGES_SIZE_THRESHOLDS+ for the format of the hash.
8
8
  attr_accessor :code_size_thresholds
9
9
 
10
+ # @!attribute max_commits_count
11
+ # @return [Integer] the maximum number of allowed non-squashed/non-fixup commits for a given MR. A warning is triggered if the MR has more commits.
12
+ attr_accessor :max_commits_count
13
+
10
14
  DEFAULT_CHANGES_SIZE_THRESHOLDS = { high: 2_000, medium: 500 }.freeze
15
+ DEFAULT_COMMIT_MESSAGES_MAX_COMMITS_COUNT = 10
11
16
 
12
17
  def initialize
13
18
  @code_size_thresholds = DEFAULT_CHANGES_SIZE_THRESHOLDS
19
+ @max_commits_count = DEFAULT_COMMIT_MESSAGES_MAX_COMMITS_COUNT
14
20
  end
15
21
  end
16
22
  end
@@ -19,6 +19,8 @@ module Gitlab
19
19
  end
20
20
 
21
21
  def has_draft_flag?(title)
22
+ puts "This method is deprecated in favor of `helper.draft_mr?`."
23
+
22
24
  DRAFT_REGEX.match?(title)
23
25
  end
24
26
 
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module Dangerfiles
3
- VERSION = "2.0.0"
3
+ VERSION = "2.1.4"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-dangerfiles
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
4
+ version: 2.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - GitLab
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-04-27 00:00:00.000000000 Z
11
+ date: 2021-07-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: danger-gitlab
@@ -134,6 +134,7 @@ files:
134
134
  - lib/danger/plugins/helper.rb
135
135
  - lib/danger/plugins/roulette.rb
136
136
  - lib/danger/rules/changes_size/Dangerfile
137
+ - lib/danger/rules/commit_messages/Dangerfile
137
138
  - lib/gitlab-dangerfiles.rb
138
139
  - lib/gitlab/Dangerfile
139
140
  - lib/gitlab/dangerfiles.rb