danger 2.0.1 → 2.1.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.
@@ -23,9 +23,15 @@ module Danger
23
23
  # @example Warn when there are merge commits in the diff
24
24
  #
25
25
  # if commits.any? { |c| c.message =~ /^Merge branch 'master'/ }
26
- # warn 'Please rebase to get rid of the merge commits in this PR'
26
+ # warn 'Please rebase to get rid of the merge commits in this PR'
27
27
  # end
28
28
  #
29
+ # @example Warn when somebody tries to add nokogiri to the project
30
+ #
31
+ # diff = git.diff_for_file["Gemfile.lock"]
32
+ # if diff && diff.patch =~ "nokogiri"
33
+ # warn 'Please do not add nokogiri to the project. Thank you.'
34
+ # end
29
35
  #
30
36
  # @see danger/danger
31
37
  # @tags core, git
@@ -100,5 +106,13 @@ module Danger
100
106
  def commits
101
107
  @git.log.to_a
102
108
  end
109
+
110
+ # @!group Git Metadata
111
+ # Details for a specific file in this diff
112
+ # @return [Git::Diff::DiffFile] from the gem `git`
113
+ #
114
+ def diff_for_file(file)
115
+ modified_files.include?(file) ? @git.diff[file] : nil
116
+ end
103
117
  end
104
118
  end
@@ -71,11 +71,16 @@ module Danger
71
71
  #
72
72
  # @see danger/danger
73
73
  # @tags core, github
74
-
74
+ #
75
75
  class DangerfileGitHubPlugin < Plugin
76
+ # So that this init can fail.
77
+ def self.new(dangerfile)
78
+ return nil if dangerfile.env.request_source.class != Danger::RequestSources::GitHub
79
+ super
80
+ end
81
+
76
82
  def initialize(dangerfile)
77
83
  super(dangerfile)
78
- return nil unless dangerfile.env.request_source.class == Danger::RequestSources::GitHub
79
84
 
80
85
  @github = dangerfile.env.request_source
81
86
  end
@@ -177,16 +182,23 @@ module Danger
177
182
  end
178
183
 
179
184
  # @!group GitHub Misc
180
- # Returns a HTML anchor for a file, or files in the head repository. An example would be:
181
- # `<a href='https://github.com/artsy/eigen/blob/561827e46167077b5e53515b4b7349b8ae04610b/file.txt'>file.txt</a>`
185
+ # Returns a list of HTML anchors for a file, or files in the head repository. An example would be:
186
+ # `<a href='https://github.com/artsy/eigen/blob/561827e46167077b5e53515b4b7349b8ae04610b/file.txt'>file.txt</a>`. It returns a string of multiple anchors if passed an array.
187
+ # @param [String or Array<String>] paths
188
+ # A list of strings to convert to github anchors
189
+ # @param [Bool] full_path
190
+ # Shows the full path as the link's text, defaults to `true`.
191
+ #
182
192
  # @return [String]
183
- def html_link(paths)
193
+ def html_link(paths, full_path: true)
184
194
  paths = [paths] unless paths.kind_of?(Array)
185
195
  commit = head_commit
186
196
  repo = pr_json[:head][:repo][:html_url]
197
+
187
198
  paths = paths.map do |path|
188
- path_with_slash = "/#{path}" unless path.start_with? "/"
189
- create_link("#{repo}/blob/#{commit}#{path_with_slash}", path)
199
+ url_path = path.start_with?("/") ? path : "/#{path}"
200
+ text = full_path ? path : File.basename(path)
201
+ create_link("#{repo}/blob/#{commit}#{url_path}", text)
190
202
  end
191
203
 
192
204
  return paths.first if paths.count < 2
@@ -0,0 +1,105 @@
1
+ require "redcarpet"
2
+
3
+ module Danger
4
+ module Helpers
5
+ module CommentsHelper
6
+ def markdown_parser
7
+ @markdown_parser ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML.new(hard_wrap: true), no_intra_emphasis: true)
8
+ end
9
+
10
+ def parse_tables_from_comment(comment)
11
+ comment.split("</table>")
12
+ end
13
+
14
+ def violations_from_table(table)
15
+ regex = %r{<td data-sticky="true">(?:<del>)?(.*?)(?:</del>)?\s*</td>}im
16
+ table.scan(regex).flatten.map(&:strip)
17
+ end
18
+
19
+ def process_markdown(violation)
20
+ html = markdown_parser.render(violation.message)
21
+ # Remove the outer `<p>`, the -5 represents a newline + `</p>`
22
+ html = html[3...-5] if html.start_with? "<p>"
23
+ Violation.new(html, violation.sticky)
24
+ end
25
+
26
+ def parse_comment(comment)
27
+ tables = parse_tables_from_comment(comment)
28
+ violations = {}
29
+ tables.each do |table|
30
+ next unless table =~ %r{<th width="100%"(.*?)</th>}im
31
+ title = Regexp.last_match(1)
32
+ kind = table_kind_from_title(title)
33
+ next unless kind
34
+
35
+ violations[kind] = violations_from_table(table)
36
+ end
37
+
38
+ violations.reject { |_, v| v.empty? }
39
+ end
40
+
41
+ def table(name, emoji, violations, all_previous_violations)
42
+ content = violations.map { |v| process_markdown(v) }.uniq
43
+ kind = table_kind_from_title(name)
44
+ previous_violations = all_previous_violations[kind] || []
45
+ messages = content.map(&:message)
46
+ resolved_violations = previous_violations.uniq - messages
47
+ count = content.count
48
+
49
+ {
50
+ name: name,
51
+ emoji: emoji,
52
+ content: content,
53
+ resolved: resolved_violations,
54
+ count: count
55
+ }
56
+ end
57
+
58
+ def table_kind_from_title(title)
59
+ if title =~ /error/i
60
+ :error
61
+ elsif title =~ /warning/i
62
+ :warning
63
+ elsif title =~ /message/i
64
+ :message
65
+ end
66
+ end
67
+
68
+ def generate_comment(warnings: [], errors: [], messages: [], markdowns: [], previous_violations: {}, danger_id: "danger", template: "github")
69
+ require "erb"
70
+
71
+ md_template = File.join(Danger.gem_path, "lib/danger/comment_generators/#{template}.md.erb")
72
+
73
+ # erb: http://www.rrn.dk/rubys-erb-templating-system
74
+ # for the extra args: http://stackoverflow.com/questions/4632879/erb-template-removing-the-trailing-line
75
+ @tables = [
76
+ table("Error", "no_entry_sign", errors, previous_violations),
77
+ table("Warning", "warning", warnings, previous_violations),
78
+ table("Message", "book", messages, previous_violations)
79
+ ]
80
+ @markdowns = markdowns
81
+ @danger_id = danger_id
82
+
83
+ return ERB.new(File.read(md_template), 0, "-").result(binding)
84
+ end
85
+
86
+ def generate_description(warnings: nil, errors: nil)
87
+ if errors.empty? && warnings.empty?
88
+ return "All green. #{random_compliment}"
89
+ else
90
+ message = "⚠ "
91
+ message += "#{'Error'.danger_pluralize(errors.count)}. " unless errors.empty?
92
+ message += "#{'Warning'.danger_pluralize(warnings.count)}. " unless warnings.empty?
93
+ message += "Don't worry, everything is fixable."
94
+ return message
95
+ end
96
+ end
97
+
98
+ def random_compliment
99
+ compliment = ["Well done.", "Congrats.", "Woo!",
100
+ "Yay.", "Jolly good show.", "Good on 'ya.", "Nice work."]
101
+ compliment.sample
102
+ end
103
+ end
104
+ end
105
+ end
@@ -41,7 +41,7 @@ module Danger
41
41
  end
42
42
  # When empty, imply you want to test the current lib folder as a plugin
43
43
  else
44
- Dir.glob(File.join(".", "lib/*.rb")).map { |path| File.expand_path(path) }
44
+ Dir.glob(File.join(".", "lib/**/*.rb")).map { |path| File.expand_path(path) }
45
45
  end
46
46
  end
47
47
  end
@@ -1,4 +1,4 @@
1
- require 'json'
1
+ require "json"
2
2
 
3
3
  =begin
4
4
 
@@ -171,7 +171,7 @@ module Danger
171
171
  attribute_meths = klass.attributes[:instance].values.map(&:values).flatten
172
172
 
173
173
  methods = klass.meths - klass.inherited_meths - attribute_meths
174
- usable_methods = methods.select { |m| m.visibility == :public }.reject { |m| m.name == :initialize || m.name == :instance_name }
174
+ usable_methods = methods.select { |m| m.visibility == :public }.reject { |m| m.name == :initialize || m.name == :instance_name || m.name == :new }
175
175
 
176
176
  plugin_gem = klass.file.include?("gems") ? klass.file.split("gems/").last.split("-")[0..-2].join("-") : nil
177
177
  # Pull out the gem's path ( to make relative file paths )
@@ -11,14 +11,16 @@
11
11
 
12
12
  <%- unless plugin["attributes"].empty? %>
13
13
  #### Attributes
14
- <%- plugin["attributes"].each do |attribute| %><tr>
14
+ <%- plugin["attributes"].each do |attribute| %>
15
15
  `<%= attribute.keys.first %>` - <%= attribute.values.first["write"]["body_md"] %>
16
16
  <%- end %>
17
17
  <%- end %>
18
18
 
19
+ <%- unless plugin["methods"].empty? %>
19
20
  #### Methods
20
21
  <%- plugin["methods"].each do |method| %>
21
22
  `<%= method["name"] %>` - <%= method["body_md"] %>
22
23
  <%- end %>
24
+ <%- end %>
23
25
 
24
26
  <% end %>
@@ -1,10 +1,12 @@
1
1
  # coding: utf-8
2
2
  require 'octokit'
3
- require 'redcarpet'
3
+ require 'danger/helpers/comments_helper'
4
4
 
5
5
  module Danger
6
6
  module RequestSources
7
7
  class GitHub < RequestSource
8
+ include Danger::Helpers::CommentsHelper
9
+
8
10
  attr_accessor :pr_json, :issue_json, :support_tokenless_auth
9
11
 
10
12
  def initialize(ci_source, environment)
@@ -32,10 +34,6 @@ module Danger
32
34
  @client ||= Octokit::Client.new(access_token: @token)
33
35
  end
34
36
 
35
- def markdown_parser
36
- @markdown_parser ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, no_intra_emphasis: true)
37
- end
38
-
39
37
  def pr_diff
40
38
  @pr_diff ||= client.pull_request(ci_source.repo_slug, ci_source.pull_request_id, accept: 'application/vnd.github.v3.diff')
41
39
  end
@@ -93,7 +91,8 @@ module Danger
93
91
  messages: messages,
94
92
  markdowns: markdowns,
95
93
  previous_violations: previous_violations,
96
- danger_id: danger_id)
94
+ danger_id: danger_id,
95
+ template: 'github')
97
96
 
98
97
  if editable_issues.empty?
99
98
  comment_result = client.add_comment(ci_source.repo_slug, ci_source.pull_request_id, body)
@@ -112,7 +111,7 @@ module Danger
112
111
 
113
112
  def submit_pull_request_status!(warnings: [], errors: [], details_url: [])
114
113
  status = (errors.count.zero? ? 'success' : 'failure')
115
- message = generate_github_description(warnings: warnings, errors: errors)
114
+ message = generate_description(warnings: warnings, errors: errors)
116
115
 
117
116
  latest_pr_commit_ref = self.pr_json[:head][:sha]
118
117
 
@@ -154,93 +153,6 @@ module Danger
154
153
  end
155
154
  end
156
155
 
157
- def random_compliment
158
- compliment = ['Well done.', 'Congrats.', 'Woo!',
159
- 'Yay.', 'Jolly good show.', "Good on 'ya.", 'Nice work.']
160
- compliment.sample
161
- end
162
-
163
- def generate_github_description(warnings: nil, errors: nil)
164
- if errors.empty? && warnings.empty?
165
- return "All green. #{random_compliment}"
166
- else
167
- message = "⚠ "
168
- message += "#{'Error'.danger_pluralize(errors.count)}. " unless errors.empty?
169
- message += "#{'Warning'.danger_pluralize(warnings.count)}. " unless warnings.empty?
170
- message += "Don't worry, everything is fixable."
171
- return message
172
- end
173
- end
174
-
175
- def generate_comment(warnings: [], errors: [], messages: [], markdowns: [], previous_violations: {}, danger_id: 'danger')
176
- require 'erb'
177
-
178
- md_template = File.join(Danger.gem_path, 'lib/danger/comment_generators/github.md.erb')
179
-
180
- # erb: http://www.rrn.dk/rubys-erb-templating-system
181
- # for the extra args: http://stackoverflow.com/questions/4632879/erb-template-removing-the-trailing-line
182
- @tables = [
183
- table('Error', 'no_entry_sign', errors, previous_violations),
184
- table('Warning', 'warning', warnings, previous_violations),
185
- table('Message', 'book', messages, previous_violations)
186
- ]
187
- @markdowns = markdowns
188
- @danger_id = danger_id
189
-
190
- return ERB.new(File.read(md_template), 0, '-').result(binding)
191
- end
192
-
193
- def table(name, emoji, violations, all_previous_violations)
194
- content = violations.map { |v| process_markdown(v) }.uniq
195
- kind = table_kind_from_title(name)
196
- previous_violations = all_previous_violations[kind] || []
197
- messages = content.map(&:message)
198
- resolved_violations = previous_violations.uniq - messages
199
- count = content.count
200
- { name: name, emoji: emoji, content: content, resolved: resolved_violations, count: count }
201
- end
202
-
203
- def parse_comment(comment)
204
- tables = parse_tables_from_comment(comment)
205
- violations = {}
206
- tables.each do |table|
207
- next unless table =~ %r{<th width="100%"(.*?)</th>}im
208
- title = Regexp.last_match(1)
209
- kind = table_kind_from_title(title)
210
- next unless kind
211
-
212
- violations[kind] = violations_from_table(table)
213
- end
214
-
215
- violations.reject { |_, v| v.empty? }
216
- end
217
-
218
- def violations_from_table(table)
219
- regex = %r{<td data-sticky="true">(?:<del>)?(.*?)(?:</del>)?\s*</td>}im
220
- table.scan(regex).flatten.map(&:strip)
221
- end
222
-
223
- def table_kind_from_title(title)
224
- if title =~ /error/i
225
- :error
226
- elsif title =~ /warning/i
227
- :warning
228
- elsif title =~ /message/i
229
- :message
230
- end
231
- end
232
-
233
- def parse_tables_from_comment(comment)
234
- comment.split("</table>")
235
- end
236
-
237
- def process_markdown(violation)
238
- html = markdown_parser.render(violation.message)
239
- # Remove the outer `<p>`, the -5 represents a newline + `</p>`
240
- html = html[3...-5] if html.start_with? "<p>"
241
- Violation.new(html, violation.sticky)
242
- end
243
-
244
156
  # @return [String] The organisation name, is nil if it can't be detected
245
157
  def organisation
246
158
  matched = self.issue_json[:repository_url].match(%r{repos\/(.*)\/})
@@ -18,7 +18,8 @@ module Danger
18
18
  raise "Subclass and overwrite initialize"
19
19
  end
20
20
 
21
- def validates?
21
+ # What does this do?
22
+ def validates_as_ci?
22
23
  !!self.scm.origins.match(%r{#{Regexp.escape self.host}(:|/)(?<repo_slug>.+/.+?)(?:\.git)?$})
23
24
  end
24
25
 
@@ -1,4 +1,4 @@
1
1
  module Danger
2
- VERSION = "2.0.1".freeze
2
+ VERSION = "2.1.0".freeze
3
3
  DESCRIPTION = "Automate your PR etiquette.".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: 2.0.1
4
+ version: 2.1.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: 2016-07-26 00:00:00.000000000 Z
12
+ date: 2016-07-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: claide
@@ -340,6 +340,7 @@ files:
340
340
  - lib/danger/commands/plugins/plugin_lint.rb
341
341
  - lib/danger/commands/plugins/plugin_readme.rb
342
342
  - lib/danger/commands/runner.rb
343
+ - lib/danger/commands/systems.rb
343
344
  - lib/danger/comment_generators/github.md.erb
344
345
  - lib/danger/core_ext/file_list.rb
345
346
  - lib/danger/core_ext/string.rb
@@ -353,6 +354,7 @@ files:
353
354
  - lib/danger/danger_core/plugins/dangerfile_messaging_plugin.rb
354
355
  - lib/danger/danger_core/standard_error.rb
355
356
  - lib/danger/danger_core/violation.rb
357
+ - lib/danger/helpers/comments_helper.rb
356
358
  - lib/danger/plugin_support/plugin.rb
357
359
  - lib/danger/plugin_support/plugin_file_resolver.rb
358
360
  - lib/danger/plugin_support/plugin_linter.rb
@@ -382,8 +384,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
382
384
  version: '0'
383
385
  requirements: []
384
386
  rubyforge_project:
385
- rubygems_version: 2.2.2
387
+ rubygems_version: 2.4.8
386
388
  signing_key:
387
389
  specification_version: 4
388
390
  summary: Automate your PR etiquette.
389
391
  test_files: []
392
+ has_rdoc: