danger 0.9.1 → 0.10.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.
- checksums.yaml +4 -4
- data/README.md +10 -0
- data/lib/danger.rb +1 -0
- data/lib/danger/ci_source/buildkite.rb +1 -0
- data/lib/danger/ci_source/circle.rb +1 -0
- data/lib/danger/ci_source/drone.rb +1 -0
- data/lib/danger/ci_source/jenkins.rb +1 -0
- data/lib/danger/ci_source/local_git_repo.rb +1 -0
- data/lib/danger/ci_source/semaphore.rb +1 -0
- data/lib/danger/ci_source/surf.rb +1 -0
- data/lib/danger/ci_source/teamcity.rb +1 -0
- data/lib/danger/ci_source/travis.rb +1 -0
- data/lib/danger/ci_source/xcode_server.rb +1 -0
- data/lib/danger/commands/local.rb +29 -1
- data/lib/danger/commands/local_helpers/http_cache.rb +36 -0
- data/lib/danger/commands/plugins/plugin_lint.rb +1 -1
- data/lib/danger/commands/runner.rb +6 -49
- data/lib/danger/danger_core/executor.rb +55 -0
- data/lib/danger/danger_core/plugins/dangerfile_git_plugin.rb +4 -0
- data/lib/danger/danger_core/plugins/dangerfile_github_plugin.rb +4 -1
- data/lib/danger/danger_core/plugins/dangerfile_import_plugin.rb +38 -23
- data/lib/danger/danger_core/plugins/dangerfile_messaging_plugin.rb +18 -4
- data/lib/danger/plugin_support/plugin_linter.rb +5 -4
- data/lib/danger/plugin_support/plugin_parser.rb +15 -5
- data/lib/danger/request_source/github.rb +52 -5
- data/lib/danger/request_source/request_source.rb +22 -0
- data/lib/danger/version.rb +1 -1
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7b697f1591c4b33509e536da0cf20d7acaa61e8c
|
4
|
+
data.tar.gz: 0a9d995a79188ae53f543230fbd9a7007c1641b8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a1350d0ce5fbfe8c22c27c04848243a589b07e39e6805ae15343259891153145f2aacc6bee0505101cc53052d35c44b83efb3e3e05733469f9eddb6d8850bd4
|
7
|
+
data.tar.gz: 0bcc00b71b54a8b4d23ac457feab9793d742c110fa55ee5997a584b7719adad5591fe4faa9f27804cff7c9253759aab6c0a63e63763825e7ea7ff0af56e19019
|
data/README.md
CHANGED
@@ -201,6 +201,16 @@ Danger will update the comment to cross it out. If you don't want this behavior,
|
|
201
201
|
fail("PR needs labels", sticky: false) if pr_labels.empty?
|
202
202
|
```
|
203
203
|
|
204
|
+
## Org-Wide Dangerfile
|
205
|
+
|
206
|
+
To have consistent rules across the repos in your organisation, you can use a shared `Dangerfile`:
|
207
|
+
|
208
|
+
1. create a repo on your GitHub organization called `danger` (or `Danger`)
|
209
|
+
1. Add a `Dangerfile` to the root of that repo
|
210
|
+
1. The new `Dangerfile` is ran after the current repo's `Dangerfile`
|
211
|
+
|
212
|
+
The org `Dangerfile` will have access to all of the same plugins, and metadata. For an example, see [themoji/danger](https://github.com/Themoji/danger).
|
213
|
+
|
204
214
|
## Multiple Dangers
|
205
215
|
|
206
216
|
If one Danger is not enough for you, you can run several ones on the same PR. Just use the `danger_id` param. For example:
|
data/lib/danger.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
require "danger/commands/local_helpers/http_cache"
|
2
|
+
require "faraday/http_cache"
|
3
|
+
require "octokit"
|
4
|
+
require "tmpdir"
|
5
|
+
|
1
6
|
module Danger
|
2
7
|
class Local < Runner
|
3
8
|
self.summary = "Run the Dangerfile locally."
|
@@ -6,12 +11,14 @@ module Danger
|
|
6
11
|
def initialize(argv)
|
7
12
|
@dangerfile_path = "Dangerfile" if File.exist? "Dangerfile"
|
8
13
|
@pr_num = argv.option("use-merged-pr")
|
14
|
+
@clear_http_cache = argv.flag?("clear-http-cache", false)
|
9
15
|
super
|
10
16
|
end
|
11
17
|
|
12
18
|
def self.options
|
13
19
|
[
|
14
|
-
["--use-merged-pr=[#id]", "The ID of an already merged PR inside your history to use as a reference for the local run."]
|
20
|
+
["--use-merged-pr=[#id]", "The ID of an already merged PR inside your history to use as a reference for the local run."],
|
21
|
+
["--clear-http-cache", "Clear the local http cache before running Danger locally."]
|
15
22
|
].concat(super)
|
16
23
|
end
|
17
24
|
|
@@ -26,6 +33,15 @@ module Danger
|
|
26
33
|
ENV["DANGER_USE_LOCAL_GIT"] = "YES"
|
27
34
|
ENV["LOCAL_GIT_PR_ID"] = @pr_num if @pr_num
|
28
35
|
|
36
|
+
# setup caching for Github calls to hitting the API rate limit too quickly
|
37
|
+
cache_file = File.join(ENV["DANGER_TMPDIR"] || Dir.tmpdir, "danger_local_cache")
|
38
|
+
cache = HTTPCache.new(cache_file, clear_cache: @clear_http_cache)
|
39
|
+
Octokit.middleware = Faraday::Builder.new do |builder|
|
40
|
+
builder.use Faraday::HttpCache, store: cache, serializer: Marshal, shared_cache: false
|
41
|
+
builder.use Octokit::Response::RaiseError
|
42
|
+
builder.adapter Faraday.default_adapter
|
43
|
+
end
|
44
|
+
|
29
45
|
env = EnvironmentManager.new(ENV)
|
30
46
|
dm = Dangerfile.new(env, cork)
|
31
47
|
dm.init_plugins
|
@@ -64,11 +80,23 @@ module Danger
|
|
64
80
|
dm.env.fill_environment_vars
|
65
81
|
dm.env.ensure_danger_branches_are_setup
|
66
82
|
dm.env.scm.diff_for_folder(".", from: Danger::EnvironmentManager.danger_base_branch, to: Danger::EnvironmentManager.danger_head_branch)
|
83
|
+
|
67
84
|
dm.parse(Pathname.new(@dangerfile_path))
|
85
|
+
check_and_run_org_dangerfile(dm)
|
86
|
+
|
68
87
|
dm.print_results
|
69
88
|
ensure
|
70
89
|
dm.env.clean_up
|
71
90
|
end
|
72
91
|
end
|
92
|
+
|
93
|
+
# Check to see if there's a Dangerfile in the organisation, and run it if so
|
94
|
+
def check_and_run_org_dangerfile(dm)
|
95
|
+
if dm.env.request_source.organisation && !dm.env.request_source.danger_repo? && (danger_repo = dm.env.request_source.fetch_danger_repo)
|
96
|
+
url = dm.env.request_source.file_url(repository: danger_repo.name, path: "Dangerfile")
|
97
|
+
path = dm.plugin.download(url)
|
98
|
+
dm.parse(Pathname.new(path))
|
99
|
+
end
|
100
|
+
end
|
73
101
|
end
|
74
102
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require "pstore"
|
2
|
+
|
3
|
+
module Danger
|
4
|
+
class HTTPCache
|
5
|
+
attr_reader :expires_in
|
6
|
+
def initialize(cache_file = nil, options = {})
|
7
|
+
File.delete(cache_file) if options[:clear_cache]
|
8
|
+
@store = PStore.new(cache_file)
|
9
|
+
@expires_in = options[:expires_in] || 300 # 5 minutes
|
10
|
+
end
|
11
|
+
|
12
|
+
def read(key)
|
13
|
+
@store.transaction do
|
14
|
+
entry = @store[key]
|
15
|
+
return nil unless entry
|
16
|
+
return entry[:value] unless entry_has_expired(entry, @expires_in)
|
17
|
+
@store.delete key
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete(key)
|
23
|
+
@store.transaction { @store.delete key }
|
24
|
+
end
|
25
|
+
|
26
|
+
def write(key, value)
|
27
|
+
@store.transaction do
|
28
|
+
@store[key] = { updated_at: Time.now.to_i, value: value }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def entry_has_expired(entry, ttl)
|
33
|
+
Time.now.to_i > entry[:updated_at].to_i + ttl.to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -16,14 +16,14 @@ module Danger
|
|
16
16
|
require "danger/commands/plugins/plugin_json"
|
17
17
|
require "danger/commands/plugins/plugin_readme"
|
18
18
|
|
19
|
+
attr_accessor :cork
|
20
|
+
|
19
21
|
self.summary = "Run the Dangerfile."
|
20
22
|
self.command = "danger"
|
21
23
|
self.version = Danger::VERSION
|
22
24
|
|
23
25
|
self.plugin_prefixes = %w(claide danger)
|
24
26
|
|
25
|
-
attr_accessor :cork
|
26
|
-
|
27
27
|
def initialize(argv)
|
28
28
|
dangerfile = argv.option("dangerfile", "Dangerfile")
|
29
29
|
@dangerfile_path = dangerfile if File.exist? dangerfile
|
@@ -52,53 +52,10 @@ module Danger
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def run
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
dm.verbose = verbose
|
60
|
-
dm.init_plugins
|
61
|
-
|
62
|
-
dm.env.fill_environment_vars
|
63
|
-
|
64
|
-
begin
|
65
|
-
dm.env.ensure_danger_branches_are_setup
|
66
|
-
|
67
|
-
# Offer the chance for a user to specify a branch through the command line
|
68
|
-
ci_base = @base || EnvironmentManager.danger_base_branch
|
69
|
-
ci_head = @head || EnvironmentManager.danger_head_branch
|
70
|
-
dm.env.scm.diff_for_folder(".", from: ci_base, to: ci_head)
|
71
|
-
|
72
|
-
dm.parse Pathname.new(@dangerfile_path)
|
73
|
-
|
74
|
-
post_results dm
|
75
|
-
dm.print_results
|
76
|
-
ensure
|
77
|
-
dm.env.clean_up
|
78
|
-
end
|
79
|
-
else
|
80
|
-
cork.puts "Not a Pull Request - skipping `danger` run"
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def post_results(dm)
|
85
|
-
gh = dm.env.request_source
|
86
|
-
violations = dm.violation_report
|
87
|
-
status = dm.status_report
|
88
|
-
|
89
|
-
gh.update_pull_request!(warnings: violations[:warnings], errors: violations[:errors], messages: violations[:messages], markdowns: status[:markdowns], danger_id: @danger_id)
|
90
|
-
end
|
91
|
-
|
92
|
-
def self.report_error(exception)
|
93
|
-
raise exception if exception.kind_of?(SystemExit)
|
94
|
-
message = "#{exception.message.red} (#{exception.class.to_s.yellow})"
|
95
|
-
if exception.backtrace
|
96
|
-
danger_lib = File.expand_path("../../..", __FILE__)
|
97
|
-
message << "\n\t" << exception.backtrace.reverse_each.
|
98
|
-
drop_while { |bt| !bt.start_with?(danger_lib) }.reverse.
|
99
|
-
join("\n\t")
|
100
|
-
end
|
101
|
-
abort(message)
|
55
|
+
Executor.new.run(base: @base,
|
56
|
+
head: @head,
|
57
|
+
dangerfile_path: @dangerfile_path,
|
58
|
+
danger_id: @danger_id)
|
102
59
|
end
|
103
60
|
end
|
104
61
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Danger
|
2
|
+
class Executor
|
3
|
+
def run(env: nil,
|
4
|
+
dm: nil,
|
5
|
+
cork: nil,
|
6
|
+
base: nil,
|
7
|
+
head: nil,
|
8
|
+
dangerfile_path: nil,
|
9
|
+
danger_id: nil)
|
10
|
+
|
11
|
+
cork ||= Cork::Board.new(silent: false,
|
12
|
+
verbose: false)
|
13
|
+
env ||= EnvironmentManager.new(ENV)
|
14
|
+
dm ||= Dangerfile.new(env, cork)
|
15
|
+
|
16
|
+
if dm.env.pr?
|
17
|
+
dm.init_plugins
|
18
|
+
|
19
|
+
dm.env.fill_environment_vars
|
20
|
+
|
21
|
+
begin
|
22
|
+
dm.env.ensure_danger_branches_are_setup
|
23
|
+
|
24
|
+
# Offer the chance for a user to specify a branch through the command line
|
25
|
+
ci_base = base || EnvironmentManager.danger_base_branch
|
26
|
+
ci_head = head || EnvironmentManager.danger_head_branch
|
27
|
+
dm.env.scm.diff_for_folder(".", from: ci_base, to: ci_head)
|
28
|
+
|
29
|
+
dm.parse(Pathname.new(dangerfile_path))
|
30
|
+
|
31
|
+
if dm.env.request_source.organisation && !dm.env.request_source.danger_repo? && (danger_repo = dm.env.request_source.fetch_danger_repo)
|
32
|
+
url = dm.env.request_source.file_url(repository: danger_repo.name, path: "Dangerfile")
|
33
|
+
path = dm.plugin.download(url)
|
34
|
+
dm.parse(Pathname.new(path))
|
35
|
+
end
|
36
|
+
|
37
|
+
post_results(dm, danger_id)
|
38
|
+
dm.print_results
|
39
|
+
ensure
|
40
|
+
dm.env.clean_up
|
41
|
+
end
|
42
|
+
else
|
43
|
+
cork.puts "Not a Pull Request - skipping `danger` run"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def post_results(dm, danger_id)
|
48
|
+
gh = dm.env.request_source
|
49
|
+
violations = dm.violation_report
|
50
|
+
status = dm.status_report
|
51
|
+
|
52
|
+
gh.update_pull_request!(warnings: violations[:warnings], errors: violations[:errors], messages: violations[:messages], markdowns: status[:markdowns], danger_id: danger_id)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require "danger/plugin_support/plugin"
|
2
2
|
require "danger/core_ext/file_list"
|
3
3
|
|
4
|
+
# Danger
|
4
5
|
module Danger
|
5
6
|
# Handles interacting with git inside a Dangerfile. Providing access to files that have changed, and useful statistics. Also provides
|
6
7
|
# access to the commits in the form of [Git::Log](https://github.com/schacon/ruby-git/blob/master/lib/git/log.rb) objects.
|
@@ -30,6 +31,9 @@ module Danger
|
|
30
31
|
# @tags core, git
|
31
32
|
|
32
33
|
class DangerfileGitPlugin < Plugin
|
34
|
+
# The instance name used in the Dangerfile
|
35
|
+
# @return [String]
|
36
|
+
#
|
33
37
|
def self.instance_name
|
34
38
|
"git"
|
35
39
|
end
|
@@ -33,6 +33,9 @@ module Danger
|
|
33
33
|
@github = dangerfile.env.request_source
|
34
34
|
end
|
35
35
|
|
36
|
+
# The instance name used in the Dangerfile
|
37
|
+
# @return [String]
|
38
|
+
#
|
36
39
|
def self.instance_name
|
37
40
|
"github"
|
38
41
|
end
|
@@ -87,7 +90,7 @@ module Danger
|
|
87
90
|
|
88
91
|
# @!group PR Commit Metadata
|
89
92
|
# The base commit to which the PR is going to be merged as a parent.
|
90
|
-
# @return String
|
93
|
+
# @return [String]
|
91
94
|
#
|
92
95
|
def base_commit
|
93
96
|
pr_json[:base][:sha]
|
@@ -24,6 +24,9 @@ module Danger
|
|
24
24
|
# @tags core, plugins
|
25
25
|
|
26
26
|
class DangerfileImportPlugin < Plugin
|
27
|
+
# The instance name used in the Dangerfile
|
28
|
+
# @return [String]
|
29
|
+
#
|
27
30
|
def self.instance_name
|
28
31
|
"plugin"
|
29
32
|
end
|
@@ -31,32 +34,33 @@ module Danger
|
|
31
34
|
# @!group Plugins
|
32
35
|
# Download a local or remote plugin and use it inside the Dangerfile.
|
33
36
|
#
|
34
|
-
# @param [String]
|
37
|
+
# @param [String] path_or_url
|
35
38
|
# a local path or a https URL to the Ruby file to import
|
36
39
|
# a danger plugin from.
|
37
|
-
# @return
|
38
|
-
|
39
|
-
def import(
|
40
|
-
raise "`import` requires a string" unless
|
41
|
-
path += ".rb" unless path.end_with?(".rb")
|
40
|
+
# @return [void]
|
41
|
+
#
|
42
|
+
def import(path_or_url)
|
43
|
+
raise "`import` requires a string" unless path_or_url.kind_of?(String)
|
42
44
|
|
43
|
-
if
|
44
|
-
import_url(
|
45
|
+
if path_or_url.start_with?("http")
|
46
|
+
import_url(path_or_url)
|
45
47
|
else
|
46
|
-
import_local(
|
48
|
+
import_local(path_or_url)
|
47
49
|
end
|
48
50
|
end
|
49
51
|
|
50
|
-
private
|
51
|
-
|
52
52
|
# @!group Plugins
|
53
|
-
# Download a remote plugin
|
53
|
+
# Download a local or remote plugin or Dangerfile
|
54
|
+
# This method will not import the file for you, use plugin.import instead
|
54
55
|
#
|
55
|
-
# @param [String]
|
56
|
-
# https URL to the Ruby file to
|
57
|
-
#
|
58
|
-
|
59
|
-
|
56
|
+
# @param [String] path_or_url
|
57
|
+
# a local path or a https URL to the Ruby file to import
|
58
|
+
# a danger plugin from.
|
59
|
+
# @return [String] The path to the downloaded Ruby file
|
60
|
+
#
|
61
|
+
def download(path_or_url)
|
62
|
+
raise "`download` requires a string" unless path_or_url.kind_of?(String)
|
63
|
+
raise "URL is not https, for security reasons `danger` only supports encrypted requests" if URI.parse(path_or_url).scheme != "https"
|
60
64
|
|
61
65
|
require "tmpdir"
|
62
66
|
require "faraday"
|
@@ -64,13 +68,24 @@ module Danger
|
|
64
68
|
@http_client ||= Faraday.new do |b|
|
65
69
|
b.adapter :net_http
|
66
70
|
end
|
67
|
-
content = @http_client.get(
|
71
|
+
content = @http_client.get(path_or_url)
|
68
72
|
|
69
|
-
Dir.mktmpdir
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
73
|
+
path = File.join(Dir.mktmpdir, "temporary_danger.rb")
|
74
|
+
File.write(path, content.body)
|
75
|
+
return path
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# @!group Plugins
|
81
|
+
# Download a remote plugin and use it locally.
|
82
|
+
#
|
83
|
+
# @param [String] url
|
84
|
+
# https URL to the Ruby file to use
|
85
|
+
# @return [void]
|
86
|
+
def import_url(url)
|
87
|
+
path = download(url)
|
88
|
+
import_local(path)
|
74
89
|
end
|
75
90
|
|
76
91
|
# @!group Plugins
|
@@ -53,6 +53,9 @@ module Danger
|
|
53
53
|
@markdowns = []
|
54
54
|
end
|
55
55
|
|
56
|
+
# The instance name used in the Dangerfile
|
57
|
+
# @return [String]
|
58
|
+
#
|
56
59
|
def self.instance_name
|
57
60
|
"messaging"
|
58
61
|
end
|
@@ -62,6 +65,8 @@ module Danger
|
|
62
65
|
#
|
63
66
|
# @param [String] message
|
64
67
|
# The markdown based message to be printed below the table
|
68
|
+
# @return [void]
|
69
|
+
#
|
65
70
|
def markdown(message)
|
66
71
|
@markdowns << message
|
67
72
|
end
|
@@ -69,10 +74,13 @@ module Danger
|
|
69
74
|
# @!group Core
|
70
75
|
# Print out a generate message on the PR
|
71
76
|
#
|
72
|
-
# @param [String] message
|
77
|
+
# @param [String] message
|
78
|
+
# The message to present to the user
|
73
79
|
# @param [Boolean] sticky
|
74
80
|
# Whether the message should be kept after it was fixed,
|
75
81
|
# defaults to `true`.
|
82
|
+
# @return [void]
|
83
|
+
#
|
76
84
|
def message(message, sticky: true)
|
77
85
|
@messages << Violation.new(message, sticky)
|
78
86
|
end
|
@@ -80,10 +88,13 @@ module Danger
|
|
80
88
|
# @!group Core
|
81
89
|
# Specifies a problem, but not critical
|
82
90
|
#
|
83
|
-
# @param [String] message
|
91
|
+
# @param [String] message
|
92
|
+
# The message to present to the user
|
84
93
|
# @param [Boolean] sticky
|
85
94
|
# Whether the message should be kept after it was fixed,
|
86
95
|
# defaults to `true`.
|
96
|
+
# @return [void]
|
97
|
+
#
|
87
98
|
def warn(message, sticky: true)
|
88
99
|
return if should_ignore_violation(message)
|
89
100
|
@warnings << Violation.new(message, sticky)
|
@@ -97,6 +108,8 @@ module Danger
|
|
97
108
|
# @param [Boolean] sticky
|
98
109
|
# Whether the message should be kept after it was fixed,
|
99
110
|
# defaults to `true`.
|
111
|
+
# @return [void]
|
112
|
+
#
|
100
113
|
def fail(message, sticky: true)
|
101
114
|
return if should_ignore_violation(message)
|
102
115
|
@errors << Violation.new(message, sticky)
|
@@ -106,7 +119,8 @@ module Danger
|
|
106
119
|
# A list of all messages passed to Danger, including
|
107
120
|
# the markdowns.
|
108
121
|
#
|
109
|
-
# @
|
122
|
+
# @visibility hidden
|
123
|
+
# @return [Hash]
|
110
124
|
def status_report
|
111
125
|
{
|
112
126
|
errors: @errors.map(&:message).clone.freeze,
|
@@ -121,7 +135,7 @@ module Danger
|
|
121
135
|
# anticipate users of Danger needing to use this.
|
122
136
|
#
|
123
137
|
# @visibility hidden
|
124
|
-
# @return
|
138
|
+
# @return [Hash]
|
125
139
|
def violation_report
|
126
140
|
{
|
127
141
|
errors: @errors.clone.freeze,
|
@@ -51,7 +51,7 @@ module Danger
|
|
51
51
|
# Did the linter pass/fail?
|
52
52
|
#
|
53
53
|
def failed?
|
54
|
-
errors.
|
54
|
+
errors.count > 0
|
55
55
|
end
|
56
56
|
|
57
57
|
# Prints a summary of the errors and warnings.
|
@@ -59,15 +59,16 @@ module Danger
|
|
59
59
|
def print_summary(ui)
|
60
60
|
# Print whether it passed/failed at the top
|
61
61
|
if failed?
|
62
|
-
ui.notice "Passed\n"
|
63
|
-
else
|
64
62
|
ui.puts "\n[!] Failed\n".red
|
63
|
+
else
|
64
|
+
ui.notice "Passed"
|
65
65
|
end
|
66
66
|
|
67
67
|
# A generic proc to handle the similarities between
|
68
68
|
# erros and warnings.
|
69
69
|
do_rules = proc do |name, rules|
|
70
70
|
unless rules.empty?
|
71
|
+
ui.puts ""
|
71
72
|
ui.section(name.bold) do
|
72
73
|
rules.each do |rule|
|
73
74
|
title = rule.title.bold + " - #{rule.object_applied_to}"
|
@@ -111,7 +112,7 @@ module Danger
|
|
111
112
|
Rule.new(:error, 40..41, "Description", "You should include a description for your method.", proc do |json|
|
112
113
|
json[:body_md] && json[:body_md].empty?
|
113
114
|
end),
|
114
|
-
Rule.new(:warning, 43..45, "Params", "
|
115
|
+
Rule.new(:warning, 43..45, "Params", "You should give a 'type' for the param, yes, ruby is duck-typey but it's useful for newbies to the language, use `@param [Type] name`.", proc do |json|
|
115
116
|
json[:param_couplets] && json[:param_couplets].flat_map(&:values).include?(nil)
|
116
117
|
end),
|
117
118
|
Rule.new(:warning, 46, "Return Type", "If the function has no useful return value, use ` @return [void]` - this will be ignored by documentation generators.", proc do |json|
|
@@ -34,9 +34,11 @@ module Danger
|
|
34
34
|
class PluginParser
|
35
35
|
attr_accessor :registry
|
36
36
|
|
37
|
-
def initialize(paths)
|
37
|
+
def initialize(paths, verbose = false)
|
38
38
|
raise "Path cannot be empty" if paths.empty?
|
39
39
|
|
40
|
+
setup_yard(verbose)
|
41
|
+
|
40
42
|
if paths.kind_of? String
|
41
43
|
@paths = [File.expand_path(paths)]
|
42
44
|
else
|
@@ -44,12 +46,20 @@ module Danger
|
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
|
-
def
|
49
|
+
def setup_yard(verbose)
|
48
50
|
require 'yard'
|
49
|
-
|
50
|
-
#
|
51
|
+
|
52
|
+
# Unless specifically asked, don't output anything.
|
53
|
+
unless verbose
|
54
|
+
YARD::Logger.instance.level = YARD::Logger::FATAL
|
55
|
+
end
|
56
|
+
|
57
|
+
# Add some of our custom tags
|
51
58
|
YARD::Tags::Library.define_tag('tags', :tags)
|
52
59
|
YARD::Tags::Library.define_tag('availablity', :availablity)
|
60
|
+
end
|
61
|
+
|
62
|
+
def parse
|
53
63
|
files = ["lib/danger/plugin_support/plugin.rb"] + @paths
|
54
64
|
|
55
65
|
# This turns on YARD debugging
|
@@ -153,7 +163,7 @@ module Danger
|
|
153
163
|
attribute_meths = klass.attributes[:instance].values.map(&:values).flatten
|
154
164
|
|
155
165
|
methods = klass.meths - klass.inherited_meths - attribute_meths
|
156
|
-
usable_methods = methods.select { |m| m.visibility == :public }.reject { |m| m.name == :initialize || m.name == :
|
166
|
+
usable_methods = methods.select { |m| m.visibility == :public }.reject { |m| m.name == :initialize || m.name == :instance_name }
|
157
167
|
|
158
168
|
{
|
159
169
|
name: klass.name.to_s,
|
@@ -128,7 +128,12 @@ module Danger
|
|
128
128
|
# use a read-only GitHub account
|
129
129
|
if errors.count > 0
|
130
130
|
# We need to fail the actual build here
|
131
|
-
|
131
|
+
is_private = pr_json[:base][:repo][:private]
|
132
|
+
if is_private
|
133
|
+
abort("\nDanger has failed this build. \nFound #{'error'.danger_pluralize(errors.count)} and I don't have write access to the PR set a PR status.")
|
134
|
+
else
|
135
|
+
abort("\nDanger has failed this build. \nFound #{'error'.danger_pluralize(errors.count)}.")
|
136
|
+
end
|
132
137
|
else
|
133
138
|
puts message
|
134
139
|
end
|
@@ -222,14 +227,56 @@ module Danger
|
|
222
227
|
end
|
223
228
|
|
224
229
|
def parse_tables_from_comment(comment)
|
225
|
-
comment.split(
|
230
|
+
comment.split("</table>")
|
226
231
|
end
|
227
232
|
|
228
233
|
def process_markdown(violation)
|
229
234
|
html = markdown_parser.render(violation.message)
|
230
|
-
|
231
|
-
|
232
|
-
Violation.new(
|
235
|
+
# Remove the outer `<p>`, the -5 represents a newline + `</p>`
|
236
|
+
html = html[3...-5] if html.start_with? "<p>"
|
237
|
+
Violation.new(html, violation.sticky)
|
238
|
+
end
|
239
|
+
|
240
|
+
# @return [String] The organisation name, is nil if it can't be detected
|
241
|
+
def organisation
|
242
|
+
matched = self.issue_json[:repository_url].match(%r{repos\/(.*)\/})
|
243
|
+
return matched[1] if matched && matched[1]
|
244
|
+
rescue
|
245
|
+
nil
|
246
|
+
end
|
247
|
+
|
248
|
+
# @return [Hash] with the information about the repo
|
249
|
+
# returns nil if the repo is not available
|
250
|
+
def fetch_repository(organisation: nil, repository: nil)
|
251
|
+
organisation ||= self.organisation
|
252
|
+
repository ||= self.ci_source.repo_slug.split("/").last
|
253
|
+
self.client.repo("#{organisation}/#{repository}")
|
254
|
+
rescue Octokit::NotFound
|
255
|
+
nil # repo doesn't exist
|
256
|
+
end
|
257
|
+
|
258
|
+
# @return [Hash] with the information about the repo.
|
259
|
+
# This will automatically detect if the repo is capitalised
|
260
|
+
# returns nil if there is no danger repo
|
261
|
+
def fetch_danger_repo(organisation: nil)
|
262
|
+
data = nil
|
263
|
+
data ||= fetch_repository(organisation: organisation, repository: DANGER_REPO_NAME.downcase)
|
264
|
+
data ||= fetch_repository(organisation: organisation, repository: DANGER_REPO_NAME.capitalize)
|
265
|
+
data
|
266
|
+
end
|
267
|
+
|
268
|
+
# @return [Bool] is this repo the danger repo of the org?
|
269
|
+
def danger_repo?(organisation: nil, repository: nil)
|
270
|
+
repo = fetch_repository(organisation: organisation, repository: repository)
|
271
|
+
repo[:name].casecmp(DANGER_REPO_NAME).zero?
|
272
|
+
rescue
|
273
|
+
false
|
274
|
+
end
|
275
|
+
|
276
|
+
# @return [String] A URL to the specific file, ready to be downloaded
|
277
|
+
def file_url(organisation: nil, repository: nil, branch: 'master', path: nil)
|
278
|
+
organisation ||= self.organisation
|
279
|
+
"https://raw.githubusercontent.com/#{organisation}/#{repository}/#{branch}/#{path}"
|
233
280
|
end
|
234
281
|
end
|
235
282
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
module Danger
|
2
2
|
module RequestSources
|
3
3
|
class RequestSource
|
4
|
+
DANGER_REPO_NAME = "danger".freeze
|
5
|
+
|
4
6
|
attr_accessor :ci_source, :environment, :scm, :host, :ignored_violations
|
5
7
|
|
6
8
|
def self.inherited(child_class)
|
@@ -43,6 +45,26 @@ module Danger
|
|
43
45
|
def fetch_details
|
44
46
|
raise "Subclass and overwrite initialize"
|
45
47
|
end
|
48
|
+
|
49
|
+
def organisation
|
50
|
+
raise "Subclass and overwrite organisation"
|
51
|
+
end
|
52
|
+
|
53
|
+
def fetch_repository(_organisation: nil, _repository: nil)
|
54
|
+
raise "Subclass and overwrite fetch_repository"
|
55
|
+
end
|
56
|
+
|
57
|
+
def fetch_danger_repo(_organisation: nil)
|
58
|
+
raise "Subclass and overwrite fetch_danger_repo"
|
59
|
+
end
|
60
|
+
|
61
|
+
def danger_repo?(_organisation: nil, _repository: nil)
|
62
|
+
raise "Subclass and overwrite danger_repo?"
|
63
|
+
end
|
64
|
+
|
65
|
+
def file_url(_organisation: nil, _repository: nil, _branch: "master", _path: nil)
|
66
|
+
raise "Subclass and overwrite file_url"
|
67
|
+
end
|
46
68
|
end
|
47
69
|
end
|
48
70
|
end
|
data/lib/danger/version.rb
CHANGED
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: 0.
|
4
|
+
version: 0.10.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-
|
12
|
+
date: 2016-07-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: claide
|
@@ -81,6 +81,20 @@ dependencies:
|
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: faraday-http-cache
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - "~>"
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '1.0'
|
91
|
+
type: :runtime
|
92
|
+
prerelease: false
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - "~>"
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '1.0'
|
84
98
|
- !ruby/object:Gem::Dependency
|
85
99
|
name: octokit
|
86
100
|
requirement: !ruby/object:Gem::Requirement
|
@@ -322,6 +336,7 @@ files:
|
|
322
336
|
- lib/danger/commands/init.rb
|
323
337
|
- lib/danger/commands/init_helpers/interviewer.rb
|
324
338
|
- lib/danger/commands/local.rb
|
339
|
+
- lib/danger/commands/local_helpers/http_cache.rb
|
325
340
|
- lib/danger/commands/plugins/plugin_json.rb
|
326
341
|
- lib/danger/commands/plugins/plugin_lint.rb
|
327
342
|
- lib/danger/commands/plugins/plugin_readme.rb
|
@@ -332,6 +347,7 @@ files:
|
|
332
347
|
- lib/danger/danger_core/dangerfile.rb
|
333
348
|
- lib/danger/danger_core/dangerfile_dsl.rb
|
334
349
|
- lib/danger/danger_core/environment_manager.rb
|
350
|
+
- lib/danger/danger_core/executor.rb
|
335
351
|
- lib/danger/danger_core/plugins/dangerfile_git_plugin.rb
|
336
352
|
- lib/danger/danger_core/plugins/dangerfile_github_plugin.rb
|
337
353
|
- lib/danger/danger_core/plugins/dangerfile_import_plugin.rb
|
@@ -367,7 +383,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
367
383
|
version: '0'
|
368
384
|
requirements: []
|
369
385
|
rubyforge_project:
|
370
|
-
rubygems_version: 2.
|
386
|
+
rubygems_version: 2.2.2
|
371
387
|
signing_key:
|
372
388
|
specification_version: 4
|
373
389
|
summary: Automate your PR etiquette.
|