danger 8.0.3
Sign up to get free protection for your applications and to get access to all the features.
- 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 +159 -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,53 @@
|
|
1
|
+
require "danger/commands/local_helpers/pry_setup"
|
2
|
+
require "fileutils"
|
3
|
+
require "tmpdir"
|
4
|
+
|
5
|
+
module Danger
|
6
|
+
class Staging < Runner
|
7
|
+
self.summary = "Run the Dangerfile locally against local master"
|
8
|
+
self.command = "staging"
|
9
|
+
|
10
|
+
def self.options
|
11
|
+
[
|
12
|
+
["--pry", "Drop into a Pry shell after evaluating the Dangerfile."]
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(argv)
|
17
|
+
show_help = true if argv.arguments == ["-h"]
|
18
|
+
|
19
|
+
# Currently CLAide doesn't support short option like -h https://github.com/CocoaPods/CLAide/pull/60
|
20
|
+
# when user pass in -h, mimic the behavior of passing in --help.
|
21
|
+
argv = CLAide::ARGV.new ["--help"] if show_help
|
22
|
+
|
23
|
+
super
|
24
|
+
|
25
|
+
if argv.flag?("pry", false)
|
26
|
+
@dangerfile_path = PrySetup.new(cork).setup_pry(@dangerfile_path)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate!
|
31
|
+
super
|
32
|
+
unless @dangerfile_path
|
33
|
+
help! "Could not find a Dangerfile."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def run
|
38
|
+
ENV["DANGER_USE_LOCAL_ONLY_GIT"] = "YES"
|
39
|
+
|
40
|
+
env = EnvironmentManager.new(ENV, cork)
|
41
|
+
dm = Dangerfile.new(env, cork)
|
42
|
+
|
43
|
+
dm.run(
|
44
|
+
Danger::EnvironmentManager.danger_base_branch,
|
45
|
+
Danger::EnvironmentManager.danger_head_branch,
|
46
|
+
@dangerfile_path,
|
47
|
+
nil,
|
48
|
+
nil,
|
49
|
+
nil
|
50
|
+
)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Danger
|
2
|
+
class Systems < Runner
|
3
|
+
self.abstract_command = true
|
4
|
+
self.description = "For commands related to passing information from Danger to Danger.Systems."
|
5
|
+
self.summary = "Create data for Danger.Systems."
|
6
|
+
end
|
7
|
+
|
8
|
+
class CIDocs < Systems
|
9
|
+
self.command = "ci_docs"
|
10
|
+
self.summary = "Outputs the up-to-date CI documentation for Danger."
|
11
|
+
|
12
|
+
def run
|
13
|
+
here = File.dirname(__FILE__)
|
14
|
+
ci_source_paths = Dir.glob(here + "/../ci_source/*.rb")
|
15
|
+
|
16
|
+
require "yard"
|
17
|
+
# Pull out all the Danger::CI subclasses docs
|
18
|
+
registry = YARD::Registry.load(ci_source_paths, true)
|
19
|
+
ci_sources = begin
|
20
|
+
registry.all(:class)
|
21
|
+
.select { |klass| klass.inheritance_tree.map(&:name).include? :CI }
|
22
|
+
.reject { |source| source.name == :CI }
|
23
|
+
.reject { |source| source.name == :LocalGitRepo }
|
24
|
+
end
|
25
|
+
|
26
|
+
# Fail if anything is added and not documented
|
27
|
+
cis_without_docs = ci_sources.select { |source| source.base_docstring.empty? }
|
28
|
+
unless cis_without_docs.empty?
|
29
|
+
cork.puts "Please add docs to: #{cis_without_docs.map(&:name).join(', ')}"
|
30
|
+
abort("Failed.".red)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Output a JSON array of name and details
|
34
|
+
require "json"
|
35
|
+
cork.puts ci_sources.map { |ci|
|
36
|
+
{
|
37
|
+
name: ci.name,
|
38
|
+
docs: ci.docstring
|
39
|
+
}
|
40
|
+
}.to_json
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%- @tables.each do |table| -%>
|
2
|
+
<%- if table[:content].any? || table[:resolved].any? -%>
|
3
|
+
| | <%= table[:count] %> <%= table[:name] %><%= "s" unless table[:count] == 1 %> |
|
4
|
+
|---|---|
|
5
|
+
<%- table[:content].each do |violation| -%>
|
6
|
+
| <%= @emoji_mapper.map(table[:emoji]) %> | <%= violation.message %> |
|
7
|
+
<%- end -%>
|
8
|
+
<%- table[:resolved].each do |message| -%>
|
9
|
+
| @emoji_mapper.map("white_check_mark") | <%= message %> |
|
10
|
+
<%- end -%>
|
11
|
+
|
12
|
+
<%- end -%>
|
13
|
+
<%- end -%>
|
14
|
+
|
15
|
+
<%- @markdowns.each do |current| -%>
|
16
|
+
<%= current %>
|
17
|
+
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
18
|
+
<%- end -%>
|
19
|
+
|
20
|
+
Generated by :no_entry_sign: [Danger](https://danger.systems/ "generated_by_<%= @danger_id %>")
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%- @tables.each do |table| -%>
|
2
|
+
<%- table[:content].each do |violation| -%>
|
3
|
+
<%= @emoji_mapper.map(table[:emoji]) if table[:emoji] %> <%= violation.message %>
|
4
|
+
<%- end -%>
|
5
|
+
<%- table[:resolved] && table[:resolved].each do |message| -%>
|
6
|
+
<%= @emoji_mapper.map("white_check_mark") %> <%= message %>
|
7
|
+
<%- end -%>
|
8
|
+
<%- end -%>
|
9
|
+
|
10
|
+
<%- @markdowns.each do |current| -%>
|
11
|
+
<%= current %>
|
12
|
+
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
13
|
+
<%- end -%>
|
14
|
+
|
15
|
+
Generated by :no_entry_sign: [Danger](https://danger.systems/ "generated_by_<%= @danger_id %>")
|
@@ -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 %>")
|
@@ -0,0 +1,55 @@
|
|
1
|
+
<!--
|
2
|
+
<%- @tables.each do |table| -%>
|
3
|
+
<%= pluralize(table[:name], table[:count]) %><%= ": #{truncate(table[:content].first.message)}" if table[:count] > 0 %>
|
4
|
+
<%- end -%>
|
5
|
+
<%= pluralize("Markdown", @markdowns.size) %>
|
6
|
+
-->
|
7
|
+
<%- @tables.each do |table| -%>
|
8
|
+
<%- if table[:content].any? || table[:resolved].any? -%>
|
9
|
+
<table>
|
10
|
+
<thead>
|
11
|
+
<tr>
|
12
|
+
<th width="50"></th>
|
13
|
+
<th width="100%" data-danger-table="true" data-kind="<%= table[:name] %>">
|
14
|
+
<%- if table[:count] > 0 -%>
|
15
|
+
<%= pluralize(table[:name], table[:count]) %>
|
16
|
+
<%- else -%>
|
17
|
+
:white_check_mark: <%= random_compliment %>
|
18
|
+
<%- end -%>
|
19
|
+
</th>
|
20
|
+
</tr>
|
21
|
+
</thead>
|
22
|
+
<tbody>
|
23
|
+
<%- max_num_violations = FindMaxNumViolations.new(table[:content]).call -%>
|
24
|
+
<%- table[:content].take(max_num_violations).each do |violation| -%>
|
25
|
+
<tr>
|
26
|
+
<td>:<%= table[:emoji] %>:</td>
|
27
|
+
<td data-sticky="<%= violation.sticky %>"><%= violation.message %></td>
|
28
|
+
</tr>
|
29
|
+
<%- end -%>
|
30
|
+
<%- if table[:content].length > max_num_violations -%>
|
31
|
+
<tr>
|
32
|
+
<td>:warning:</td>
|
33
|
+
<td>
|
34
|
+
Danger found <%= table[:content].length %> violations with this PR. Due to GitHub's max issue comment size, the number shown has been truncated to <%= max_num_violations %>.
|
35
|
+
</td>
|
36
|
+
</tr>
|
37
|
+
<%- end -%>
|
38
|
+
<%- table[:resolved].each do |message| -%>
|
39
|
+
<tr>
|
40
|
+
<td>:white_check_mark:</td>
|
41
|
+
<td data-sticky="true"><del><%= message %></del></td>
|
42
|
+
</tr>
|
43
|
+
<%- end -%>
|
44
|
+
</tbody>
|
45
|
+
</table>
|
46
|
+
<%- end -%>
|
47
|
+
<%- end -%>
|
48
|
+
|
49
|
+
<%- @markdowns.each do |current| -%>
|
50
|
+
<%= current %>
|
51
|
+
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
52
|
+
<%- end -%>
|
53
|
+
<p align="right" data-meta="generated_by_<%= @danger_id %>">
|
54
|
+
Generated by :no_entry_sign: <a href="https://danger.systems/">Danger</a>
|
55
|
+
</p>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%- @tables.each do |table| -%>
|
2
|
+
<%- if table[:content].any? -%>
|
3
|
+
<table data-meta="generated_by_<%= @danger_id %>">
|
4
|
+
<tbody>
|
5
|
+
<%- table[:content].each do |violation| -%>
|
6
|
+
<tr>
|
7
|
+
<td>:<%= table[:emoji] %>:</td>
|
8
|
+
<td width="100%" data-sticky="<%= violation.sticky %>"><%= "<del>" if table[:resolved] %><%= violation.message %><%= "</del>" if table[:resolved] %></td>
|
9
|
+
</tr>
|
10
|
+
<%- end -%>
|
11
|
+
</tbody>
|
12
|
+
</table>
|
13
|
+
<%- end -%>
|
14
|
+
<%- end -%>
|
15
|
+
|
16
|
+
<%- @markdowns.each do |current| -%>
|
17
|
+
<%= current %>
|
18
|
+
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
19
|
+
<%- end -%>
|
20
|
+
<%# We need to add the generated_by_ to identify comments from danger. But with inlines %>
|
21
|
+
<%# it might be a little annoying, so we set on the table, but if we have markdown we add the footer anyway %>
|
22
|
+
<%- if @markdowns.count > 0 -%>
|
23
|
+
<p align="right" data-meta="generated_by_<%= @danger_id %>">
|
24
|
+
Generated by :no_entry_sign: <a href="http://danger.systems/">Danger</a>
|
25
|
+
</p>
|
26
|
+
<%- end -%>
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<%- @tables.each do |table| -%>
|
2
|
+
<%- if table[:content].any? || table[:resolved].any? -%>
|
3
|
+
<table>
|
4
|
+
<thead>
|
5
|
+
<tr>
|
6
|
+
<th width="5%"></th>
|
7
|
+
<th width="95%" data-danger-table="true" data-kind="<%= table[:name] %>">
|
8
|
+
<%- if table[:count] > 0 -%>
|
9
|
+
<%= table[:count] %> <%= table[:name] %><%= "s" unless table[:count] == 1 %>
|
10
|
+
<%- else -%>
|
11
|
+
:white_check_mark: <%= random_compliment %>
|
12
|
+
<%- end -%>
|
13
|
+
</th>
|
14
|
+
</tr>
|
15
|
+
</thead>
|
16
|
+
<tbody>
|
17
|
+
<%- table[:content].each do |violation| -%>
|
18
|
+
<tr>
|
19
|
+
<td>:<%= table[:emoji] %>:</td>
|
20
|
+
<td data-sticky="<%= violation.sticky %>"><%= violation.message %></td>
|
21
|
+
</tr>
|
22
|
+
<%- end -%>
|
23
|
+
<%- table[:resolved].each do |message| -%>
|
24
|
+
<tr>
|
25
|
+
<td>:white_check_mark:</td>
|
26
|
+
<td data-sticky="true"><del><%= message %></del></td>
|
27
|
+
</tr>
|
28
|
+
<%- end -%>
|
29
|
+
</tbody>
|
30
|
+
</table>
|
31
|
+
<%- end -%>
|
32
|
+
<%- end -%>
|
33
|
+
|
34
|
+
<%- @markdowns.each do |current| -%>
|
35
|
+
<%= current %>
|
36
|
+
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
37
|
+
<%- end -%>
|
38
|
+
<p align="right" data-meta="generated_by_<%= @danger_id %>">
|
39
|
+
Generated by :no_entry_sign: <a href="https://github.com/danger/danger/">Danger</a>
|
40
|
+
</p>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<%- @tables.each do |table| -%>
|
2
|
+
<%- if table[:content].any? -%>
|
3
|
+
<table data-meta="generated_by_<%= @danger_id %>">
|
4
|
+
<tbody>
|
5
|
+
<%- table[:content].each do |violation| -%>
|
6
|
+
<tr>
|
7
|
+
<td>:<%= table[:emoji] %>:</td>
|
8
|
+
<td width="100%" data-sticky="<%= violation.sticky %>"><%= "<del>" if table[:resolved] %><%= violation.message %><%= "</del>" if table[:resolved] %></td>
|
9
|
+
</tr>
|
10
|
+
<%- end -%>
|
11
|
+
</tbody>
|
12
|
+
</table>
|
13
|
+
<%- end -%>
|
14
|
+
<%- end -%>
|
15
|
+
|
16
|
+
<%- @markdowns.each do |current| -%>
|
17
|
+
<%= current %>
|
18
|
+
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
19
|
+
<%- end -%>
|
20
|
+
<%# We need to add the generated_by_ to identify comments from danger. But with inlines %>
|
21
|
+
<%# it might be a little annoying, so we set on the table, but if we have markdown we add the footer anyway %>
|
22
|
+
<%- if @markdowns.count > 0 -%>
|
23
|
+
<p align="right" data-meta="generated_by_<%= @danger_id %>">
|
24
|
+
Generated by :no_entry_sign: <a href="http://danger.systems/">Danger</a>
|
25
|
+
</p>
|
26
|
+
<%- end -%>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<%- @tables.each do |table| -%>
|
2
|
+
<%- if table[:content].any? || table[:resolved].any? -%>
|
3
|
+
| | <%= table[:count] %> <%= table[:name] %><%= "s" unless table[:count] == 1 %> |
|
4
|
+
|---|---|
|
5
|
+
<%- table[:content].each do |violation| -%>
|
6
|
+
| <%= @emoji_mapper.map(table[:emoji]) %> | <%= violation.message %> |
|
7
|
+
<%- end -%>
|
8
|
+
<%- table[:resolved].each do |message| -%>
|
9
|
+
| @emoji_mapper.map("white_check_mark") | <%= message %> |
|
10
|
+
<%- end -%>
|
11
|
+
|
12
|
+
<%- end -%>
|
13
|
+
<%- end -%>
|
14
|
+
|
15
|
+
<%- @markdowns.each do |current| -%>
|
16
|
+
<%= current %>
|
17
|
+
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
18
|
+
<%- end -%>
|
19
|
+
|
20
|
+
Generated by :no_entry_sign: [Danger](https://danger.systems/ "generated_by_<%= @danger_id %>")
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "danger/helpers/array_subclass"
|
2
|
+
|
3
|
+
module Danger
|
4
|
+
class FileList
|
5
|
+
include Helpers::ArraySubclass
|
6
|
+
|
7
|
+
# Information about pattern: http://ruby-doc.org/core-2.2.0/File.html#method-c-fnmatch
|
8
|
+
# e.g. "**/something.*" for any file called something with any extension
|
9
|
+
def include?(pattern)
|
10
|
+
self.each do |current|
|
11
|
+
unless current.nil?
|
12
|
+
return true if File.fnmatch(pattern, current) || pattern == current
|
13
|
+
end
|
14
|
+
end
|
15
|
+
return false
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class String
|
2
|
+
# @return [String] the plural form of self determined by count
|
3
|
+
def danger_pluralize(count)
|
4
|
+
"#{count} #{self}#{'s' unless count == 1}"
|
5
|
+
end
|
6
|
+
|
7
|
+
# @return [String] converts to underscored, lowercase form
|
8
|
+
def danger_underscore
|
9
|
+
self.gsub(/::/, "/".freeze).
|
10
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2'.freeze).
|
11
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2'.freeze).
|
12
|
+
tr("-".freeze, "_".freeze).
|
13
|
+
downcase
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [String] truncates string with ellipsis when exceeding the limit
|
17
|
+
def danger_truncate(limit)
|
18
|
+
length > limit ? "#{self[0...limit]}..." : self
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,341 @@
|
|
1
|
+
# So much was ripped direct from CocoaPods-Core - thanks!
|
2
|
+
|
3
|
+
require "danger/danger_core/dangerfile_dsl"
|
4
|
+
require "danger/danger_core/standard_error"
|
5
|
+
require "danger/danger_core/message_aggregator"
|
6
|
+
|
7
|
+
require "danger/danger_core/plugins/dangerfile_messaging_plugin"
|
8
|
+
require "danger/danger_core/plugins/dangerfile_danger_plugin"
|
9
|
+
require "danger/danger_core/plugins/dangerfile_git_plugin"
|
10
|
+
require "danger/danger_core/plugins/dangerfile_github_plugin"
|
11
|
+
require "danger/danger_core/plugins/dangerfile_gitlab_plugin"
|
12
|
+
require "danger/danger_core/plugins/dangerfile_bitbucket_server_plugin"
|
13
|
+
require "danger/danger_core/plugins/dangerfile_bitbucket_cloud_plugin"
|
14
|
+
require "danger/danger_core/plugins/dangerfile_vsts_plugin"
|
15
|
+
require "danger/danger_core/plugins/dangerfile_local_only_plugin"
|
16
|
+
|
17
|
+
module Danger
|
18
|
+
class Dangerfile
|
19
|
+
include Danger::Dangerfile::DSL
|
20
|
+
|
21
|
+
attr_accessor :env, :verbose, :plugins, :ui
|
22
|
+
|
23
|
+
# @return [Pathname] the path where the Dangerfile was loaded from. It is nil
|
24
|
+
# if the Dangerfile was generated programmatically.
|
25
|
+
#
|
26
|
+
attr_accessor :defined_in_file
|
27
|
+
|
28
|
+
# @return [String] a string useful to represent the Dangerfile in a message
|
29
|
+
# presented to the user.
|
30
|
+
#
|
31
|
+
def to_s
|
32
|
+
"Dangerfile"
|
33
|
+
end
|
34
|
+
|
35
|
+
# These are the classes that are allowed to also use method_missing
|
36
|
+
# in order to provide broader plugin support
|
37
|
+
def self.core_plugin_classes
|
38
|
+
[DangerfileMessagingPlugin]
|
39
|
+
end
|
40
|
+
|
41
|
+
# The ones that everything would break without
|
42
|
+
def self.essential_plugin_classes
|
43
|
+
[DangerfileMessagingPlugin, DangerfileGitPlugin, DangerfileDangerPlugin, DangerfileGitHubPlugin, DangerfileGitLabPlugin, DangerfileBitbucketServerPlugin, DangerfileBitbucketCloudPlugin, DangerfileVSTSPlugin, DangerfileLocalOnlyPlugin]
|
44
|
+
end
|
45
|
+
|
46
|
+
# Both of these methods exist on all objects
|
47
|
+
# http://ruby-doc.org/core-2.2.3/Kernel.html#method-i-warn
|
48
|
+
# http://ruby-doc.org/core-2.2.3/Kernel.html#method-i-fail
|
49
|
+
# However, as we're using using them in the DSL, they won't
|
50
|
+
# get method_missing called correctly without overriding them.
|
51
|
+
|
52
|
+
def warn(*args, &blk)
|
53
|
+
method_missing(:warn, *args, &blk)
|
54
|
+
end
|
55
|
+
|
56
|
+
def fail(*args, &blk)
|
57
|
+
method_missing(:fail, *args, &blk)
|
58
|
+
end
|
59
|
+
|
60
|
+
# When an undefined method is called, we check to see if it's something
|
61
|
+
# that the core DSLs have, then starts looking at plugins support.
|
62
|
+
|
63
|
+
# rubocop:disable Style/MethodMissing
|
64
|
+
def method_missing(method_sym, *arguments, &_block)
|
65
|
+
@core_plugins.each do |plugin|
|
66
|
+
if plugin.public_methods(false).include?(method_sym)
|
67
|
+
return plugin.send(method_sym, *arguments)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
73
|
+
# cork_board not being set comes from plugins #585
|
74
|
+
def initialize(env_manager, cork_board = nil)
|
75
|
+
@plugins = {}
|
76
|
+
@core_plugins = []
|
77
|
+
@ui = cork_board || Cork::Board.new(silent: false, verbose: false)
|
78
|
+
|
79
|
+
# Triggers the core plugins
|
80
|
+
@env = env_manager
|
81
|
+
|
82
|
+
# Triggers local plugins from the root of a project
|
83
|
+
Dir["./danger_plugins/*.rb"].each do |file|
|
84
|
+
require File.expand_path(file)
|
85
|
+
end
|
86
|
+
|
87
|
+
refresh_plugins if env_manager.pr?
|
88
|
+
end
|
89
|
+
|
90
|
+
# Iterate through available plugin classes and initialize them with
|
91
|
+
# a reference to this Dangerfile
|
92
|
+
def refresh_plugins
|
93
|
+
plugins = Plugin.all_plugins
|
94
|
+
plugins.each do |klass|
|
95
|
+
next if klass.respond_to?(:singleton_class?) && klass.singleton_class?
|
96
|
+
plugin = klass.new(self)
|
97
|
+
next if plugin.nil? || @plugins[klass]
|
98
|
+
|
99
|
+
name = plugin.class.instance_name
|
100
|
+
self.class.send(:attr_reader, name)
|
101
|
+
instance_variable_set("@#{name}", plugin)
|
102
|
+
|
103
|
+
@plugins[klass] = plugin
|
104
|
+
@core_plugins << plugin if self.class.core_plugin_classes.include? klass
|
105
|
+
end
|
106
|
+
end
|
107
|
+
alias init_plugins refresh_plugins
|
108
|
+
|
109
|
+
def core_dsl_attributes
|
110
|
+
@core_plugins.map { |plugin| { plugin: plugin, methods: plugin.public_methods(false) } }
|
111
|
+
end
|
112
|
+
|
113
|
+
def external_dsl_attributes
|
114
|
+
plugins.values.reject { |plugin| @core_plugins.include? plugin } .map { |plugin| { plugin: plugin, methods: plugin.public_methods(false) } }
|
115
|
+
end
|
116
|
+
|
117
|
+
def method_values_for_plugin_hashes(plugin_hashes)
|
118
|
+
plugin_hashes.flat_map do |plugin_hash|
|
119
|
+
plugin = plugin_hash[:plugin]
|
120
|
+
methods = plugin_hash[:methods].select { |name| plugin.method(name).parameters.empty? }
|
121
|
+
|
122
|
+
methods.map do |method|
|
123
|
+
case method
|
124
|
+
when :api
|
125
|
+
value = "Octokit::Client"
|
126
|
+
|
127
|
+
when :pr_json, :mr_json
|
128
|
+
value = "[Skipped JSON]"
|
129
|
+
|
130
|
+
when :pr_diff, :mr_diff
|
131
|
+
value = "[Skipped Diff]"
|
132
|
+
|
133
|
+
else
|
134
|
+
value = plugin.send(method)
|
135
|
+
value = wrap_text(value.encode("utf-8")) if value.kind_of?(String)
|
136
|
+
# So that we either have one value per row
|
137
|
+
# or we have [] for an empty array
|
138
|
+
value = value.join("\n") if value.kind_of?(Array) && value.count > 0
|
139
|
+
end
|
140
|
+
|
141
|
+
[method.to_s, value]
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Iterates through the DSL's attributes, and table's the output
|
147
|
+
def print_known_info
|
148
|
+
rows = []
|
149
|
+
rows += method_values_for_plugin_hashes(core_dsl_attributes)
|
150
|
+
rows << ["---", "---"]
|
151
|
+
rows += method_values_for_plugin_hashes(external_dsl_attributes)
|
152
|
+
rows << ["---", "---"]
|
153
|
+
rows << ["SCM", env.scm.class]
|
154
|
+
rows << ["Source", env.ci_source.class]
|
155
|
+
rows << ["Requests", env.request_source.class]
|
156
|
+
rows << ["Base Commit", env.meta_info_for_base]
|
157
|
+
rows << ["Head Commit", env.meta_info_for_head]
|
158
|
+
|
159
|
+
params = {}
|
160
|
+
params[:rows] = rows.each { |current| current[0] = current[0].yellow }
|
161
|
+
params[:title] = "Danger v#{Danger::VERSION}\nDSL Attributes".green
|
162
|
+
|
163
|
+
ui.section("Info:") do
|
164
|
+
ui.puts
|
165
|
+
table = Terminal::Table.new(params)
|
166
|
+
table.align_column(0, :right)
|
167
|
+
ui.puts table
|
168
|
+
ui.puts
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Parses the file at a path, optionally takes the content of the file for DI
|
173
|
+
#
|
174
|
+
def parse(path, contents = nil)
|
175
|
+
print_known_info if verbose
|
176
|
+
|
177
|
+
contents ||= File.open(path, "r:utf-8", &:read)
|
178
|
+
|
179
|
+
# Work around for Rubinius incomplete encoding in 1.9 mode
|
180
|
+
if contents.respond_to?(:encoding) && contents.encoding.name != "UTF-8"
|
181
|
+
contents.encode!("UTF-8")
|
182
|
+
end
|
183
|
+
|
184
|
+
if contents.tr!("“”‘’‛", %(""'''))
|
185
|
+
# Changes have been made
|
186
|
+
ui.puts "Your #{path.basename} has had smart quotes sanitised. " \
|
187
|
+
"To avoid issues in the future, you should not use " \
|
188
|
+
"TextEdit for editing it. If you are not using TextEdit, " \
|
189
|
+
"you should turn off smart quotes in your editor of choice.".red
|
190
|
+
end
|
191
|
+
|
192
|
+
if contents.include?("puts")
|
193
|
+
ui.puts "You used `puts` in your Dangerfile. To print out text to GitHub use `message` instead"
|
194
|
+
end
|
195
|
+
|
196
|
+
self.defined_in_file = path
|
197
|
+
instance_eval do
|
198
|
+
# rubocop:disable Lint/RescueException
|
199
|
+
begin
|
200
|
+
eval_file(contents, path)
|
201
|
+
rescue Exception => e
|
202
|
+
message = "Invalid `#{path.basename}` file: #{e.message}"
|
203
|
+
raise DSLError.new(message, path, e.backtrace, contents)
|
204
|
+
end
|
205
|
+
# rubocop:enable Lint/RescueException
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def print_results
|
210
|
+
status = status_report
|
211
|
+
violations = violation_report
|
212
|
+
return if (violations[:errors] + violations[:warnings] + violations[:messages] + status[:markdowns]).count.zero?
|
213
|
+
|
214
|
+
ui.section("Results:") do
|
215
|
+
%i(errors warnings messages).each do |key|
|
216
|
+
formatted = key.to_s.capitalize + ":"
|
217
|
+
title = case key
|
218
|
+
when :errors
|
219
|
+
formatted.red
|
220
|
+
when :warnings
|
221
|
+
formatted.yellow
|
222
|
+
else
|
223
|
+
formatted
|
224
|
+
end
|
225
|
+
rows = violations[key].uniq
|
226
|
+
print_list(title, rows)
|
227
|
+
end
|
228
|
+
|
229
|
+
if status[:markdowns].count > 0
|
230
|
+
ui.title("Markdown:") do
|
231
|
+
status[:markdowns].each do |current_markdown|
|
232
|
+
ui.puts "#{current_markdown.file}\#L#{current_markdown.line}" if current_markdown.file && current_markdown.line
|
233
|
+
ui.puts current_markdown.message
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def failed?
|
241
|
+
violation_report[:errors].count > 0
|
242
|
+
end
|
243
|
+
|
244
|
+
def post_results(danger_id, new_comment, remove_previous_comments)
|
245
|
+
violations = violation_report
|
246
|
+
report = {
|
247
|
+
warnings: violations[:warnings].uniq,
|
248
|
+
errors: violations[:errors].uniq,
|
249
|
+
messages: violations[:messages].uniq,
|
250
|
+
markdowns: status_report[:markdowns].uniq,
|
251
|
+
danger_id: danger_id
|
252
|
+
}
|
253
|
+
|
254
|
+
if env.request_source.respond_to?(:update_pr_by_line!) && ENV["DANGER_MESSAGE_AGGREGATION"]
|
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])
|
259
|
+
else
|
260
|
+
env.request_source.update_pull_request!(
|
261
|
+
**report,
|
262
|
+
new_comment: new_comment,
|
263
|
+
remove_previous_comments: remove_previous_comments
|
264
|
+
)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
def setup_for_running(base_branch, head_branch)
|
269
|
+
env.ensure_danger_branches_are_setup
|
270
|
+
env.scm.diff_for_folder(".".freeze, from: base_branch, to: head_branch, lookup_top_level: true)
|
271
|
+
end
|
272
|
+
|
273
|
+
def run(base_branch, head_branch, dangerfile_path, danger_id, new_comment, remove_previous_comments)
|
274
|
+
# Setup internal state
|
275
|
+
init_plugins
|
276
|
+
env.fill_environment_vars
|
277
|
+
|
278
|
+
begin
|
279
|
+
# Sets up the git environment
|
280
|
+
setup_for_running(base_branch, head_branch)
|
281
|
+
|
282
|
+
# Parse the local Dangerfile
|
283
|
+
parse(Pathname.new(dangerfile_path))
|
284
|
+
|
285
|
+
# Push results to the API
|
286
|
+
# Pass along the details of the run to the request source
|
287
|
+
# to send back to the code review site.
|
288
|
+
post_results(danger_id, new_comment, remove_previous_comments) unless danger_id.nil?
|
289
|
+
|
290
|
+
# Print results in the terminal
|
291
|
+
print_results
|
292
|
+
rescue DSLError => ex
|
293
|
+
# Push exception to the API and re-raise
|
294
|
+
post_exception(ex, danger_id, new_comment) unless danger_id.nil?
|
295
|
+
raise
|
296
|
+
ensure
|
297
|
+
# Makes sure that Danger specific git branches are cleaned
|
298
|
+
env.clean_up
|
299
|
+
end
|
300
|
+
|
301
|
+
failed?
|
302
|
+
end
|
303
|
+
|
304
|
+
private
|
305
|
+
|
306
|
+
def eval_file(contents, path)
|
307
|
+
eval(contents, nil, path.to_s) # rubocop:disable Eval
|
308
|
+
end
|
309
|
+
|
310
|
+
def print_list(title, rows)
|
311
|
+
unless rows.empty?
|
312
|
+
ui.title(title) do
|
313
|
+
rows.each do |row|
|
314
|
+
if row.file && row.line
|
315
|
+
path = "#{row.file}\#L#{row.line}: "
|
316
|
+
else
|
317
|
+
path = ""
|
318
|
+
end
|
319
|
+
|
320
|
+
ui.puts("- [ ] #{path}#{row.message}")
|
321
|
+
end
|
322
|
+
end
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
def wrap_text(text, width = 80)
|
327
|
+
text.gsub(/.{,#{width}}/) do |line|
|
328
|
+
line.strip!
|
329
|
+
"#{line}\n"
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
def post_exception(ex, danger_id, new_comment)
|
334
|
+
env.request_source.update_pull_request!(
|
335
|
+
danger_id: danger_id,
|
336
|
+
new_comment: new_comment,
|
337
|
+
markdowns: [ex.to_markdown]
|
338
|
+
)
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|