danger 6.3.2 → 7.0.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: 27b09c31a2f456489426bf90c66b907f7c7b620bc0019387c3c7dd89e14267b6
4
- data.tar.gz: 7aeed8d94b83e5fb757ca0f319fe55e3c07a4fc641c93dd56408efc1aaeccf4a
3
+ metadata.gz: bac82d5de5c00b56576cd95681444543eb4b540f6bb6767ac1d407fb13150fbc
4
+ data.tar.gz: 032b2993f97a2c8c56b4d8f69690c7bbd7bbf6738e3631af54a0ea657811939f
5
5
  SHA512:
6
- metadata.gz: 267bc39cef40d450ec1be77ddeb0c279ef6b5b7f5cd8a3dd2afdb49f6a4b5fa32feb10622c84f0f2f85a3907b4fb05824ecfad0b517fcf4eacd0d4949423dc69
7
- data.tar.gz: de72c74f898bdc9a3c70bf730158e2c642aa6b392935a3e89a6980a457262475c549f10380e0123e4a5b92c03ae9b27018bf7cb8aa919667256edd5639d70149
6
+ metadata.gz: 74fa60f6fc40846e32837a0b8234b119f6132ff4a629abd705480a8c4ebee1bbb78ed19ad940fc63d8d08b427e238bea3edb2d67286d23ceef48ac8a7c9e0dd3
7
+ data.tar.gz: 7072368e374403c31ea5240b8004942c9e28f00806f4acb1d65fafe850d291b8a893f06a3b1a294a325e374fc594e732c43343cd50c36ea99ee5d52ffe281c0a
@@ -66,12 +66,15 @@ module Danger
66
66
 
67
67
  private
68
68
 
69
+ # this method is a duplicate of Commands::PR#configure_octokit
70
+ # - worth a refactor sometime?
69
71
  def configure_octokit(cache_dir)
70
72
  # setup caching for Github calls to hitting the API rate limit too quickly
71
73
  cache_file = File.join(cache_dir, "danger_local_cache")
72
74
  cache = HTTPCache.new(cache_file, clear_cache: @clear_http_cache)
73
75
  Octokit.middleware = Faraday::RackBuilder.new do |builder|
74
76
  builder.use Faraday::HttpCache, store: cache, serializer: Marshal, shared_cache: false
77
+ builder.use Octokit::Middleware::FollowRedirects
75
78
  builder.use Octokit::Response::RaiseError
76
79
  builder.adapter Faraday.default_adapter
77
80
  end
@@ -83,6 +83,7 @@ module Danger
83
83
  end
84
84
  Octokit.middleware = Faraday::RackBuilder.new do |builder|
85
85
  builder.use Faraday::HttpCache, store: cache, serializer: Marshal, shared_cache: false
86
+ builder.use Octokit::Middleware::FollowRedirects
86
87
  builder.use Octokit::Response::RaiseError
87
88
  builder.adapter Faraday.default_adapter
88
89
  end
@@ -0,0 +1,12 @@
1
+ <%- @message_group.messages.each do |message| -%>
2
+ <%- next if message.type == :markdown -%>
3
+ <%= @emoji_mapper.from_type(message.type) -%> <%= message.message %>
4
+
5
+ <%- end -%>
6
+ <%- @resolved.each do |message| -%>
7
+ <%= @emoji_mapper.map("white_check_mark") %> <%= message %>
8
+ <%- end -%>
9
+
10
+ <%= @message_group.markdowns.map(&:message).join("\n\n") %>
11
+
12
+ Generated by :no_entry_sign: [Danger](https://danger.systems/ "generated_by_<%= @danger_id %>")
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "danger/danger_core/dangerfile_dsl"
4
4
  require "danger/danger_core/standard_error"
5
+ require "danger/danger_core/message_aggregator"
5
6
 
6
7
  require "danger/danger_core/plugins/dangerfile_messaging_plugin"
7
8
  require "danger/danger_core/plugins/dangerfile_danger_plugin"
@@ -251,7 +252,10 @@ module Danger
251
252
  }
252
253
 
253
254
  if env.request_source.respond_to?(:update_pr_by_line!) && ENV["DANGER_MESSAGE_AGGREGATION"]
254
- env.request_source.update_pr_by_line!(messages: MessageAggregator.aggregate(**report))
255
+ env.request_source.update_pr_by_line!(message_groups: MessageAggregator.aggregate(**report),
256
+ new_comment: new_comment,
257
+ remove_previous_comments: remove_previous_comments,
258
+ danger_id: report[:danger_id])
255
259
  else
256
260
  env.request_source.update_pull_request!(
257
261
  **report,
@@ -1,12 +1,49 @@
1
- class MessageAggregator
2
- def self.aggregate(*args)
3
- new(*args).aggregate
4
- end
1
+ # frozen_string_literal: true
2
+ require "danger/danger_core/message_group"
3
+ require "danger/helpers/message_groups_array_helper"
4
+
5
+ module Danger
6
+ class MessageAggregator
7
+ def self.aggregate(*args)
8
+ new(*args).aggregate
9
+ end
10
+
11
+ def initialize(warnings: [],
12
+ errors: [],
13
+ messages: [],
14
+ markdowns: [],
15
+ danger_id: "danger")
16
+ @messages = warnings + errors + messages + markdowns
17
+ @danger_id = danger_id
18
+ end
19
+
20
+ # aggregates the messages into an array of MessageGroups
21
+ # @return [[MessageGroup]]
22
+ def aggregate
23
+ # oookay I took some shortcuts with this one.
24
+ # first, sort messages by file and line
25
+ @messages.sort! { |a, b| a.compare_by_file_and_line(b) }
26
+
27
+ # now create an initial empty message group
28
+ first_group = MessageGroup.new(file: nil,
29
+ line: nil)
30
+ @message_groups = @messages.reduce([first_group]) do |groups, msg|
31
+ # We get to take a shortcut because we sorted the messages earlier - only
32
+ # have to see if we can append msg to the last group in the list
33
+ if groups.last << msg
34
+ # we appended it, so return groups unchanged
35
+ groups
36
+ else
37
+ # have to create a new group since msg wasn't appended to the other
38
+ # group
39
+ new_group = MessageGroup.new(file: msg.file,
40
+ line: msg.line)
41
+ new_group << msg
42
+ groups << new_group
43
+ end
44
+ end
5
45
 
6
- def initialize(warnings: [],
7
- errors: [],
8
- messages: [],
9
- markdowns: [],
10
- danger_id: "danger")
46
+ @message_groups.extend(Helpers::MessageGroupsArrayHelper)
47
+ end
11
48
  end
12
49
  end
@@ -28,7 +28,18 @@ module Danger
28
28
  # @param message [Markdown, Violation] the message to add
29
29
  def <<(message)
30
30
  # TODO: insertion sort
31
- messages << message if same_line?(message)
31
+ return nil unless same_line?(message)
32
+
33
+ inserted = false
34
+ messages.each.with_index do |other, idx|
35
+ if (message <=> other) == -1
36
+ inserted = true
37
+ messages.insert(idx, message)
38
+ break
39
+ end
40
+ end
41
+ messages << message unless inserted
42
+ messages
32
43
  end
33
44
 
34
45
  # The list of messages in this group. This list will be sorted in decreasing
@@ -38,5 +49,20 @@ module Danger
38
49
  end
39
50
 
40
51
  attr_reader :file, :line
52
+
53
+ # @return a hash of statistics. Currently only :warnings_count and
54
+ # :errors_count
55
+ def stats
56
+ stats = { warnings_count: 0, errors_count: 0 }
57
+ messages.each do |msg|
58
+ stats[:warnings_count] += 1 if msg.type == :warning
59
+ stats[:errors_count] += 1 if msg.type == :error
60
+ end
61
+ stats
62
+ end
63
+
64
+ def markdowns
65
+ messages.select { |x| x.type == :markdown }
66
+ end
41
67
  end
42
68
  end
@@ -48,7 +48,7 @@ module Danger
48
48
  extra << "line: #{line}" if line
49
49
  extra << "type: #{type}"
50
50
 
51
- "Violation #{message} { #{extra.join ', '.freeze} }"
51
+ "Violation #{message} { #{extra.join ', '} }"
52
52
  end
53
53
  end
54
54
  end
@@ -136,14 +136,14 @@ module Danger
136
136
  # @return [Hash] with keys `:insertions`, `:deletions` giving line counts, and `:before`, `:after` giving file contents, or nil if the file has no changes or does not exist
137
137
  #
138
138
  def info_for_file(file)
139
- return nil unless modified_files.include?(file)
139
+ return nil unless modified_files.include?(file) || added_files.include?(file) || deleted_files.include?(file)
140
140
  stats = @git.diff.stats[:files][file]
141
141
  diff = @git.diff[file]
142
142
  {
143
143
  insertions: stats[:insertions],
144
144
  deletions: stats[:deletions],
145
- before: diff.blob(:src).contents,
146
- after: diff.blob(:dst).contents
145
+ before: added_files.include?(file) || deleted_files.include?(file) ? nil : diff.blob(:src).contents,
146
+ after: added_files.include?(file) || deleted_files.include?(file) ? nil : diff.blob(:dst).contents
147
147
  }
148
148
  end
149
149
 
@@ -76,7 +76,7 @@ module Danger
76
76
  }
77
77
  end
78
78
 
79
- def apply_template(tables: [], markdowns: [], danger_id: "danger", template: "github")
79
+ def apply_template(tables: [], markdowns: [], danger_id: "danger", template: "github", request_source: template)
80
80
  require "erb"
81
81
 
82
82
  md_template = File.join(Danger.gem_path, "lib/danger/comment_generators/#{template}.md.erb")
@@ -86,7 +86,7 @@ module Danger
86
86
  @tables = tables
87
87
  @markdowns = markdowns.map(&:message)
88
88
  @danger_id = danger_id
89
- @emoji_mapper = EmojiMapper.new(template)
89
+ @emoji_mapper = EmojiMapper.new(request_source.sub("_inline",""))
90
90
 
91
91
  return ERB.new(File.read(md_template), 0, "-").result(binding)
92
92
  end
@@ -104,7 +104,32 @@ module Danger
104
104
  )
105
105
  end
106
106
 
107
- def generate_inline_comment_body(emoji, message, danger_id: "danger", resolved: false, template: "github")
107
+ # resolved is essentially reserved for future use - eventually we might
108
+ # have some nice generic resolved-thing going :)
109
+ def generate_message_group_comment(message_group:,
110
+ danger_id: "danger",
111
+ resolved: [],
112
+ template: "github")
113
+ # cheating a bit - I don't want to alter the apply_template API
114
+ # so just sneak around behind its back setting some instance variables
115
+ # to get them to show up in the template
116
+ @message_group = message_group
117
+ @resolved = resolved
118
+ request_source_name = template.sub("_message_group", "")
119
+
120
+
121
+ apply_template(danger_id: danger_id,
122
+ markdowns: message_group.markdowns,
123
+ template: template,
124
+ request_source: request_source_name)
125
+ .sub(/\A\n*/, "")
126
+ end
127
+
128
+ def generate_inline_comment_body(emoji,
129
+ message,
130
+ danger_id: "danger",
131
+ resolved: [],
132
+ template: "github")
108
133
  apply_template(
109
134
  tables: [{ content: [message], resolved: resolved, emoji: emoji }],
110
135
  danger_id: danger_id,
@@ -15,16 +15,25 @@ module Danger
15
15
  }
16
16
  }.freeze
17
17
 
18
+ TYPE_TO_EMOJI = {
19
+ error: "no_entry_sign",
20
+ warning: "warning",
21
+ message: "book",
22
+ }.freeze
23
+
18
24
  def initialize(template)
19
- template.sub!('_inline', '')
20
25
  @template = DATA.has_key?(template) ? template : "github"
21
26
  end
22
27
 
23
28
  def map(emoji)
24
- emoji.delete! ":"
29
+ emoji&.delete! ":"
25
30
  DATA[template][emoji]
26
31
  end
27
32
 
33
+ def from_type(type)
34
+ map(TYPE_TO_EMOJI[type])
35
+ end
36
+
28
37
  private
29
38
 
30
39
  attr_reader :template
@@ -0,0 +1,31 @@
1
+ module Danger
2
+ module Helpers
3
+ module MessageGroupsArrayHelper
4
+ FakeArray = Struct.new(:count) do
5
+ def empty?
6
+ count.zero?
7
+ end
8
+ end
9
+
10
+ def fake_warnings_array
11
+ FakeArray.new(counts[:warnings])
12
+ end
13
+
14
+ def fake_errors_array
15
+ FakeArray.new(counts[:errors])
16
+ end
17
+
18
+ def counts
19
+ return @counts if @counts
20
+
21
+ @counts = { warnings: 0, errors: 0 }
22
+ each do |message_group, counts|
23
+ group_stats = message_group.stats
24
+ @counts[:warnings] += group_stats[:warnings_count]
25
+ @counts[:errors] += group_stats[:errors_count]
26
+ end
27
+ @counts
28
+ end
29
+ end
30
+ end
31
+ end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "danger/helpers/comments_helper"
4
4
  require "danger/request_sources/bitbucket_cloud_api"
5
+ require "danger/danger_core/message_group"
5
6
 
6
7
  module Danger
7
8
  module RequestSources
@@ -12,6 +13,7 @@ module Danger
12
13
  def self.env_vars
13
14
  [
14
15
  "DANGER_BITBUCKETCLOUD_USERNAME",
16
+ "DANGER_BITBUCKETCLOUD_UUID",
15
17
  "DANGER_BITBUCKETCLOUD_PASSWORD"
16
18
  ]
17
19
  end
@@ -90,6 +92,50 @@ module Danger
90
92
  @api.post_comment(comment)
91
93
  end
92
94
 
95
+ def update_pr_by_line!(message_groups:,
96
+ danger_id: "danger",
97
+ new_comment: false,
98
+ remove_previous_comments: false)
99
+ if !new_comment || remove_previous_comments
100
+ delete_old_comments(danger_id: danger_id)
101
+ end
102
+
103
+ summary_body = generate_description(warnings: message_groups.fake_warnings_array,
104
+ errors: message_groups.fake_errors_array,
105
+ template: "bitbucket_server")
106
+ summary_body += "\n\n"
107
+
108
+
109
+ # this isn't the most elegant thing in the world, but we need the group
110
+ # with file: nil, line: nil so we can combine its info in with the
111
+ # summary_body
112
+ summary_group = message_groups.first
113
+ if summary_group && summary_group.file.nil? && summary_group.line.nil?
114
+ # remove summary_group from message_groups so it doesn't get a
115
+ # duplicate comment posted in the message_groups loop below
116
+ message_groups.shift
117
+ else
118
+ summary_group = MessageGroup.new(file: nil, line: nil)
119
+ end
120
+
121
+ summary_body += generate_message_group_comment(
122
+ message_group: summary_group,
123
+ danger_id: danger_id,
124
+ template: "bitbucket_server_message_group"
125
+ )
126
+
127
+ @api.post_comment(summary_body)
128
+
129
+ message_groups.each do |message_group|
130
+ body = generate_message_group_comment(message_group: message_group,
131
+ danger_id: danger_id,
132
+ template: "bitbucket_server_message_group")
133
+ @api.post_comment(body,
134
+ file: message_group.file,
135
+ line: message_group.line)
136
+ end
137
+ end
138
+
93
139
  def update_inline_comments_for_kind!(kind, messages, danger_id: "danger")
94
140
  emoji = { warnings: "warning", errors: "no_entry_sign", messages: "book" }[kind]
95
141
 
@@ -6,8 +6,10 @@ module Danger
6
6
  module RequestSources
7
7
  class BitbucketCloudAPI
8
8
  attr_accessor :host, :project, :slug, :access_token, :pull_request_id
9
+ attr_reader :my_uuid
9
10
 
10
11
  def initialize(repo_slug, pull_request_id, branch_name, environment)
12
+ initialize_my_uuid(environment["DANGER_BITBUCKETCLOUD_UUID"])
11
13
  @username = environment["DANGER_BITBUCKETCLOUD_USERNAME"]
12
14
  @password = environment["DANGER_BITBUCKETCLOUD_PASSWORD"]
13
15
  self.project, self.slug = repo_slug.split("/")
@@ -16,6 +18,17 @@ module Danger
16
18
  self.host = "https://bitbucket.org/"
17
19
  end
18
20
 
21
+ def initialize_my_uuid(uuid)
22
+ return if uuid.nil?
23
+ return @my_uuid = uuid if uuid.empty?
24
+
25
+ if uuid.start_with?("{") && uuid.end_with?("}")
26
+ @my_uuid = uuid
27
+ else
28
+ @my_uuid = "{#{uuid}}"
29
+ end
30
+ end
31
+
19
32
  def inspect
20
33
  inspected = super
21
34
 
@@ -27,12 +40,9 @@ module Danger
27
40
  end
28
41
 
29
42
  def credentials_given?
30
- @username && !@username.empty? && @password && !@password.empty?
31
- end
32
-
33
- def my_uuid
34
- uri = URI("https://api.bitbucket.org/2.0/users/#{@username}")
35
- @my_uuid ||= fetch_json(uri)[:uuid]
43
+ @my_uuid && !@my_uuid.empty? &&
44
+ @username && !@username.empty? &&
45
+ @password && !@password.empty?
36
46
  end
37
47
 
38
48
  def pull_request(*)
@@ -157,7 +167,9 @@ module Danger
157
167
  end
158
168
 
159
169
  def credentials_not_available
160
- "Credentials not available. Provide DANGER_BITBUCKETCLOUD_USERNAME and DANGER_BITBUCKETCLOUD_PASSWORD as environment variables."
170
+ "Credentials not available. Provide DANGER_BITBUCKETCLOUD_USERNAME, " \
171
+ "DANGER_BITBUCKETCLOUD_UUID, and DANGER_BITBUCKETCLOUD_PASSWORD " \
172
+ "as environment variables."
161
173
  end
162
174
 
163
175
  def error_fetching_json(url, status_code)
@@ -1,4 +1,4 @@
1
1
  module Danger
2
- VERSION = "6.3.2".freeze
2
+ VERSION = "7.0.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: 6.3.2
4
+ version: 7.0.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: 2020-03-26 00:00:00.000000000 Z
12
+ date: 2020-04-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: claide
@@ -71,16 +71,22 @@ dependencies:
71
71
  name: faraday
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - "~>"
74
+ - - ">="
75
75
  - !ruby/object:Gem::Version
76
- version: '0.9'
76
+ version: 0.9.0
77
+ - - "<"
78
+ - !ruby/object:Gem::Version
79
+ version: '2.0'
77
80
  type: :runtime
78
81
  prerelease: false
79
82
  version_requirements: !ruby/object:Gem::Requirement
80
83
  requirements:
81
- - - "~>"
84
+ - - ">="
82
85
  - !ruby/object:Gem::Version
83
- version: '0.9'
86
+ version: 0.9.0
87
+ - - "<"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
84
90
  - !ruby/object:Gem::Dependency
85
91
  name: faraday-http-cache
86
92
  requirement: !ruby/object:Gem::Requirement
@@ -250,6 +256,7 @@ files:
250
256
  - lib/danger/commands/systems.rb
251
257
  - lib/danger/comment_generators/bitbucket_server.md.erb
252
258
  - lib/danger/comment_generators/bitbucket_server_inline.md.erb
259
+ - lib/danger/comment_generators/bitbucket_server_message_group.md.erb
253
260
  - lib/danger/comment_generators/github.md.erb
254
261
  - lib/danger/comment_generators/github_inline.md.erb
255
262
  - lib/danger/comment_generators/gitlab.md.erb
@@ -283,6 +290,7 @@ files:
283
290
  - lib/danger/helpers/comments_parsing_helper.rb
284
291
  - lib/danger/helpers/emoji_mapper.rb
285
292
  - lib/danger/helpers/find_max_num_violations.rb
293
+ - lib/danger/helpers/message_groups_array_helper.rb
286
294
  - lib/danger/plugin_support/gems_resolver.rb
287
295
  - lib/danger/plugin_support/plugin.rb
288
296
  - lib/danger/plugin_support/plugin_file_resolver.rb