gitlab-dangerfiles 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0d3407bad03ff3220a55329e625c1fd5a962b4ffe29b4ab1da68a7e998761024
4
- data.tar.gz: a9f31b18452500fa6e437a847b1d726cbbe2c47a1912c5e40fd18196ca3716fa
3
+ metadata.gz: 30a4d627f19b9baece5e677425892f5ede2b883db11c57ae4178956975dcdb69
4
+ data.tar.gz: dfb9f139593171a0ddf7b075993ebe9419c0b32a33a391c5b7dfa4814871f553
5
5
  SHA512:
6
- metadata.gz: 3390ab204b7572654e748198fb1d03b70056ab26b32a8ea29cc2c624e307e59c5cfab5306afb8900c71df62671b984ccdbb21e7c1e9adb16b2ab43a9299774c0
7
- data.tar.gz: '06879db4e54bff63e540793f8c94f3c9412d6481641144bfa80934bb36a82872c76e9693c86aa9b381d78528da06a27795f620ff9127829e4904938807958ede'
6
+ metadata.gz: 504abc1a266560c6277dd9cb329b35894e2cdc958703403bdd88e3b2a7ad883860ed56be1bb14bf48529d0207b61f69a896260e4ab87cd0e251b373bcb902b18
7
+ data.tar.gz: ba5ff6ef20d7571c70a6bc4b130b5b54a89881c3757bf2b4c6949be6e7c441ba9deca33b13753be8428f0877663d24410a05a9aa3e45bac8fc2f5ff9e5a6aeae
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.
@@ -0,0 +1,139 @@
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_EXCEEDED_MESSAGE = <<~MSG
10
+ This merge request includes more than %<max_commits_count>d commits. Each commit should meet the following criteria:
11
+
12
+ 1. Have a well-written commit message.
13
+ 1. Has all tests passing when used on its own (e.g. when using git checkout SHA).
14
+ 1. Can be reverted on its own without also requiring the revert of commit that came before it.
15
+ 1. Is small enough that it can be reviewed in isolation in under 30 minutes or so.
16
+
17
+ 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.
18
+ MSG
19
+
20
+ max_commits_count = helper.config.max_commits_count
21
+
22
+ def fail_commit(commit, message, more_info: true)
23
+ self.fail(build_message(commit, message, more_info: more_info))
24
+ end
25
+
26
+ def warn_commit(commit, message, more_info: true)
27
+ self.warn(build_message(commit, message, more_info: more_info))
28
+ end
29
+
30
+ def build_message(commit, message, more_info: true)
31
+ [message].tap do |full_message|
32
+ full_message << ". #{MORE_INFO}" if more_info
33
+ full_message.unshift("#{commit.sha}: ") if commit.sha
34
+ end.join
35
+ end
36
+
37
+ def danger_job_link
38
+ helper.ci? ? "[#{format(THE_DANGER_JOB_TEXT, job_name: ENV["CI_JOB_NAME"])}](#{ENV['CI_JOB_URL']})" : THE_DANGER_JOB_TEXT
39
+ end
40
+
41
+ # Perform various checks against commits. We're not using
42
+ # https://github.com/jonallured/danger-commit_lint because its output is not
43
+ # very helpful, and it doesn't offer the means of ignoring merge commits.
44
+ def lint_commit(commit)
45
+ linter = Gitlab::Dangerfiles::CommitLinter.new(commit)
46
+
47
+ # For now we'll ignore merge commits, as getting rid of those is a problem
48
+ # separate from enforcing good commit messages.
49
+ return linter if linter.merge?
50
+
51
+ # We ignore revert commits as they are well structured by Git already
52
+ return linter if linter.revert?
53
+
54
+ # If MR is set to squash, we ignore fixup commits
55
+ return linter if linter.fixup? && helper.squash_mr?
56
+
57
+ if linter.fixup?
58
+ msg = "Squash or fixup commits must be squashed before merge, or enable squash merge option and re-run #{danger_job_link}."
59
+ if helper.draft_mr? || helper.squash_mr?
60
+ warn_commit(commit, msg, more_info: false)
61
+ else
62
+ fail_commit(commit, msg, more_info: false)
63
+ end
64
+
65
+ # Makes no sense to process other rules for fixup commits, they trigger just more noise
66
+ return linter
67
+ end
68
+
69
+ # Fail if a suggestion commit is used and squash is not enabled
70
+ if linter.suggestion?
71
+ unless helper.squash_mr?
72
+ fail_commit(commit, "If you are applying suggestions, enable squash in the merge request and re-run #{danger_job_link}.", more_info: false)
73
+ end
74
+
75
+ return linter
76
+ end
77
+
78
+ linter.lint
79
+ end
80
+
81
+ def lint_mr_title(mr_title)
82
+ commit = Struct.new(:message, :sha).new(mr_title)
83
+
84
+ Gitlab::Dangerfiles::MergeRequestLinter.new(commit).lint
85
+ end
86
+
87
+ def count_non_fixup_commits(commit_linters)
88
+ commit_linters.count { |commit_linter| !commit_linter.fixup? }
89
+ end
90
+
91
+ def lint_commits(commits)
92
+ commit_linters = commits.map { |commit| lint_commit(commit) }
93
+
94
+ if helper.squash_mr?
95
+ multi_line_commit_linter = commit_linters.detect { |commit_linter| !commit_linter.merge? && commit_linter.multi_line? }
96
+
97
+ if multi_line_commit_linter && multi_line_commit_linter.failed?
98
+ warn_or_fail_commits(multi_line_commit_linter)
99
+ commit_linters.delete(multi_line_commit_linter) # Don't show an error (here) and a warning (below)
100
+ elsif helper.ci? # We don't have access to the MR title locally
101
+ title_linter = lint_mr_title(gitlab.mr_json['title'])
102
+ if title_linter.failed?
103
+ warn_or_fail_commits(title_linter)
104
+ end
105
+ end
106
+ else
107
+ if count_non_fixup_commits(commit_linters) > max_commits_count
108
+ self.warn(format(MAX_COMMITS_COUNT_EXCEEDED_MESSAGE, max_commits_count: max_commits_count))
109
+ end
110
+ end
111
+
112
+ failed_commit_linters = commit_linters.select { |commit_linter| commit_linter.failed? }
113
+ warn_or_fail_commits(failed_commit_linters, default_to_fail: !helper.squash_mr?)
114
+ end
115
+
116
+ def warn_or_fail_commits(failed_linters, default_to_fail: true)
117
+ level = default_to_fail ? :fail : :warn
118
+
119
+ Array(failed_linters).each do |linter|
120
+ linter.problems.each do |problem_key, problem_desc|
121
+ case problem_key
122
+ when :subject_too_short, :subject_above_warning, :details_too_many_changes, :details_line_too_long
123
+ warn_commit(linter.commit, problem_desc)
124
+ else
125
+ self.__send__("#{level}_commit", linter.commit, problem_desc) # rubocop:disable GitlabSecurity/PublicSend
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ # As part of https://gitlab.com/groups/gitlab-org/-/epics/4826 we are
132
+ # vendoring workhorse commits from the stand-alone gitlab-workhorse
133
+ # repo. There is no point in linting commits that we want to vendor as
134
+ # is.
135
+ def workhorse_changes?
136
+ git.diff.any? { |file| file.path.start_with?('workhorse/') }
137
+ end
138
+
139
+ lint_commits(git.commits) unless workhorse_changes?
@@ -8,7 +8,10 @@ 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
12
15
 
13
16
  def self.problems_mapping
14
17
  super.merge(
@@ -139,7 +142,8 @@ module Gitlab
139
142
  end
140
143
 
141
144
  def message_contains_short_reference?
142
- commit.message.match?(SHORT_REFERENCE_REGEX)
145
+ commit.message.match?(SHORT_REFERENCE_REGEX) ||
146
+ commit.message.match?(MS_SHORT_REFERENCE_REGEX)
143
147
  end
144
148
 
145
149
  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.0"
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.0
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-06-11 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