danger-dangermattic 1.3.0 → 1.4.0

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: 455052da651ef9af5d20ffc6be33a06ab961393e4c0adc8d3d87e27beba62efd
4
- data.tar.gz: f04b1494ea66bc1fb3677e69658c08fa40b7373f548215f424ffd6f5fd0a4148
3
+ metadata.gz: 1ea5b40de9b9c82ffa11d1f10449caacbdd87051a9f2d1d7765a73869fe923a6
4
+ data.tar.gz: 82a8e207c33c9cddde899d05094bd6e1a128d6d8ce95e4847f59248a3f0af1c0
5
5
  SHA512:
6
- metadata.gz: 58e0ffcb0c9ee7ce6f6a9080dc95e5aa8d9fe21eac85b576782625c4a528d0ebdc7069498fc6e965345f23d159eba6a186c7a9074f33ba38988e8bd3e24cc70c
7
- data.tar.gz: 5401b6ce0765675148c5a6951c4f1279be562a3bc55a0e9dc824d6e0fd92a123738cdef5b8258fb734e8427939c206af845dac89d89d3192ee0f32f6ac2c0c3e
6
+ metadata.gz: 7c059b2ecabb7c0e126811bb3f5f8b0b3555feec5ed14a1df606dfcc61201a7540cf1242622802c0f76b6b4f59836a8038f275fb0491476b397d0967a673f2ea
7
+ data.tar.gz: 9cf786de34875f9cdd091aa479d285f13a8a78950c86bb480467c3f8aab6499dbbf7b3b7142d8cd6c8237b38c6247f38251f77e0e264ab4fb3c65cc81d557302
@@ -0,0 +1,13 @@
1
+ # Ruby dependency surface
2
+ Gemfile* @Automattic/apps-infra-tooling
3
+ *.gemspec @Automattic/apps-infra-tooling
4
+ .bundle/ @Automattic/apps-infra-tooling
5
+ .rubocop*.yml @Automattic/apps-infra-tooling
6
+
7
+ # CI and automation
8
+ .buildkite/ @Automattic/apps-infra-tooling
9
+ .github/workflows/ @Automattic/apps-infra-tooling
10
+ .github/dependabot.yml @Automattic/apps-infra-tooling
11
+
12
+ # Toolchain and environment pins
13
+ .ruby-version @Automattic/apps-infra-tooling
@@ -21,3 +21,12 @@ updates:
21
21
  cooldown:
22
22
  default-days: 7
23
23
  semver-major-days: 14
24
+
25
+ - package-ecosystem: bundler
26
+ directory: /
27
+ schedule:
28
+ interval: daily
29
+ groups:
30
+ ruby-minor-and-patch:
31
+ update-types: [minor, patch]
32
+ open-pull-requests-limit: 5
@@ -26,11 +26,11 @@ jobs:
26
26
  runs-on: ubuntu-latest
27
27
  steps:
28
28
  - name: 📥 Checkout Repo
29
- uses: actions/checkout@v4
29
+ uses: actions/checkout@v7
30
30
  with:
31
31
  fetch-depth: 100
32
32
  - name: 💎 Ruby Setup
33
- uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0
33
+ uses: ruby/setup-ruby@d45b1a4e94b71acab930e56e79c6aa188764e7f9 # v1.316.0
34
34
  with:
35
35
  bundler-cache: true
36
36
  - name: ☢️ Danger PR Check
data/CHANGELOG.md CHANGED
@@ -20,6 +20,12 @@ _None_
20
20
 
21
21
  _None_
22
22
 
23
+ ## 1.4.0
24
+
25
+ ### New Features
26
+
27
+ - `pr_size_checker`: add optional `line_selector` to `check_diff_size` (and `insertions_size` / `deletions_size` / `diff_size`) to exclude specific changed lines (e.g. comments and blank lines) from the diff-size metric. [#133]
28
+
23
29
  ## 1.3.0
24
30
 
25
31
  ### New Features
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- danger-dangermattic (1.3.0)
4
+ danger-dangermattic (1.4.0)
5
5
  danger (~> 9.5, >= 9.5.3)
6
6
  danger-plugin-api (~> 1.0)
7
7
  danger-rubocop (~> 0.13)
@@ -35,7 +35,7 @@ GEM
35
35
  open4 (~> 1.3)
36
36
  coderay (1.1.3)
37
37
  colored2 (3.1.2)
38
- concurrent-ruby (1.3.6)
38
+ concurrent-ruby (1.3.7)
39
39
  connection_pool (3.0.2)
40
40
  cork (0.3.0)
41
41
  colored2 (~> 3.1)
@@ -60,13 +60,13 @@ GEM
60
60
  rubocop (~> 1.0)
61
61
  diff-lcs (1.6.2)
62
62
  drb (2.2.3)
63
- faraday (2.14.1)
63
+ faraday (2.14.3)
64
64
  faraday-net_http (>= 2.0, < 3.5)
65
65
  json
66
66
  logger
67
67
  faraday-http-cache (2.6.1)
68
68
  faraday (>= 0.8)
69
- faraday-net_http (3.4.2)
69
+ faraday-net_http (3.4.4)
70
70
  net-http (~> 0.5)
71
71
  ffi (1.17.2)
72
72
  ffi (1.17.2-arm64-darwin)
@@ -94,7 +94,7 @@ GEM
94
94
  rspec (>= 2.99.0, < 4.0)
95
95
  i18n (1.14.8)
96
96
  concurrent-ruby (~> 1.0)
97
- json (2.19.3)
97
+ json (2.20.0)
98
98
  kramdown (2.5.2)
99
99
  rexml (>= 3.4.4)
100
100
  kramdown-parser-gfm (1.1.0)
@@ -190,7 +190,7 @@ GEM
190
190
  unicode-emoji (~> 4.1)
191
191
  unicode-emoji (4.2.0)
192
192
  uri (1.1.1)
193
- yard (0.9.43)
193
+ yard (0.9.44)
194
194
 
195
195
  PLATFORMS
196
196
  arm64-darwin-22
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Dangermattic
4
- VERSION = '1.3.0'
4
+ VERSION = '1.4.0'
5
5
  end
@@ -18,6 +18,14 @@ module Danger
18
18
  # # Check the size of insertions in the files selected by the file_selector
19
19
  # pr_size_checker.check_diff_size(file_selector: ->(file) { file.include?('/java/test/') }, type: :insertions)
20
20
  #
21
+ # @example Running a PR diff size check that excludes comment and blank lines from the count
22
+ #
23
+ # # Only count changed lines that are neither blank nor comments (e.g. Kotlin/Java/Swift)
24
+ # pr_size_checker.check_diff_size(
25
+ # max_size: 300,
26
+ # line_selector: ->(line) { stripped = line.strip; !(stripped.empty? || stripped.start_with?('//', '/*', '*', '*/')) }
27
+ # )
28
+ #
21
29
  # @example Running a PR description length check
22
30
  #
23
31
  # # Check the PR Body using the default parameters, reporting a warning if the PR is smaller than 10 characters
@@ -39,20 +47,28 @@ module Danger
39
47
  #
40
48
  # @param max_size [Integer] The maximum allowed size for the diff.
41
49
  # @param file_selector [Proc] Optional closure to filter the files in the diff to be used for size calculation.
50
+ # @param line_selector [Proc] Optional closure to filter the individual changed lines counted towards the size.
51
+ # It receives the content of an added/removed line (without the leading `+`/`-` diff marker or trailing newline)
52
+ # and should return `true` for lines that should be counted. When provided, the size is computed by iterating the
53
+ # diff patches instead of the cached numstats, which is slower but allows excluding lines such as comments or blanks.
42
54
  # @param type [:insertions, :deletions, :all] The type of diff size to check. (default: :all)
43
55
  # @param message [String] The message to display if the diff size exceeds the maximum. (default: DEFAULT_DIFF_SIZE_MESSAGE)
44
56
  # @param report_type [Symbol] (optional) The type of report for the message. Types: :error, :warning (default), :message.
45
57
  #
46
58
  # @return [void]
47
- def check_diff_size(max_size:, file_selector: nil, type: :all, message: format(DEFAULT_DIFF_SIZE_MESSAGE_FORMAT, max_size), report_type: :warning)
48
- case type
49
- when :insertions
50
- reporter.report(message: message, type: report_type) if insertions_size(file_selector: file_selector) > max_size
51
- when :deletions
52
- reporter.report(message: message, type: report_type) if deletions_size(file_selector: file_selector) > max_size
53
- when :all
54
- reporter.report(message: message, type: report_type) if diff_size(file_selector: file_selector) > max_size
55
- end
59
+ def check_diff_size(max_size:, file_selector: nil, line_selector: nil, type: :all, message: format(DEFAULT_DIFF_SIZE_MESSAGE_FORMAT, max_size), report_type: :warning)
60
+ size = case type
61
+ when :insertions
62
+ insertions_size(file_selector: file_selector, line_selector: line_selector)
63
+ when :deletions
64
+ deletions_size(file_selector: file_selector, line_selector: line_selector)
65
+ when :all
66
+ diff_size(file_selector: file_selector, line_selector: line_selector)
67
+ else
68
+ raise ArgumentError, "Unknown diff size type: #{type.inspect}. Use :insertions, :deletions, or :all."
69
+ end
70
+
71
+ reporter.report(message: message, type: report_type) if size > max_size
56
72
  end
57
73
 
58
74
  # Check the size of the Pull Request description (PR body) against a specified minimum size.
@@ -71,9 +87,12 @@ module Danger
71
87
  # Calculate the total size of insertions in modified files that match the file selector.
72
88
  #
73
89
  # @param file_selector [Proc] Select the files to be used for the insertions calculation.
90
+ # @param line_selector [Proc] Optional closure to select which added lines are counted (see #check_diff_size).
74
91
  #
75
92
  # @return [Integer] The total size of insertions in the selected modified files.
76
- def insertions_size(file_selector: nil)
93
+ def insertions_size(file_selector: nil, line_selector: nil)
94
+ return filtered_diff_size(file_selector: file_selector, line_selector: line_selector, change_types: [:added]) if line_selector
95
+
77
96
  return danger.git.insertions unless file_selector
78
97
 
79
98
  # Only check added and modified files - deleted files have 0 insertions
@@ -88,9 +107,12 @@ module Danger
88
107
  # Calculate the total size of deletions in modified files that match the file selector.
89
108
  #
90
109
  # @param file_selector [Proc] Select the files to be used for the deletions calculation.
110
+ # @param line_selector [Proc] Optional closure to select which removed lines are counted (see #check_diff_size).
91
111
  #
92
112
  # @return [Integer] The total size of deletions in the selected modified files.
93
- def deletions_size(file_selector: nil)
113
+ def deletions_size(file_selector: nil, line_selector: nil)
114
+ return filtered_diff_size(file_selector: file_selector, line_selector: line_selector, change_types: [:removed]) if line_selector
115
+
94
116
  return danger.git.deletions unless file_selector
95
117
 
96
118
  filtered_files = git_utils.all_changed_files.select(&file_selector)
@@ -104,9 +126,12 @@ module Danger
104
126
  # Calculate the total size of changes (insertions and deletions) in modified files that match the file selector.
105
127
  #
106
128
  # @param file_selector [Proc] Select the files to be used for the total insertions and deletions calculation.
129
+ # @param line_selector [Proc] Optional closure to select which added/removed lines are counted (see #check_diff_size).
107
130
  #
108
131
  # @return [Integer] The total size of changes in the selected modified files.
109
- def diff_size(file_selector: nil)
132
+ def diff_size(file_selector: nil, line_selector: nil)
133
+ return filtered_diff_size(file_selector: file_selector, line_selector: line_selector, change_types: %i[added removed]) if line_selector
134
+
110
135
  return danger.git.lines_of_code unless file_selector
111
136
 
112
137
  filtered_files = git_utils.all_changed_files.select(&file_selector)
@@ -119,5 +144,47 @@ module Danger
119
144
  stats[:deletions].to_i + stats[:insertions].to_i
120
145
  end
121
146
  end
147
+
148
+ private
149
+
150
+ # Count the changed lines across the selected files by iterating the diff patches, keeping only the lines
151
+ # whose change type is included in `change_types` and for which `line_selector` returns true.
152
+ #
153
+ # This is slower than the cached-numstats path used when no `line_selector` is given, since it needs the
154
+ # actual patch content to evaluate each line, but it is the only way to exclude specific lines (e.g. comments).
155
+ #
156
+ # @param file_selector [Proc, nil] Optional closure to select the files to inspect.
157
+ # @param line_selector [Proc] Closure receiving a changed line's content (without the `+`/`-` marker),
158
+ # returning true when the line should be counted.
159
+ # @param change_types [Array<Symbol>] The diff change types to count (any of :added, :removed).
160
+ #
161
+ # @return [Integer] The total number of counted changed lines.
162
+ def filtered_diff_size(file_selector:, line_selector:, change_types:)
163
+ files = git_utils.all_changed_files
164
+ files = files.select(&file_selector) if file_selector
165
+
166
+ files.sum do |file|
167
+ # `patch` can be nil (e.g. binary files), in which case there are no textual lines to count.
168
+ patch = danger.git.diff_for_file(file)&.patch
169
+ next 0 unless patch
170
+
171
+ patch.each_line.count do |diff_line|
172
+ next false unless change_types.include?(git_utils.change_type(diff_line: diff_line))
173
+
174
+ line_selector.call(strip_diff_marker(diff_line))
175
+ end
176
+ end
177
+ end
178
+
179
+ # Strip the leading `+`/`-` diff marker and the trailing newline from a diff patch line,
180
+ # so that `line_selector` only sees the actual line content.
181
+ #
182
+ # @param diff_line [String] A line from a diff patch, e.g. `"+ // a comment\n"`.
183
+ #
184
+ # @return [String] The line content, e.g. `" // a comment"`.
185
+ def strip_diff_marker(diff_line)
186
+ without_marker = diff_line[1..].to_s
187
+ without_marker.chomp
188
+ end
122
189
  end
123
190
  end
@@ -177,6 +177,120 @@ module Danger
177
177
  it_behaves_like 'using the default diff size counter, without a file selector', :deletions
178
178
  it_behaves_like 'using a file selector to filter and count the changes in a diff', :deletions, [221, 380, 1157]
179
179
  end
180
+
181
+ context 'when using a line_selector to exclude comment and blank lines' do
182
+ # Counts a changed line only if, once trimmed, it is neither empty nor the start of a comment.
183
+ let(:code_line_selector) do
184
+ lambda do |line|
185
+ stripped = line.strip
186
+ !(stripped.empty? || stripped.start_with?('//', '/*', '*', '*/'))
187
+ end
188
+ end
189
+
190
+ # 4 added code lines (fun/val/return/}) + 1 removed code line, plus comment and blank lines that must be ignored.
191
+ let(:kotlin_patch) do
192
+ <<~PATCH
193
+ diff --git a/Foo.kt b/Foo.kt
194
+ index 1234567..89abcde 100644
195
+ --- a/Foo.kt
196
+ +++ b/Foo.kt
197
+ @@ -1,2 +1,10 @@
198
+ package com.example
199
+ +
200
+ +// a single line comment
201
+ +/* a block comment */
202
+ +/** kdoc opening */
203
+ + * kdoc continuation line
204
+ +fun foo(): Int {
205
+ + val x = 1
206
+ + return x
207
+ +}
208
+ -val removedCode = 0
209
+ -// removed comment
210
+ PATCH
211
+ end
212
+
213
+ before do
214
+ stub_const('GitDiffStruct', Struct.new(:type, :path, :patch))
215
+ allow(@plugin.git).to receive_messages(added_files: ['Foo.kt'], modified_files: [], deleted_files: [])
216
+ allow(@plugin.git).to receive(:diff_for_file).with('Foo.kt').and_return(GitDiffStruct.new('added', 'Foo.kt', kotlin_patch))
217
+ end
218
+
219
+ it 'reports a warning when the non-comment, non-blank changes exceed the max (type :all counts 5)' do
220
+ @plugin.check_diff_size(max_size: 4, type: :all, line_selector: code_line_selector)
221
+
222
+ expect(@dangerfile).to report_warnings([format(described_class::DEFAULT_DIFF_SIZE_MESSAGE_FORMAT, 4)])
223
+ end
224
+
225
+ it 'does nothing when the non-comment, non-blank changes are within the max (type :all counts 5)' do
226
+ @plugin.check_diff_size(max_size: 5, type: :all, line_selector: code_line_selector)
227
+
228
+ expect(@dangerfile).to not_report
229
+ end
230
+
231
+ it 'counts only added code lines for :insertions (counts 4)' do
232
+ @plugin.check_diff_size(max_size: 3, type: :insertions, line_selector: code_line_selector)
233
+
234
+ expect(@dangerfile).to report_warnings([format(described_class::DEFAULT_DIFF_SIZE_MESSAGE_FORMAT, 3)])
235
+ end
236
+
237
+ it 'does nothing for :insertions when the added code lines are within the max (counts 4)' do
238
+ @plugin.check_diff_size(max_size: 4, type: :insertions, line_selector: code_line_selector)
239
+
240
+ expect(@dangerfile).to not_report
241
+ end
242
+
243
+ it 'counts only removed code lines for :deletions (counts 1)' do
244
+ @plugin.check_diff_size(max_size: 0, type: :deletions, line_selector: code_line_selector)
245
+
246
+ expect(@dangerfile).to report_warnings([format(described_class::DEFAULT_DIFF_SIZE_MESSAGE_FORMAT, 0)])
247
+ end
248
+
249
+ it 'does nothing for :deletions when the removed code lines are within the max (counts 1)' do
250
+ @plugin.check_diff_size(max_size: 1, type: :deletions, line_selector: code_line_selector)
251
+
252
+ expect(@dangerfile).to not_report
253
+ end
254
+
255
+ it 'exposes the filtered counts through the size helpers' do
256
+ expect(@plugin.diff_size(line_selector: code_line_selector)).to eq(5)
257
+ expect(@plugin.insertions_size(line_selector: code_line_selector)).to eq(4)
258
+ end
259
+
260
+ context 'when combined with a file_selector' do
261
+ before do
262
+ excluded_test_file = 'src/test/java/FooTest.kt'
263
+ allow(@plugin.git).to receive_messages(added_files: ['Foo.kt', excluded_test_file], modified_files: [], deleted_files: [])
264
+ allow(@plugin.git).to receive(:diff_for_file).with(excluded_test_file).and_return(GitDiffStruct.new('added', excluded_test_file, kotlin_patch))
265
+ end
266
+
267
+ it 'only counts lines in files accepted by the file_selector' do
268
+ # Both files carry the same patch (5 code lines each); excluding the test file must keep the count at 5, not 10.
269
+ file_selector = ->(path) { !path.include?('src/test') }
270
+
271
+ expect(
272
+ @plugin.diff_size(file_selector: file_selector, line_selector: code_line_selector)
273
+ ).to eq(5)
274
+ end
275
+ end
276
+
277
+ context 'without a line_selector (default numstats path)' do
278
+ before do
279
+ allow(@plugin.git).to receive(:diff).and_return(instance_double(Git::Diff))
280
+ allow(@plugin.git.diff).to receive(:stats).and_return({ files: { 'Foo.kt' => { insertions: 9, deletions: 2 } } })
281
+ end
282
+
283
+ it 'counts every changed line including comments and blanks (counts 11)' do
284
+ @plugin.check_diff_size(max_size: 10, type: :all, file_selector: ->(_path) { true })
285
+
286
+ expect(@dangerfile).to report_warnings([format(described_class::DEFAULT_DIFF_SIZE_MESSAGE_FORMAT, 10)])
287
+ end
288
+ end
289
+ end
290
+
291
+ it 'raises an ArgumentError when given an unknown diff size type' do
292
+ expect { @plugin.check_diff_size(max_size: 100, type: :unknown) }.to raise_error(ArgumentError)
293
+ end
180
294
  end
181
295
 
182
296
  context 'when checking a PR body size' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: danger-dangermattic
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Automattic
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-06-16 00:00:00.000000000 Z
11
+ date: 2026-07-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: danger
@@ -207,6 +207,7 @@ files:
207
207
  - ".buildkite/gem-push.sh"
208
208
  - ".buildkite/pipeline.yml"
209
209
  - ".bundle/config"
210
+ - ".github/CODEOWNERS"
210
211
  - ".github/dependabot.yml"
211
212
  - ".github/workflows/README.md"
212
213
  - ".github/workflows/reusable-check-labels-on-issues.yml"