danger 8.0.4
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 +7 -0
- data/LICENSE +22 -0
- data/README.md +94 -0
- data/bin/danger +5 -0
- data/lib/assets/DangerfileTemplate +13 -0
- data/lib/danger.rb +44 -0
- data/lib/danger/ci_source/appcenter.rb +55 -0
- data/lib/danger/ci_source/appveyor.rb +60 -0
- data/lib/danger/ci_source/azure_pipelines.rb +44 -0
- data/lib/danger/ci_source/bamboo.rb +41 -0
- data/lib/danger/ci_source/bitbucket_pipelines.rb +37 -0
- data/lib/danger/ci_source/bitrise.rb +65 -0
- data/lib/danger/ci_source/buddybuild.rb +62 -0
- data/lib/danger/ci_source/buildkite.rb +51 -0
- data/lib/danger/ci_source/ci_source.rb +37 -0
- data/lib/danger/ci_source/circle.rb +94 -0
- data/lib/danger/ci_source/circle_api.rb +51 -0
- data/lib/danger/ci_source/cirrus.rb +31 -0
- data/lib/danger/ci_source/code_build.rb +57 -0
- data/lib/danger/ci_source/codefresh.rb +53 -0
- data/lib/danger/ci_source/codeship.rb +44 -0
- data/lib/danger/ci_source/dotci.rb +52 -0
- data/lib/danger/ci_source/drone.rb +71 -0
- data/lib/danger/ci_source/github_actions.rb +43 -0
- data/lib/danger/ci_source/gitlab_ci.rb +86 -0
- data/lib/danger/ci_source/jenkins.rb +149 -0
- data/lib/danger/ci_source/local_git_repo.rb +119 -0
- data/lib/danger/ci_source/local_only_git_repo.rb +47 -0
- data/lib/danger/ci_source/screwdriver.rb +47 -0
- data/lib/danger/ci_source/semaphore.rb +37 -0
- data/lib/danger/ci_source/support/commits.rb +17 -0
- data/lib/danger/ci_source/support/find_repo_info_from_logs.rb +35 -0
- data/lib/danger/ci_source/support/find_repo_info_from_url.rb +42 -0
- data/lib/danger/ci_source/support/local_pull_request.rb +14 -0
- data/lib/danger/ci_source/support/no_pull_request.rb +7 -0
- data/lib/danger/ci_source/support/no_repo_info.rb +5 -0
- data/lib/danger/ci_source/support/pull_request_finder.rb +179 -0
- data/lib/danger/ci_source/support/remote_pull_request.rb +15 -0
- data/lib/danger/ci_source/support/repo_info.rb +10 -0
- data/lib/danger/ci_source/surf.rb +37 -0
- data/lib/danger/ci_source/teamcity.rb +161 -0
- data/lib/danger/ci_source/travis.rb +51 -0
- data/lib/danger/ci_source/vsts.rb +73 -0
- data/lib/danger/ci_source/xcode_server.rb +48 -0
- data/lib/danger/clients/rubygems_client.rb +14 -0
- data/lib/danger/commands/dangerfile/gem.rb +43 -0
- data/lib/danger/commands/dangerfile/init.rb +30 -0
- data/lib/danger/commands/dry_run.rb +54 -0
- data/lib/danger/commands/init.rb +297 -0
- data/lib/danger/commands/init_helpers/interviewer.rb +92 -0
- data/lib/danger/commands/local.rb +83 -0
- data/lib/danger/commands/local_helpers/http_cache.rb +36 -0
- data/lib/danger/commands/local_helpers/local_setup.rb +46 -0
- data/lib/danger/commands/local_helpers/pry_setup.rb +31 -0
- data/lib/danger/commands/plugins/plugin_json.rb +46 -0
- data/lib/danger/commands/plugins/plugin_lint.rb +54 -0
- data/lib/danger/commands/plugins/plugin_readme.rb +45 -0
- data/lib/danger/commands/pr.rb +92 -0
- data/lib/danger/commands/runner.rb +94 -0
- data/lib/danger/commands/staging.rb +53 -0
- data/lib/danger/commands/systems.rb +43 -0
- data/lib/danger/comment_generators/bitbucket_server.md.erb +20 -0
- data/lib/danger/comment_generators/bitbucket_server_inline.md.erb +15 -0
- data/lib/danger/comment_generators/bitbucket_server_message_group.md.erb +12 -0
- data/lib/danger/comment_generators/github.md.erb +55 -0
- data/lib/danger/comment_generators/github_inline.md.erb +26 -0
- data/lib/danger/comment_generators/gitlab.md.erb +40 -0
- data/lib/danger/comment_generators/gitlab_inline.md.erb +26 -0
- data/lib/danger/comment_generators/vsts.md.erb +20 -0
- data/lib/danger/core_ext/file_list.rb +18 -0
- data/lib/danger/core_ext/string.rb +20 -0
- data/lib/danger/danger_core/dangerfile.rb +341 -0
- data/lib/danger/danger_core/dangerfile_dsl.rb +29 -0
- data/lib/danger/danger_core/dangerfile_generator.rb +11 -0
- data/lib/danger/danger_core/environment_manager.rb +123 -0
- data/lib/danger/danger_core/executor.rb +92 -0
- data/lib/danger/danger_core/message_aggregator.rb +49 -0
- data/lib/danger/danger_core/message_group.rb +68 -0
- data/lib/danger/danger_core/messages/base.rb +56 -0
- data/lib/danger/danger_core/messages/markdown.rb +42 -0
- data/lib/danger/danger_core/messages/violation.rb +54 -0
- data/lib/danger/danger_core/plugins/dangerfile_bitbucket_cloud_plugin.rb +144 -0
- data/lib/danger/danger_core/plugins/dangerfile_bitbucket_server_plugin.rb +211 -0
- data/lib/danger/danger_core/plugins/dangerfile_danger_plugin.rb +248 -0
- data/lib/danger/danger_core/plugins/dangerfile_git_plugin.rb +158 -0
- data/lib/danger/danger_core/plugins/dangerfile_github_plugin.rb +254 -0
- data/lib/danger/danger_core/plugins/dangerfile_gitlab_plugin.rb +240 -0
- data/lib/danger/danger_core/plugins/dangerfile_local_only_plugin.rb +42 -0
- data/lib/danger/danger_core/plugins/dangerfile_messaging_plugin.rb +218 -0
- data/lib/danger/danger_core/plugins/dangerfile_vsts_plugin.rb +191 -0
- data/lib/danger/danger_core/standard_error.rb +143 -0
- data/lib/danger/helpers/array_subclass.rb +61 -0
- data/lib/danger/helpers/comment.rb +32 -0
- data/lib/danger/helpers/comments_helper.rb +178 -0
- data/lib/danger/helpers/comments_parsing_helper.rb +70 -0
- data/lib/danger/helpers/emoji_mapper.rb +41 -0
- data/lib/danger/helpers/find_max_num_violations.rb +31 -0
- data/lib/danger/helpers/message_groups_array_helper.rb +31 -0
- data/lib/danger/plugin_support/gems_resolver.rb +77 -0
- data/lib/danger/plugin_support/plugin.rb +49 -0
- data/lib/danger/plugin_support/plugin_file_resolver.rb +30 -0
- data/lib/danger/plugin_support/plugin_linter.rb +161 -0
- data/lib/danger/plugin_support/plugin_parser.rb +199 -0
- data/lib/danger/plugin_support/templates/readme_table.html.erb +26 -0
- data/lib/danger/request_sources/bitbucket_cloud.rb +171 -0
- data/lib/danger/request_sources/bitbucket_cloud_api.rb +181 -0
- data/lib/danger/request_sources/bitbucket_server.rb +105 -0
- data/lib/danger/request_sources/bitbucket_server_api.rb +117 -0
- data/lib/danger/request_sources/github/github.rb +530 -0
- data/lib/danger/request_sources/github/github_review.rb +126 -0
- data/lib/danger/request_sources/github/github_review_resolver.rb +19 -0
- data/lib/danger/request_sources/github/github_review_unsupported.rb +25 -0
- data/lib/danger/request_sources/gitlab.rb +525 -0
- data/lib/danger/request_sources/local_only.rb +53 -0
- data/lib/danger/request_sources/request_source.rb +85 -0
- data/lib/danger/request_sources/support/get_ignored_violation.rb +17 -0
- data/lib/danger/request_sources/vsts.rb +118 -0
- data/lib/danger/request_sources/vsts_api.rb +138 -0
- data/lib/danger/scm_source/git_repo.rb +181 -0
- data/lib/danger/version.rb +4 -0
- metadata +339 -0
@@ -0,0 +1,143 @@
|
|
1
|
+
require "claide"
|
2
|
+
require "claide/informative_error"
|
3
|
+
|
4
|
+
module Danger
|
5
|
+
# From below here - this entire file was taken verbatim for CocoaPods-Core.
|
6
|
+
|
7
|
+
#-------------------------------------------------------------------------#
|
8
|
+
|
9
|
+
# Wraps an exception raised by a DSL file in order to show to the user the
|
10
|
+
# contents of the line that raised the exception.
|
11
|
+
#
|
12
|
+
class DSLError < StandardError
|
13
|
+
# @return [String] the description that should be presented to the user.
|
14
|
+
#
|
15
|
+
attr_reader :description
|
16
|
+
|
17
|
+
# @return [String] the path of the dsl file that raised the exception.
|
18
|
+
#
|
19
|
+
attr_reader :dsl_path
|
20
|
+
|
21
|
+
# @return [Exception] the backtrace of the exception raised by the
|
22
|
+
# evaluation of the dsl file.
|
23
|
+
#
|
24
|
+
attr_reader :backtrace
|
25
|
+
|
26
|
+
# @param [Exception] backtrace @see backtrace
|
27
|
+
# @param [String] dsl_path @see dsl_path
|
28
|
+
#
|
29
|
+
def initialize(description, dsl_path, backtrace, contents = nil)
|
30
|
+
@description = description
|
31
|
+
@dsl_path = dsl_path
|
32
|
+
@backtrace = backtrace
|
33
|
+
@contents = contents
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String] the contents of the DSL that cause the exception to
|
37
|
+
# be raised.
|
38
|
+
#
|
39
|
+
def contents
|
40
|
+
@contents ||= begin
|
41
|
+
dsl_path && File.exist?(dsl_path) && File.read(dsl_path)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# The message of the exception reports the content of podspec for the
|
46
|
+
# line that generated the original exception.
|
47
|
+
#
|
48
|
+
# @example Output
|
49
|
+
#
|
50
|
+
# Invalid podspec at `RestKit.podspec` - undefined method
|
51
|
+
# `exclude_header_search_paths=' for #<Pod::Specification for
|
52
|
+
# `RestKit/Network (0.9.3)`>
|
53
|
+
#
|
54
|
+
# from spec-repos/master/RestKit/0.9.3/RestKit.podspec:36
|
55
|
+
# -------------------------------------------
|
56
|
+
# # because it would break: #import <CoreData/CoreData.h>
|
57
|
+
# > ns.exclude_header_search_paths = 'Code/RestKit.h'
|
58
|
+
# end
|
59
|
+
# -------------------------------------------
|
60
|
+
#
|
61
|
+
# @return [String] the message of the exception.
|
62
|
+
#
|
63
|
+
def message
|
64
|
+
@message ||= begin
|
65
|
+
description, stacktrace = parse.values_at(:description, :stacktrace)
|
66
|
+
|
67
|
+
msg = description
|
68
|
+
msg = msg.red if msg.respond_to?(:red)
|
69
|
+
msg << stacktrace if stacktrace
|
70
|
+
msg
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_markdown
|
75
|
+
@markdown ||= begin
|
76
|
+
description, stacktrace = parse.values_at(:description, :stacktrace)
|
77
|
+
|
78
|
+
# Highlight failed method in markdown
|
79
|
+
description = description.tr("'", "`")
|
80
|
+
|
81
|
+
# Escape markdown brackets
|
82
|
+
description = description.gsub(/<|>/) { |bracket| "\\#{bracket}" }
|
83
|
+
|
84
|
+
md = "## Danger has errored"
|
85
|
+
md << "#{description}\n"
|
86
|
+
md << "```#{stacktrace}```" if stacktrace
|
87
|
+
|
88
|
+
Markdown.new(md, nil, nil)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def parse
|
95
|
+
result = {}
|
96
|
+
|
97
|
+
trace_line, description = parse_line_number_from_description
|
98
|
+
latest_version = Danger.danger_outdated?
|
99
|
+
|
100
|
+
result[:description] = "\n[!] #{description}"
|
101
|
+
result[:description] << upgrade_message(latest_version) if latest_version
|
102
|
+
|
103
|
+
return result unless backtrace && dsl_path && contents
|
104
|
+
|
105
|
+
trace_line = backtrace.find { |l| l.include?(dsl_path.to_s) } || trace_line
|
106
|
+
return result unless trace_line
|
107
|
+
line_numer = trace_line.split(":")[1].to_i - 1
|
108
|
+
return result unless line_numer
|
109
|
+
|
110
|
+
lines = contents.lines
|
111
|
+
indent = " # "
|
112
|
+
indicator = indent.tr("#", ">")
|
113
|
+
first_line = line_numer.zero?
|
114
|
+
last_line = (line_numer == (lines.count - 1))
|
115
|
+
|
116
|
+
result[:stacktrace] = "\n"
|
117
|
+
result[:stacktrace] << "#{indent}from #{trace_line.gsub(/:in.*$/, '')}\n"
|
118
|
+
result[:stacktrace] << "#{indent}-------------------------------------------\n"
|
119
|
+
result[:stacktrace] << "#{indent}#{lines[line_numer - 1]}" unless first_line
|
120
|
+
result[:stacktrace] << "#{indicator}#{lines[line_numer]}"
|
121
|
+
result[:stacktrace] << "#{indent}#{lines[line_numer + 1]}" unless last_line
|
122
|
+
result[:stacktrace] << "\n" unless result[:stacktrace].end_with?("\n")
|
123
|
+
result[:stacktrace] << "#{indent}-------------------------------------------\n"
|
124
|
+
|
125
|
+
result
|
126
|
+
end
|
127
|
+
|
128
|
+
def parse_line_number_from_description
|
129
|
+
description = self.description
|
130
|
+
if dsl_path && description =~ /((#{Regexp.quote File.expand_path(dsl_path)}|#{Regexp.quote dsl_path.to_s}):\d+)/
|
131
|
+
trace_line = Regexp.last_match[1]
|
132
|
+
description = description.sub(/#{Regexp.quote trace_line}:\s*/, "")
|
133
|
+
end
|
134
|
+
[trace_line, description]
|
135
|
+
end
|
136
|
+
|
137
|
+
def upgrade_message(latest_version)
|
138
|
+
". Updating the Danger gem might fix the issue. "\
|
139
|
+
"Your Danger version: #{Danger::VERSION}, "\
|
140
|
+
"latest Danger version: #{latest_version}\n"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Danger
|
2
|
+
module Helpers
|
3
|
+
module ArraySubclass
|
4
|
+
include Comparable
|
5
|
+
|
6
|
+
def initialize(array)
|
7
|
+
@__array__ = array
|
8
|
+
end
|
9
|
+
|
10
|
+
def kind_of?(compare_class)
|
11
|
+
return true if compare_class == self.class
|
12
|
+
|
13
|
+
dummy.kind_of?(compare_class)
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(name, *args, &block)
|
17
|
+
super unless __array__.respond_to?(name)
|
18
|
+
|
19
|
+
respond_to_method(name, *args, &block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def respond_to_missing?(name)
|
23
|
+
__array__.respond_to?(name) || super
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_a
|
27
|
+
__array__
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_ary
|
31
|
+
__array__
|
32
|
+
end
|
33
|
+
|
34
|
+
def <=>(other)
|
35
|
+
return unless other.kind_of?(self.class)
|
36
|
+
|
37
|
+
__array__ <=> other.instance_variable_get(:@__array__)
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
attr_accessor :__array__
|
43
|
+
|
44
|
+
def dummy
|
45
|
+
Class.new(Array).new
|
46
|
+
end
|
47
|
+
|
48
|
+
def respond_to_method(name, *args, &block)
|
49
|
+
result = __array__.send(name, *args, &block)
|
50
|
+
return result unless result.kind_of?(Array)
|
51
|
+
|
52
|
+
if name =~ /!/
|
53
|
+
__array__ = result
|
54
|
+
self
|
55
|
+
else
|
56
|
+
self.class.new(result)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Danger
|
2
|
+
class Comment
|
3
|
+
attr_reader :id, :body
|
4
|
+
|
5
|
+
def initialize(id, body, inline = nil)
|
6
|
+
@id = id
|
7
|
+
@body = body
|
8
|
+
@inline = inline
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.from_github(comment)
|
12
|
+
self.new(comment["id"], comment["body"])
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_gitlab(comment)
|
16
|
+
if comment.respond_to?(:id) && comment.respond_to?(:body)
|
17
|
+
type = comment.respond_to?(:type) ? comment.type : nil
|
18
|
+
self.new(comment.id, comment.body, type == "DiffNote")
|
19
|
+
else
|
20
|
+
self.new(comment["id"], comment["body"], comment["type"] == "DiffNote")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def generated_by_danger?(danger_id)
|
25
|
+
body.include?("\"generated_by_#{danger_id}\"")
|
26
|
+
end
|
27
|
+
|
28
|
+
def inline?
|
29
|
+
@inline.nil? ? body.include?("") : @inline
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
require "kramdown"
|
2
|
+
require "danger/helpers/comments_parsing_helper"
|
3
|
+
require "danger/helpers/emoji_mapper"
|
4
|
+
require "danger/helpers/find_max_num_violations"
|
5
|
+
|
6
|
+
module Danger
|
7
|
+
module Helpers
|
8
|
+
module CommentsHelper
|
9
|
+
# This might be a bit weird, but table_kind_from_title is a shared dependency for
|
10
|
+
# parsing and generating. And rubocop was adamant about file size so...
|
11
|
+
include Danger::Helpers::CommentsParsingHelper
|
12
|
+
|
13
|
+
def markdown_parser(text)
|
14
|
+
Kramdown::Document.new(text, input: "GFM")
|
15
|
+
end
|
16
|
+
|
17
|
+
# !@group Extension points
|
18
|
+
# Produces a markdown link to the file the message points to
|
19
|
+
#
|
20
|
+
# request_source implementations are invited to override this method with their
|
21
|
+
# vendor specific link.
|
22
|
+
#
|
23
|
+
# @param [Violation or Markdown] message
|
24
|
+
# @param [Bool] Should hide any generated link created
|
25
|
+
#
|
26
|
+
# @return [String] The Markdown compatible link
|
27
|
+
def markdown_link_to_message(message, _)
|
28
|
+
"#{message.file}#L#{message.line}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# !@group Extension points
|
32
|
+
# Determine whether two messages are equivalent
|
33
|
+
#
|
34
|
+
# request_source implementations are invited to override this method.
|
35
|
+
# This is mostly here to enable sources to detect when inlines change only in their
|
36
|
+
# commit hash and not in content per-se. since the link is implementation dependant
|
37
|
+
# so should be the comparison.
|
38
|
+
#
|
39
|
+
# @param [Violation or Markdown] m1
|
40
|
+
# @param [Violation or Markdown] m2
|
41
|
+
#
|
42
|
+
# @return [Boolean] whether they represent the same message
|
43
|
+
def messages_are_equivalent(m1, m2)
|
44
|
+
m1 == m2
|
45
|
+
end
|
46
|
+
|
47
|
+
def process_markdown(violation, hide_link = false)
|
48
|
+
message = violation.message
|
49
|
+
message = "#{markdown_link_to_message(violation, hide_link)}#{message}" if violation.file && violation.line
|
50
|
+
|
51
|
+
html = markdown_parser(message).to_html
|
52
|
+
# Remove the outer `<p>` and `</p>`.
|
53
|
+
html = html.strip.sub(%r{\A<p>(.*)</p>\z}m, '\1')
|
54
|
+
Violation.new(html, violation.sticky, violation.file, violation.line)
|
55
|
+
end
|
56
|
+
|
57
|
+
def table(name, emoji, violations, all_previous_violations, template: "github")
|
58
|
+
content = violations
|
59
|
+
content = content.map { |v| process_markdown(v) } unless ["bitbucket_server", "vsts"].include?(template)
|
60
|
+
|
61
|
+
kind = table_kind_from_title(name)
|
62
|
+
previous_violations = all_previous_violations[kind] || []
|
63
|
+
resolved_violations = previous_violations.reject do |pv|
|
64
|
+
content.count { |v| messages_are_equivalent(v, pv) } > 0
|
65
|
+
end
|
66
|
+
|
67
|
+
resolved_messages = resolved_violations.map(&:message).uniq
|
68
|
+
count = content.count
|
69
|
+
|
70
|
+
{
|
71
|
+
name: name,
|
72
|
+
emoji: emoji,
|
73
|
+
content: content,
|
74
|
+
resolved: resolved_messages,
|
75
|
+
count: count
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
def apply_template(tables: [], markdowns: [], danger_id: "danger", template: "github", request_source: template)
|
80
|
+
require "erb"
|
81
|
+
|
82
|
+
md_template = File.join(Danger.gem_path, "lib/danger/comment_generators/#{template}.md.erb")
|
83
|
+
|
84
|
+
# erb: http://www.rrn.dk/rubys-erb-templating-system
|
85
|
+
# for the extra args: http://stackoverflow.com/questions/4632879/erb-template-removing-the-trailing-line
|
86
|
+
@tables = tables
|
87
|
+
@markdowns = markdowns.map(&:message)
|
88
|
+
@danger_id = danger_id
|
89
|
+
@emoji_mapper = EmojiMapper.new(request_source.sub("_inline",""))
|
90
|
+
|
91
|
+
return ERB.new(File.read(md_template), 0, "-").result(binding)
|
92
|
+
end
|
93
|
+
|
94
|
+
def generate_comment(warnings: [], errors: [], messages: [], markdowns: [], previous_violations: {}, danger_id: "danger", template: "github")
|
95
|
+
apply_template(
|
96
|
+
tables: [
|
97
|
+
table("Error", "no_entry_sign", errors, previous_violations, template: template),
|
98
|
+
table("Warning", "warning", warnings, previous_violations, template: template),
|
99
|
+
table("Message", "book", messages, previous_violations, template: template)
|
100
|
+
],
|
101
|
+
markdowns: markdowns,
|
102
|
+
danger_id: danger_id,
|
103
|
+
template: template
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
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: false,
|
132
|
+
template: "github")
|
133
|
+
apply_template(
|
134
|
+
tables: [{ content: [message], resolved: resolved, emoji: emoji }],
|
135
|
+
danger_id: danger_id,
|
136
|
+
template: "#{template}_inline"
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
def generate_inline_markdown_body(markdown, danger_id: "danger", template: "github")
|
141
|
+
apply_template(
|
142
|
+
markdowns: [markdown],
|
143
|
+
danger_id: danger_id,
|
144
|
+
template: "#{template}_inline"
|
145
|
+
)
|
146
|
+
end
|
147
|
+
|
148
|
+
def generate_description(warnings: nil, errors: nil, template: "github")
|
149
|
+
emoji_mapper = EmojiMapper.new(template)
|
150
|
+
if errors.empty? && warnings.empty?
|
151
|
+
return "All green. #{random_compliment}"
|
152
|
+
else
|
153
|
+
message = "#{emoji_mapper.map('warning')} "
|
154
|
+
message += "#{'Error'.danger_pluralize(errors.count)}. " unless errors.empty?
|
155
|
+
message += "#{'Warning'.danger_pluralize(warnings.count)}. " unless warnings.empty?
|
156
|
+
message += "Don't worry, everything is fixable."
|
157
|
+
return message
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def random_compliment
|
162
|
+
["Well done.", "Congrats.", "Woo!",
|
163
|
+
"Yay.", "Jolly good show.", "Good on 'ya.", "Nice work."].sample
|
164
|
+
end
|
165
|
+
|
166
|
+
private
|
167
|
+
|
168
|
+
def pluralize(string, count)
|
169
|
+
string.danger_pluralize(count)
|
170
|
+
end
|
171
|
+
|
172
|
+
def truncate(string)
|
173
|
+
max_message_length = 30
|
174
|
+
string.danger_truncate(max_message_length)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Danger
|
2
|
+
module Helpers
|
3
|
+
module CommentsParsingHelper
|
4
|
+
# !@group Extension points
|
5
|
+
# Produces a message-like from a row in a comment table
|
6
|
+
#
|
7
|
+
# @param [String] row
|
8
|
+
# The content of the row in the table
|
9
|
+
#
|
10
|
+
# @return [Violation or Markdown] the extracted message
|
11
|
+
def parse_message_from_row(row)
|
12
|
+
Violation.new(row, true)
|
13
|
+
end
|
14
|
+
|
15
|
+
def parse_tables_from_comment(comment)
|
16
|
+
comment.split("</table>")
|
17
|
+
end
|
18
|
+
|
19
|
+
def violations_from_table(table)
|
20
|
+
row_regex = %r{<td data-sticky="true">(?:<del>)?(.*?)(?:</del>)?\s*</td>}im
|
21
|
+
table.scan(row_regex).flatten.map do |row|
|
22
|
+
parse_message_from_row(row.strip)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse_comment(comment)
|
27
|
+
tables = parse_tables_from_comment(comment)
|
28
|
+
violations = {}
|
29
|
+
tables.each do |table|
|
30
|
+
match = danger_table?(table)
|
31
|
+
next unless match
|
32
|
+
title = match[1]
|
33
|
+
kind = table_kind_from_title(title)
|
34
|
+
next unless kind
|
35
|
+
|
36
|
+
violations[kind] = violations_from_table(table)
|
37
|
+
end
|
38
|
+
|
39
|
+
violations.reject { |_, v| v.empty? }
|
40
|
+
end
|
41
|
+
|
42
|
+
def table_kind_from_title(title)
|
43
|
+
if title =~ /error/i
|
44
|
+
:error
|
45
|
+
elsif title =~ /warning/i
|
46
|
+
:warning
|
47
|
+
elsif title =~ /message/i
|
48
|
+
:message
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
GITHUB_OLD_REGEX = %r{<th width="100%"(.*?)</th>}im
|
55
|
+
NEW_REGEX = %r{<th.*data-danger-table="true"(.*?)</th>}im
|
56
|
+
|
57
|
+
def danger_table?(table)
|
58
|
+
# The old GitHub specific method relied on
|
59
|
+
# the width of a `th` element to find the table
|
60
|
+
# title and determine if it was a danger table.
|
61
|
+
# The new method uses a more robust data-danger-table
|
62
|
+
# tag instead.
|
63
|
+
match = GITHUB_OLD_REGEX.match(table)
|
64
|
+
return match if match
|
65
|
+
|
66
|
+
return NEW_REGEX.match(table)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|