danger 8.4.5 → 8.5.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: 55ca17556aed4215f86219bcdca5271049b481a1bd349e35211b4f9e509c2b15
4
- data.tar.gz: b2b1fb228f4325ce12ac2ff9c7a753d1b056966f0e8078bdce392a4fb9334b32
3
+ metadata.gz: c8d6272f0ed9095d67e585d262669d8d11705a8a5cce460c02122a9b826d5cd7
4
+ data.tar.gz: 42699026115d900c5e32f057e206697472be7ba80d6d1686e7eb07d5262100c6
5
5
  SHA512:
6
- metadata.gz: f2769209f205e40a84f24426e4ce93b3681cbe8f4d57970114b0238d0a3f4c5bb8ff75bbd69936635abb7a8c64f933aaf1e18c4c2a0355ef18630d8365b99c60
7
- data.tar.gz: c260a71c30a49e4b6fad9975986324f795fc07750edd082e0e364f6c4975fc69e68619d7bd083bb48dac24f514f14a102d7cb7b95509de1c1b664608fbc63421
6
+ metadata.gz: 3981a24f19fb7b63737b80435d8d2685fa187630aeb82edb28042c8d0db74f23412e588daf16732f045563cc52f9d85432682c76fe1913c4cde57d671b99cb8b
7
+ data.tar.gz: 4b7f3f4fb90975da2faa9cbdff6e5cb95e27ea06447fa95a749df6df77bec14de7c47c6e52fc2d98949e160cb4dd12a96d9babefec2798be8cdcd1cde77f0ebd
@@ -0,0 +1,17 @@
1
+ <%- @tables.each do |table| -%>
2
+ <%- if table[:content].any? || table[:resolved].any? -%>
3
+ | | |
4
+ |---|---|
5
+ <%- table[:content].each do |violation| -%>
6
+ | <%= @emoji_mapper.map(table[:emoji]) %> | <%= "~~" if table[:resolved] %><%= violation.message %><%= "~~" if table[:resolved] %> |
7
+ <%- end -%>
8
+
9
+ <%- end -%>
10
+ <%- end -%>
11
+
12
+ <%- @markdowns.each do |current| -%>
13
+ <%= current %>
14
+ <%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
15
+ <%- end -%>
16
+
17
+ Generated by :no_entry_sign: [Danger](https://danger.systems/ "generated_by_<%= @danger_id %>")
@@ -24,7 +24,8 @@ module Danger
24
24
  # @param [Bool] Should hide any generated link created
25
25
  #
26
26
  # @return [String] The Markdown compatible link
27
- def markdown_link_to_message(message, _)
27
+ def markdown_link_to_message(message, hide_link)
28
+ return "" if hide_link
28
29
  "#{message.file}#L#{message.line}"
29
30
  end
30
31
 
@@ -147,7 +148,7 @@ module Danger
147
148
 
148
149
  def generate_description(warnings: nil, errors: nil, template: "github")
149
150
  emoji_mapper = EmojiMapper.new(template)
150
- if errors.empty? && warnings.empty?
151
+ if (errors.nil? || errors.empty?) && (warnings.nil? || warnings.empty?)
151
152
  return ENV['DANGER_SUCCESS_MESSAGE'] || "All green. #{random_compliment}"
152
153
  else
153
154
  message = "#{emoji_mapper.map('warning')} "
@@ -43,6 +43,10 @@ module Danger
43
43
  @scm ||= GitRepo.new
44
44
  end
45
45
 
46
+ def client
47
+ @api
48
+ end
49
+
46
50
  def host
47
51
  @host ||= @api.host
48
52
  end
@@ -76,15 +80,36 @@ module Danger
76
80
  return
77
81
  end
78
82
 
79
- comment = generate_description(warnings: warnings, errors: errors)
83
+ regular_violations = regular_violations_group(
84
+ warnings: warnings,
85
+ errors: errors,
86
+ messages: messages,
87
+ markdowns: markdowns
88
+ )
89
+
90
+ inline_violations = inline_violations_group(
91
+ warnings: warnings,
92
+ errors: errors,
93
+ messages: messages,
94
+ markdowns: markdowns
95
+ )
96
+
97
+ rest_inline_violations = submit_inline_comments!(**{
98
+ danger_id: danger_id,
99
+ previous_violations: {}
100
+ }.merge(inline_violations))
101
+
102
+ main_violations = merge_violations(
103
+ regular_violations, rest_inline_violations
104
+ )
105
+
106
+ comment = generate_description(warnings: main_violations[:warnings], errors: main_violations[:errors])
80
107
  comment += "\n\n"
81
- comment += generate_comment(warnings: warnings,
82
- errors: errors,
83
- messages: messages,
84
- markdowns: markdowns,
85
- previous_violations: {},
86
- danger_id: danger_id,
87
- template: "vsts")
108
+ comment += generate_comment(**{
109
+ previous_violations: {},
110
+ danger_id: danger_id,
111
+ template: "vsts"
112
+ }.merge(main_violations))
88
113
  if new_comment || remove_previous_comments
89
114
  post_new_comment(comment)
90
115
  else
@@ -105,6 +130,8 @@ module Danger
105
130
  comment_content = comment[:content].nil? ? "" : comment[:content]
106
131
  # Skip the comment if it wasn't posted by danger
107
132
  next unless comment_content.include?("generated_by_#{danger_id}")
133
+ # Skip the comment if it's an inline comment
134
+ next unless c[:threadContext].nil?
108
135
  # Updated the danger posted comment
109
136
  @api.update_comment(thread_id, comment_id, new_comment)
110
137
  comment_updated = true
@@ -112,6 +139,142 @@ module Danger
112
139
  # If no comment was updated, post a new one
113
140
  post_new_comment(new_comment) unless comment_updated
114
141
  end
142
+
143
+ def submit_inline_comments!(warnings: [], errors: [], messages: [], markdowns: [], previous_violations: [], danger_id: "danger")
144
+ # Avoid doing any fetchs if there's no inline comments
145
+ return {} if (warnings + errors + messages + markdowns).select(&:inline?).empty?
146
+
147
+ pr_threads = @api.fetch_last_comments
148
+ danger_threads = pr_threads.select do |thread|
149
+ comment = thread[:comments].first
150
+ comment_content = comment[:content].nil? ? "" : comment[:content]
151
+
152
+ next comment_content.include?("generated_by_#{danger_id}")
153
+ end
154
+ non_danger_threads = pr_threads - danger_threads
155
+
156
+ warnings = submit_inline_comments_for_kind!(:warning, warnings, danger_threads, previous_violations["warning"], danger_id: danger_id)
157
+ errors = submit_inline_comments_for_kind!(:error, errors, danger_threads, previous_violations["error"], danger_id: danger_id)
158
+ messages = submit_inline_comments_for_kind!(:message, messages, danger_threads, previous_violations["message"], danger_id: danger_id)
159
+ markdowns = submit_inline_comments_for_kind!(:markdown, markdowns, danger_threads, [], danger_id: danger_id)
160
+
161
+ # submit removes from the array all comments that are still in force
162
+ # so we strike out all remaining ones
163
+ danger_threads.each do |thread|
164
+ violation = violations_from_table(thread[:comments].first[:content]).first
165
+ if !violation.nil? && violation.sticky
166
+ body = generate_inline_comment_body("white_check_mark", violation, danger_id: danger_id, resolved: true, template: "github")
167
+ @api.update_comment(thread[:id], thread[:comments].first[:id], body)
168
+ end
169
+ end
170
+
171
+ {
172
+ warnings: warnings,
173
+ errors: errors,
174
+ messages: messages,
175
+ markdowns: markdowns
176
+ }
177
+ end
178
+
179
+ def messages_are_equivalent(m1, m2)
180
+ blob_regexp = %r{blob/[0-9a-z]+/}
181
+ m1.file == m2.file && m1.line == m2.line &&
182
+ m1.message.sub(blob_regexp, "") == m2.message.sub(blob_regexp, "")
183
+ end
184
+
185
+ def submit_inline_comments_for_kind!(kind, messages, danger_threads, previous_violations, danger_id: "danger")
186
+ previous_violations ||= []
187
+ is_markdown_content = kind == :markdown
188
+ emoji = { warning: "warning", error: "no_entry_sign", message: "book" }[kind]
189
+
190
+ messages.reject do |m|
191
+ next false unless m.file && m.line
192
+
193
+ # Once we know we're gonna submit it, we format it
194
+ if is_markdown_content
195
+ body = generate_inline_markdown_body(m, danger_id: danger_id, template: "vsts")
196
+ else
197
+ # Hide the inline link behind a span
198
+ m.message.gsub!("\n", "<br />")
199
+ m = process_markdown(m, true)
200
+ body = generate_inline_comment_body(emoji, m, danger_id: danger_id, template: "vsts")
201
+ # A comment might be in previous_violations because only now it's part of the unified diff
202
+ # We remove from the array since it won't have a place in the table anymore
203
+ previous_violations.reject! { |v| messages_are_equivalent(v, m) }
204
+ end
205
+
206
+ matching_threads = danger_threads.select do |comment_data|
207
+ if comment_data.key?(:threadContext) && !comment_data[:threadContext].nil? &&
208
+ comment_data[:threadContext][:filePath] == m.file &&
209
+ comment_data[:threadContext].key?(:rightFileStart) &&
210
+ comment_data[:threadContext][:rightFileStart][:line] == m.line
211
+ # Parse it to avoid problems with strikethrough
212
+ violation = violations_from_table(comment_data[:comments].first[:content]).first
213
+ if violation
214
+ messages_are_equivalent(violation, m)
215
+ else
216
+ blob_regexp = %r{blob/[0-9a-z]+/}
217
+ comment_data[:comments].first[:content].sub(blob_regexp, "") == body.sub(blob_regexp, "")
218
+ end
219
+ else
220
+ false
221
+ end
222
+ end
223
+
224
+ if matching_threads.empty?
225
+ @api.post_inline_comment(body, m.file, m.line)
226
+
227
+ # Not reject because this comment has not completed
228
+ next false
229
+ else
230
+ # Remove the surviving comment so we don't strike it out
231
+ danger_threads.reject! { |c| matching_threads.include? c }
232
+
233
+ # Update the comment to remove the strikethrough if present
234
+ thread = matching_threads.first
235
+ @api.update_comment(thread[:id], thread[:comments].first[:id], body)
236
+ end
237
+
238
+ # Remove this element from the array
239
+ next true
240
+ end
241
+ end
242
+
243
+ private
244
+
245
+ def regular_violations_group(warnings: [], errors: [], messages: [], markdowns: [])
246
+ {
247
+ warnings: warnings.reject(&:inline?),
248
+ errors: errors.reject(&:inline?),
249
+ messages: messages.reject(&:inline?),
250
+ markdowns: markdowns.reject(&:inline?)
251
+ }
252
+ end
253
+
254
+ def inline_violations_group(warnings: [], errors: [], messages: [], markdowns: [])
255
+ cmp = proc do |a, b|
256
+ next -1 unless a.file && a.line
257
+ next 1 unless b.file && b.line
258
+
259
+ next a.line <=> b.line if a.file == b.file
260
+ next a.file <=> b.file
261
+ end
262
+
263
+ # Sort to group inline comments by file
264
+ {
265
+ warnings: warnings.select(&:inline?).sort(&cmp),
266
+ errors: errors.select(&:inline?).sort(&cmp),
267
+ messages: messages.select(&:inline?).sort(&cmp),
268
+ markdowns: markdowns.select(&:inline?).sort(&cmp)
269
+ }
270
+ end
271
+
272
+ def merge_violations(*violation_groups)
273
+ violation_groups.inject({}) do |accumulator, group|
274
+ accumulator.merge(group) { |_, old, fresh| old + fresh }
275
+ end
276
+ end
277
+
115
278
  end
116
279
  end
117
280
  end
@@ -76,6 +76,38 @@ module Danger
76
76
  post(uri, body)
77
77
  end
78
78
 
79
+ def post_inline_comment(text, file, line)
80
+ uri = URI("#{pr_api_endpoint}/threads?api-version=#{@api_version}")
81
+ body = {
82
+ "comments" => [
83
+ {
84
+ "parentCommentId" => 0,
85
+ "content" => text,
86
+ "commentType" => 1
87
+ }
88
+ ],
89
+ "properties" => {
90
+ "Microsoft.TeamFoundation.Discussion.SupportsMarkdown" => {
91
+ "type" => "System.Int32",
92
+ "value" => 1
93
+ }
94
+ },
95
+ "status" => 1,
96
+ "threadContext" => {
97
+ "filePath" => file,
98
+ "rightFileEnd" => {
99
+ "line" => line + 1,
100
+ "offset" => 1
101
+ },
102
+ "rightFileStart" => {
103
+ "line" => line,
104
+ "offset" => 1
105
+ }
106
+ }
107
+ }.to_json
108
+ post(uri, body)
109
+ end
110
+
79
111
  def update_comment(thread, id, new_comment)
80
112
  uri = URI("#{pr_api_endpoint}/threads/#{thread}/comments/#{id}?api-version=#{@api_version}")
81
113
  body = {
@@ -1,4 +1,4 @@
1
1
  module Danger
2
- VERSION = "8.4.5".freeze
2
+ VERSION = "8.5.0".freeze
3
3
  DESCRIPTION = "Like Unit Tests, but for your Team Culture.".freeze
4
4
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: danger
3
3
  version: !ruby/object:Gem::Version
4
- version: 8.4.5
4
+ version: 8.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Orta Therox
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2022-03-04 00:00:00.000000000 Z
12
+ date: 2022-03-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: claide
@@ -271,6 +271,7 @@ files:
271
271
  - lib/danger/comment_generators/gitlab.md.erb
272
272
  - lib/danger/comment_generators/gitlab_inline.md.erb
273
273
  - lib/danger/comment_generators/vsts.md.erb
274
+ - lib/danger/comment_generators/vsts_inline.md.erb
274
275
  - lib/danger/core_ext/file_list.rb
275
276
  - lib/danger/core_ext/string.rb
276
277
  - lib/danger/danger_core/dangerfile.rb