danger 2.0.1 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: