danger 0.7.2 → 0.8.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 +35 -13
- data/lib/danger/ci_source/circle.rb +1 -1
- data/lib/danger/ci_source/drone.rb +18 -0
- data/lib/danger/ci_source/local_git_repo.rb +11 -2
- data/lib/danger/ci_source/semaphore.rb +18 -0
- data/lib/danger/commands/init.rb +8 -8
- data/lib/danger/commands/local.rb +26 -8
- data/lib/danger/commands/new_plugin.rb +0 -8
- data/lib/danger/commands/runner.rb +32 -18
- data/lib/danger/comment_generators/github.md.erb +1 -1
- data/lib/danger/{scm_source → core_ext}/file_list.rb +1 -0
- data/lib/danger/core_ext/string.rb +4 -0
- data/lib/danger/danger_core/dangerfile.rb +217 -0
- data/lib/danger/danger_core/dangerfile_dsl.rb +29 -0
- data/lib/danger/{environment_manager.rb → danger_core/environment_manager.rb} +16 -8
- data/lib/danger/danger_core/plugins/dangerfile_git_plugin.rb +69 -0
- data/lib/danger/danger_core/plugins/dangerfile_github_plugin.rb +68 -0
- data/lib/danger/danger_core/plugins/dangerfile_import_plugin.rb +58 -0
- data/lib/danger/danger_core/plugins/dangerfile_messaging_plugin.rb +87 -0
- data/lib/danger/{standard_error.rb → danger_core/standard_error.rb} +1 -1
- data/lib/danger/plugin_support/plugin.rb +31 -0
- data/lib/danger/plugin_support/plugin_parser.rb +70 -0
- data/lib/danger/{request_sources → request_source}/github.rb +6 -37
- data/lib/danger/scm_source/git_repo.rb +2 -25
- data/lib/danger/version.rb +1 -1
- data/lib/danger.rb +3 -4
- metadata +79 -17
- data/lib/danger/available_values.rb +0 -28
- data/lib/danger/dangerfile.rb +0 -123
- data/lib/danger/dangerfile_dsl.rb +0 -159
- data/lib/danger/plugin.rb +0 -26
- data/lib/danger/plugins/protect_files.rb +0 -34
- /data/lib/danger/{circle_api.rb → ci_source/circle_api.rb} +0 -0
- /data/lib/danger/{violation.rb → danger_core/violation.rb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f195902ac5ec8dbc7c67059f6484d9c548fa1b9b
|
|
4
|
+
data.tar.gz: af4335f0b4691d17bc27b801b17885f01e9ead07
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9948b94a2189dd1e4f131f2f0e2265aa666322edfb59f4df8c741d91296f01d684059f11ef67878f6957532f6edba115fbd16071c8b48db01924d36a08584dbe
|
|
7
|
+
data.tar.gz: 44c3f8b65bd973eb45175b0b494e07749508e91514e55e8179785edcd567fffc736974eeacda00f850671761e72607463788b70ad6e1bc865e2d821c02950f9b
|
data/README.md
CHANGED
|
@@ -8,12 +8,11 @@ Formalize your Pull Request etiquette.
|
|
|
8
8
|
-------
|
|
9
9
|
|
|
10
10
|
<p align="center">
|
|
11
|
-
<a href="#
|
|
12
|
-
<a href="#usage">Usage</a> •
|
|
11
|
+
<a href="#getting-started">Getting Started</a> •
|
|
12
|
+
<a href="#usage-on-ci">Usage</a> •
|
|
13
13
|
<a href="#dsl">DSL</a> •
|
|
14
|
-
<a href="#
|
|
15
|
-
<a href="#
|
|
16
|
-
<a href="#contributing">Contributing</a>
|
|
14
|
+
<a href="#plugins">Plugins</a> •
|
|
15
|
+
<a href="#test-locally-with-danger-local">Local</a>
|
|
17
16
|
</p>
|
|
18
17
|
|
|
19
18
|
-------
|
|
@@ -32,6 +31,8 @@ To get up and running quickly, just run
|
|
|
32
31
|
bundle exec danger init
|
|
33
32
|
```
|
|
34
33
|
|
|
34
|
+
The guide will create a default `Dangerfile` and take you through the process of setting up an account for feedback on GitHub.
|
|
35
|
+
|
|
35
36
|
## Usage on CI
|
|
36
37
|
|
|
37
38
|
```
|
|
@@ -40,6 +41,10 @@ bundle exec danger
|
|
|
40
41
|
|
|
41
42
|
This will look at your `Dangerfile` and update the pull request accordingly. While you are setting up Danger, you may want to use: `--verbose` for more debug information.
|
|
42
43
|
|
|
44
|
+
## CI Support
|
|
45
|
+
|
|
46
|
+
Danger currently is supported on Travis CI, Circle CI, Xcode Bots via Buildasaur, BuildKite, Jenkins, Semaphore, and Drone CI. These work via environment variables, so it's easy to extend to include your own.
|
|
47
|
+
|
|
43
48
|
## What happens?
|
|
44
49
|
|
|
45
50
|
Danger runs at the end of a CI build, she will execute a `Dangerfile`. This file is given some special variables based on the git diff and the Pull Request being running. You can use these variables in Ruby to provide messages, warnings and failures for your build. You set up Danger with a GitHub user account and she will post updates via comments on the Pull Request, and can fail your build too.
|
|
@@ -113,7 +118,7 @@ Command | Description
|
|
|
113
118
|
|
|
114
119
|
## Plugins
|
|
115
120
|
|
|
116
|
-
Danger was built with a platform in mind:
|
|
121
|
+
Danger was built with a platform in mind: she can be used with any kind of software project and allows you to write your own action to have structured source code.
|
|
117
122
|
|
|
118
123
|
In your `Dangerfile` you can import local or remote actions using
|
|
119
124
|
|
|
@@ -134,11 +139,7 @@ To create a new plugin run
|
|
|
134
139
|
danger new_plugin
|
|
135
140
|
```
|
|
136
141
|
|
|
137
|
-
This will generate a new Ruby file which you can modify to fit your needs.
|
|
138
|
-
|
|
139
|
-
## Support
|
|
140
|
-
|
|
141
|
-
Danger currently is supported on Travis CI, Circle CI, BuildKite and Jenkins. These work via environment variables, so it's easy to extend to include your own.
|
|
142
|
+
This will generate a new Ruby file which you can modify to fit your needs.
|
|
142
143
|
|
|
143
144
|
## Advanced
|
|
144
145
|
|
|
@@ -155,8 +156,24 @@ open to turning useful bits into the official API.
|
|
|
155
156
|
|
|
156
157
|
## Test locally with `danger local`
|
|
157
158
|
|
|
158
|
-
|
|
159
|
-
`Dangerfile` against that Pull Request.
|
|
159
|
+
You can use `danger local` to run Danger in an environment similar to how she will be ran on CI. By default Danger will look
|
|
160
|
+
at the most recently merged PR, then run your `Dangerfile` against that Pull Request. This is really useful when making changes.
|
|
161
|
+
|
|
162
|
+
If you have a specific PR in mind that you'd like to work against, make sure you have it merged in your current git
|
|
163
|
+
history, then append `--use-merged-pr=[id]` to the command.
|
|
164
|
+
|
|
165
|
+
### Adding a new CI
|
|
166
|
+
If the CI server you're using isn't available yet, you can build it yourself:
|
|
167
|
+
|
|
168
|
+
Take a look at some of the [already existing integrations](https://github.com/danger/danger/tree/master/lib/danger/ci_source). The class has 2 mandatory methods:
|
|
169
|
+
|
|
170
|
+
- `self.validates?` which should detect if the CI is active (detecting via ENV variables, mostly)
|
|
171
|
+
- `initialize` which should set 2 variables:
|
|
172
|
+
- `self.repo_slug` the repo slug, in `org/repo` or `user/repo` format.
|
|
173
|
+
- `self.pull_request_id` the number of the pull request that the CI is testing (often available in ENV variables)
|
|
174
|
+
|
|
175
|
+
We'd love to see pull requests for new integrations!
|
|
176
|
+
|
|
160
177
|
|
|
161
178
|
## Suppress Violations
|
|
162
179
|
|
|
@@ -182,6 +199,11 @@ fail("PR needs labels", sticky: false) if pr_labels.empty?
|
|
|
182
199
|
|
|
183
200
|
Here are some real-world Dangerfiles: [artsy/eigen](https://github.com/artsy/eigen/blob/master/Dangerfile), [danger/danger](https://github.com/danger/danger/blob/master/Dangerfile), [artsy/elan](https://github.com/artsy/elan/blob/master/Dangerfile) and more!
|
|
184
201
|
|
|
202
|
+
## Usage with GitHub Enterprise
|
|
203
|
+
Danger allows usage with GitHub Enterprise by setting 2 environment variables:
|
|
204
|
+
- `DANGER_GITHUB_HOST` to the host that GitHub is running on
|
|
205
|
+
- `DANGER_GITHUB_API_HOST` to the host that the GitHub Enterprise API is reachable on.
|
|
206
|
+
|
|
185
207
|
## License, Contributor's Guidelines and Code of Conduct
|
|
186
208
|
|
|
187
209
|
[Join our Slack Group](https://danger-slack.herokuapp.com/)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# http://readme.drone.io/usage/variables/
|
|
2
|
+
|
|
3
|
+
module Danger
|
|
4
|
+
module CISource
|
|
5
|
+
class Drone < CI
|
|
6
|
+
def self.validates?(env)
|
|
7
|
+
return !env["DRONE"].nil?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(env)
|
|
11
|
+
self.repo_slug = env["DRONE_REPO"]
|
|
12
|
+
if env["DRONE_PULL_REQUEST"].to_i > 0
|
|
13
|
+
self.pull_request_id = env["DRONE_PULL_REQUEST"]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -34,10 +34,19 @@ module Danger
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
specific_pr = env["LOCAL_GIT_PR_ID"]
|
|
38
|
+
pr_ref = specific_pr ? "##{specific_pr}" : ''
|
|
39
|
+
pr_command = "log --merges --oneline | grep \"Merge pull request #{pr_ref}\" | head -n 1"
|
|
40
|
+
|
|
37
41
|
# get the most recent PR merge
|
|
38
|
-
pr_merge = run_git
|
|
42
|
+
pr_merge = run_git pr_command.strip
|
|
43
|
+
|
|
39
44
|
if pr_merge.to_s.empty?
|
|
40
|
-
|
|
45
|
+
if specific_pr
|
|
46
|
+
raise "Could not find the pull request (#{specific_pr}) inside the git history for this repo."
|
|
47
|
+
else
|
|
48
|
+
raise "No recent pull requests found for this repo, danger requires at least one PR for the local mode."
|
|
49
|
+
end
|
|
41
50
|
end
|
|
42
51
|
|
|
43
52
|
self.pull_request_id = pr_merge.match("#([0-9]+)")[1]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# https://semaphoreci.com/docs/available-environment-variables.html
|
|
2
|
+
|
|
3
|
+
module Danger
|
|
4
|
+
module CISource
|
|
5
|
+
class Semaphore < CI
|
|
6
|
+
def self.validates?(env)
|
|
7
|
+
return !env["SEMAPHORE"].nil?
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def initialize(env)
|
|
11
|
+
self.repo_slug = env["SEMAPHORE_REPO_SLUG"]
|
|
12
|
+
if env["PULL_REQUEST_NUMBER"].to_i > 0
|
|
13
|
+
self.pull_request_id = env["PULL_REQUEST_NUMBER"]
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/danger/commands/init.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Danger
|
|
|
23
23
|
|
|
24
24
|
def run
|
|
25
25
|
ui = Interviewer.new
|
|
26
|
-
ui.say "\nOK, thanks #{ENV['LOGNAME']},
|
|
26
|
+
ui.say "\nOK, thanks #{ENV['LOGNAME']}, have a seat and we'll get you started.\n".yellow
|
|
27
27
|
ui.pause 1
|
|
28
28
|
|
|
29
29
|
show_todo_state
|
|
@@ -43,11 +43,11 @@ module Danger
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def show_todo_state
|
|
46
|
-
ui.say "We need to do the following
|
|
46
|
+
ui.say "We need to do the following:\n"
|
|
47
47
|
ui.pause 0.6
|
|
48
48
|
ui.say " - [ ] Create a Dangerfile and add a few simple rules."
|
|
49
49
|
ui.pause 0.6
|
|
50
|
-
ui.say " - [#{@account_created ? 'x' : ' '}] Create a GitHub account for Danger use for messaging."
|
|
50
|
+
ui.say " - [#{@account_created ? 'x' : ' '}] Create a GitHub account for Danger to use, for messaging."
|
|
51
51
|
ui.pause 0.6
|
|
52
52
|
ui.say " - [ ] Set up an access token for Danger."
|
|
53
53
|
ui.pause 0.6
|
|
@@ -71,7 +71,7 @@ module Danger
|
|
|
71
71
|
ui.pause 2
|
|
72
72
|
|
|
73
73
|
ui.say "There's a collection of small, simple ideas in here, but Danger is about being able to easily"
|
|
74
|
-
ui.say "iterate. The power comes from you
|
|
74
|
+
ui.say "iterate. The power comes from you having the ability to codify fixes for some of the problems"
|
|
75
75
|
ui.say "that come up in day to day programming. It can be difficult to try and see those from day 1."
|
|
76
76
|
|
|
77
77
|
ui.say "\nIf you'd like to investigate the file, and make some changes - I'll wait here,"
|
|
@@ -113,7 +113,7 @@ module Danger
|
|
|
113
113
|
ui.say "For Open Source projects, I'd recommend giving the token the smallest scope possible."
|
|
114
114
|
ui.say "This means only providing access to " + "public_repo".yellow + " in the token.\n\n"
|
|
115
115
|
ui.pause 1
|
|
116
|
-
ui.say "This token limits Danger's abilities to just
|
|
116
|
+
ui.say "This token limits Danger's abilities to just writing comments on OSS projects. I recommend"
|
|
117
117
|
ui.say "this because the token can quite easily be extracted from the environment via pull requests."
|
|
118
118
|
ui.say "#{@bot_name} does not need admin access to your repo. So its ability to cause chaos is minimalized.\n"
|
|
119
119
|
|
|
@@ -148,7 +148,7 @@ module Danger
|
|
|
148
148
|
ui.say "\nOK, I'll give you a moment to do this..."
|
|
149
149
|
ui.wait_for_return
|
|
150
150
|
|
|
151
|
-
ui.
|
|
151
|
+
ui.header "Final step: exposing the GitHub token as an environment build variable."
|
|
152
152
|
ui.pause 0.4
|
|
153
153
|
if considered_an_oss_repo?
|
|
154
154
|
ui.say "As you have an Open Source repo, this token should be considered public, otherwise you cannot"
|
|
@@ -207,7 +207,7 @@ module Danger
|
|
|
207
207
|
# https://travis-ci.org/artsy/eigen/settings
|
|
208
208
|
ui.say "In order to add an environment variable, go to:"
|
|
209
209
|
ui.link "https://travis-ci.org/#{current_repo_slug}/settings"
|
|
210
|
-
ui.say "\nThe name is " + "DANGER_GITHUB_API_TOKEN".yellow + " and the value is the GitHub Personal
|
|
210
|
+
ui.say "\nThe name is " + "DANGER_GITHUB_API_TOKEN".yellow + " and the value is the GitHub Personal Access Token."
|
|
211
211
|
if @is_open_source
|
|
212
212
|
ui.say "Make sure to have \"Display value in build log\" enabled."
|
|
213
213
|
end
|
|
@@ -262,7 +262,7 @@ module Danger
|
|
|
262
262
|
ui.say "\n\n🎉"
|
|
263
263
|
ui.pause 0.6
|
|
264
264
|
|
|
265
|
-
ui.say "And you're
|
|
265
|
+
ui.say "And you're good to go. Danger is a collaboration between Orta Therox, Gem 'Danger' McShane and Felix Krause."
|
|
266
266
|
ui.say "If you like it, let others know. If you want to know more, follow " + "@orta".yellow + " and " + "@KrauseFx".yellow + " on Twitter."
|
|
267
267
|
ui.say "If you don't like it, help us improve it! xxx"
|
|
268
268
|
end
|
|
@@ -5,9 +5,16 @@ module Danger
|
|
|
5
5
|
|
|
6
6
|
def initialize(argv)
|
|
7
7
|
@dangerfile_path = "Dangerfile" if File.exist? "Dangerfile"
|
|
8
|
+
@pr_num = argv.option('use-merged-pr')
|
|
8
9
|
super
|
|
9
10
|
end
|
|
10
11
|
|
|
12
|
+
def self.options
|
|
13
|
+
[
|
|
14
|
+
['--use-merged-pr=[#id]', 'The ID of an already merged PR inside your history to use as a reference for the local run.']
|
|
15
|
+
].concat(super)
|
|
16
|
+
end
|
|
17
|
+
|
|
11
18
|
def validate!
|
|
12
19
|
super
|
|
13
20
|
unless @dangerfile_path
|
|
@@ -17,9 +24,11 @@ module Danger
|
|
|
17
24
|
|
|
18
25
|
def run
|
|
19
26
|
ENV["DANGER_USE_LOCAL_GIT"] = "YES"
|
|
27
|
+
ENV["LOCAL_GIT_PR_ID"] = @pr_num if @pr_num
|
|
20
28
|
|
|
21
|
-
|
|
22
|
-
dm
|
|
29
|
+
env = EnvironmentManager.new(ENV)
|
|
30
|
+
dm = Dangerfile.new(env)
|
|
31
|
+
dm.init_plugins
|
|
23
32
|
|
|
24
33
|
source = dm.env.ci_source
|
|
25
34
|
if source.nil? or source.repo_slug.empty?
|
|
@@ -41,15 +50,24 @@ module Danger
|
|
|
41
50
|
# We can use tokenless here, as it's running on someone's computer
|
|
42
51
|
# and is IP locked, as opposed to on the CI.
|
|
43
52
|
gh.support_tokenless_auth = true
|
|
44
|
-
gh.fetch_details
|
|
45
53
|
|
|
46
|
-
|
|
54
|
+
begin
|
|
55
|
+
gh.fetch_details
|
|
56
|
+
rescue Octokit::NotFound
|
|
57
|
+
puts "Local repository was not found on GitHub. If you're trying to test a private repository please provide a valid API token through " + "DANGER_GITHUB_API_TOKEN".yellow + " environment variable."
|
|
58
|
+
return
|
|
59
|
+
end
|
|
47
60
|
|
|
48
|
-
dm.env.
|
|
61
|
+
dm.env.request_source = gh
|
|
49
62
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
begin
|
|
64
|
+
dm.env.ensure_danger_branches_are_setup
|
|
65
|
+
dm.env.scm.diff_for_folder(".", from: dm.env.ci_source.base_commit, to: dm.env.ci_source.head_commit)
|
|
66
|
+
dm.parse(Pathname.new(@dangerfile_path))
|
|
67
|
+
dm.print_results
|
|
68
|
+
ensure
|
|
69
|
+
dm.env.clean_up
|
|
70
|
+
end
|
|
53
71
|
end
|
|
54
72
|
end
|
|
55
73
|
end
|
|
@@ -6,9 +6,13 @@ module Danger
|
|
|
6
6
|
|
|
7
7
|
self.summary = 'Run the Dangerfile.'
|
|
8
8
|
self.command = 'danger'
|
|
9
|
+
self.version = Danger::VERSION
|
|
10
|
+
|
|
11
|
+
self.plugin_prefixes = %w(claide danger)
|
|
9
12
|
|
|
10
13
|
def initialize(argv)
|
|
11
|
-
|
|
14
|
+
dangerfile = argv.option('dangerfile', 'Dangerfile')
|
|
15
|
+
@dangerfile_path = dangerfile if File.exist? dangerfile
|
|
12
16
|
@base = argv.option('base')
|
|
13
17
|
@head = argv.option('head')
|
|
14
18
|
super
|
|
@@ -24,37 +28,47 @@ module Danger
|
|
|
24
28
|
def self.options
|
|
25
29
|
[
|
|
26
30
|
['--base=[master|dev|stable]', 'A branch/tag/commit to use as the base of the diff'],
|
|
27
|
-
['--head=[master|dev|stable]', 'A branch/tag/commit to use as the head']
|
|
31
|
+
['--head=[master|dev|stable]', 'A branch/tag/commit to use as the head'],
|
|
32
|
+
['--dangerfile=<path/to/dangerfile>', 'The location of your Dangerfile']
|
|
28
33
|
].concat(super)
|
|
29
34
|
end
|
|
30
35
|
|
|
31
36
|
def run
|
|
32
|
-
|
|
33
|
-
dm = Dangerfile.new
|
|
34
|
-
dm.verbose = verbose
|
|
35
|
-
dm.env = EnvironmentManager.new(ENV)
|
|
36
|
-
return unless dm.env.ci_source # if it's not a PR
|
|
37
|
+
env = EnvironmentManager.new(ENV)
|
|
38
|
+
dm = Dangerfile.new(env)
|
|
37
39
|
|
|
38
|
-
dm.env.
|
|
39
|
-
|
|
40
|
+
if dm.env.pr?
|
|
41
|
+
dm.verbose = verbose
|
|
42
|
+
dm.init_plugins
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
ci_base = @base || dm.env.danger_head_branch
|
|
43
|
-
ci_head = @head || dm.env.danger_base_branch
|
|
44
|
-
dm.env.scm.diff_for_folder(".", from: ci_base, to: ci_head)
|
|
44
|
+
dm.env.fill_environment_vars
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
begin
|
|
47
|
+
dm.env.ensure_danger_branches_are_setup
|
|
47
48
|
|
|
48
|
-
|
|
49
|
+
# Offer the chance for a user to specify a branch through the command line
|
|
50
|
+
ci_base = @base || dm.env.danger_head_branch
|
|
51
|
+
ci_head = @head || dm.env.danger_base_branch
|
|
52
|
+
dm.env.scm.diff_for_folder(".", from: ci_base, to: ci_head)
|
|
49
53
|
|
|
50
|
-
|
|
54
|
+
dm.parse Pathname.new(@dangerfile_path)
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
post_results dm
|
|
57
|
+
dm.print_results
|
|
58
|
+
ensure
|
|
59
|
+
dm.env.clean_up
|
|
60
|
+
end
|
|
61
|
+
else
|
|
62
|
+
puts "Not a Pull Request - skipping `danger` run"
|
|
63
|
+
end
|
|
53
64
|
end
|
|
54
65
|
|
|
55
66
|
def post_results(dm)
|
|
56
67
|
gh = dm.env.request_source
|
|
57
|
-
|
|
68
|
+
violations = dm.violation_report
|
|
69
|
+
status = dm.status_report
|
|
70
|
+
|
|
71
|
+
gh.update_pull_request!(warnings: violations[:warnings], errors: violations[:errors], messages: violations[:messages], markdowns: status[:markdowns])
|
|
58
72
|
end
|
|
59
73
|
end
|
|
60
74
|
end
|
|
@@ -36,6 +36,6 @@
|
|
|
36
36
|
<%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
|
|
37
37
|
<% end %>
|
|
38
38
|
|
|
39
|
-
<p align="right" data-meta="generated_by_danger"
|
|
39
|
+
<p align="right" data-meta="generated_by_danger">
|
|
40
40
|
Generated by :no_entry_sign: <a href="https://github.com/danger/danger/">danger</a>
|
|
41
41
|
</p>
|
|
@@ -2,6 +2,7 @@ module Danger
|
|
|
2
2
|
class FileList < Array
|
|
3
3
|
# Information about pattern: http://ruby-doc.org/core-2.2.0/File.html#method-c-fnmatch
|
|
4
4
|
# e.g. "**/something.*" for any file called something with any extension
|
|
5
|
+
|
|
5
6
|
def include?(pattern)
|
|
6
7
|
self.each do |current|
|
|
7
8
|
return true if File.fnmatch(pattern, current)
|
|
@@ -0,0 +1,217 @@
|
|
|
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
|
+
|
|
6
|
+
require 'danger/danger_core/plugins/dangerfile_messaging_plugin'
|
|
7
|
+
require 'danger/danger_core/plugins/dangerfile_import_plugin'
|
|
8
|
+
require 'danger/danger_core/plugins/dangerfile_git_plugin'
|
|
9
|
+
require 'danger/danger_core/plugins/dangerfile_github_plugin'
|
|
10
|
+
|
|
11
|
+
require 'danger/danger_core/plugins/dangerfile_github_plugin'
|
|
12
|
+
|
|
13
|
+
module Danger
|
|
14
|
+
class Dangerfile
|
|
15
|
+
include Danger::Dangerfile::DSL
|
|
16
|
+
|
|
17
|
+
attr_accessor :env, :verbose, :plugins
|
|
18
|
+
|
|
19
|
+
# @return [Pathname] the path where the Dangerfile was loaded from. It is nil
|
|
20
|
+
# if the Dangerfile was generated programmatically.
|
|
21
|
+
#
|
|
22
|
+
attr_accessor :defined_in_file
|
|
23
|
+
|
|
24
|
+
# @return [String] a string useful to represent the Dangerfile in a message
|
|
25
|
+
# presented to the user.
|
|
26
|
+
#
|
|
27
|
+
def to_s
|
|
28
|
+
'Dangerfile'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# These are the classes that are allowed to also use method_missing
|
|
32
|
+
# in order to provide broader plugin support
|
|
33
|
+
def core_plugin_classes
|
|
34
|
+
[
|
|
35
|
+
Danger::DangerfileMessagingPlugin,
|
|
36
|
+
Danger::DangerfileImportPlugin,
|
|
37
|
+
Danger::DangerfileGitHubPlugin,
|
|
38
|
+
Danger::DangerfileGitPlugin
|
|
39
|
+
]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Both of these methods exist on all objects
|
|
43
|
+
# http://ruby-doc.org/core-2.2.3/Kernel.html#method-i-warn
|
|
44
|
+
# http://ruby-doc.org/core-2.2.3/Kernel.html#method-i-fail
|
|
45
|
+
# However, as we're using using them in the DSL, they won't
|
|
46
|
+
# get method_missing called correctly.
|
|
47
|
+
|
|
48
|
+
def warn(*args, &blk)
|
|
49
|
+
method_missing(:warn, *args, &blk)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def fail(*args, &blk)
|
|
53
|
+
method_missing(:fail, *args, &blk)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# When an undefined method is called, we check to see if it's something
|
|
57
|
+
# that the DSLs have, then starts looking at plugins support.
|
|
58
|
+
def method_missing(method_sym, *arguments, &_block)
|
|
59
|
+
@core_plugins.each do |plugin|
|
|
60
|
+
if plugin.public_methods(false).include?(method_sym)
|
|
61
|
+
return plugin.send(method_sym, *arguments)
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
super
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def initialize(env_manager)
|
|
68
|
+
@plugins = {}
|
|
69
|
+
@core_plugins = []
|
|
70
|
+
|
|
71
|
+
# Triggers the core plugins
|
|
72
|
+
@env = env_manager
|
|
73
|
+
|
|
74
|
+
# Triggers local plugins from the root of a project
|
|
75
|
+
Dir["./danger_plugins/*.rb"].each do |file|
|
|
76
|
+
require File.expand_path(file)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
refresh_plugins if env_manager.pr?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Iterate through available plugin classes and initialize them with
|
|
83
|
+
# a reference to this Dangerfile
|
|
84
|
+
def refresh_plugins
|
|
85
|
+
plugins = ObjectSpace.each_object(Class).select { |klass| klass < Danger::Plugin }
|
|
86
|
+
plugins.each do |klass|
|
|
87
|
+
next if klass.singleton_class?
|
|
88
|
+
plugin = klass.new(self)
|
|
89
|
+
next if plugin.nil? || @plugins[klass]
|
|
90
|
+
|
|
91
|
+
name = plugin.class.instance_name
|
|
92
|
+
self.class.send(:attr_reader, name)
|
|
93
|
+
instance_variable_set("@#{name}", plugin)
|
|
94
|
+
|
|
95
|
+
@plugins[klass] = plugin
|
|
96
|
+
@core_plugins << plugin if core_plugin_classes.include? klass
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
alias init_plugins refresh_plugins
|
|
100
|
+
|
|
101
|
+
def core_dsl_attributes
|
|
102
|
+
@core_plugins.map { |plugin| { plugin: plugin, methods: plugin.public_methods(false) } }
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def external_dsl_attributes
|
|
106
|
+
plugins.values.reject { |plugin| @core_plugins.include? plugin } .map { |plugin| { plugin: plugin, methods: plugin.public_methods(false) } }
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def method_values_for_plugin_hashes(plugin_hashes)
|
|
110
|
+
plugin_hashes.flat_map do |plugin_hash|
|
|
111
|
+
plugin = plugin_hash[:plugin]
|
|
112
|
+
methods = plugin_hash[:methods].reject { |name| plugin.method(name).arity != 0 }
|
|
113
|
+
|
|
114
|
+
methods.map do |method|
|
|
115
|
+
value = plugin.send(method)
|
|
116
|
+
value = value.scan(/.{,80}/).to_a.each(&:strip!).join("\n") if method == :pr_body
|
|
117
|
+
|
|
118
|
+
# So that we either have one value per row
|
|
119
|
+
# or we have [] for an empty array
|
|
120
|
+
value = value.join("\n") if value.kind_of?(Array) && value.count > 0
|
|
121
|
+
[method.to_s, value]
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Iterates through the DSL's attributes, and table's the output
|
|
127
|
+
def print_known_info
|
|
128
|
+
rows = []
|
|
129
|
+
rows += method_values_for_plugin_hashes(core_dsl_attributes)
|
|
130
|
+
rows << ["---", "---"]
|
|
131
|
+
rows += method_values_for_plugin_hashes(external_dsl_attributes)
|
|
132
|
+
rows << ["---", "---"]
|
|
133
|
+
rows << ["SCM", env.scm.class]
|
|
134
|
+
rows << ["Source", env.ci_source.class]
|
|
135
|
+
rows << ["Requests", env.request_source.class]
|
|
136
|
+
rows << ["Base Commit", env.meta_info_for_base]
|
|
137
|
+
rows << ["Head Commit", env.meta_info_for_head]
|
|
138
|
+
|
|
139
|
+
params = {}
|
|
140
|
+
params[:rows] = rows.each { |current| current[0] = current[0].yellow }
|
|
141
|
+
params[:title] = "Danger v#{Danger::VERSION}\nDSL Attributes".green
|
|
142
|
+
|
|
143
|
+
puts ""
|
|
144
|
+
puts Terminal::Table.new(params)
|
|
145
|
+
puts ""
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Parses the file at a path, optionally takes the content of the file for DI
|
|
149
|
+
#
|
|
150
|
+
def parse(path, contents = nil)
|
|
151
|
+
print_known_info if verbose
|
|
152
|
+
|
|
153
|
+
contents ||= File.open(path, 'r:utf-8', &:read)
|
|
154
|
+
|
|
155
|
+
# Work around for Rubinius incomplete encoding in 1.9 mode
|
|
156
|
+
if contents.respond_to?(:encoding) && contents.encoding.name != 'UTF-8'
|
|
157
|
+
contents.encode!('UTF-8')
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
if contents.tr!('“”‘’‛', %(""'''))
|
|
161
|
+
# Changes have been made
|
|
162
|
+
puts "Your #{path.basename} has had smart quotes sanitised. " \
|
|
163
|
+
'To avoid issues in the future, you should not use ' \
|
|
164
|
+
'TextEdit for editing it. If you are not using TextEdit, ' \
|
|
165
|
+
'you should turn off smart quotes in your editor of choice.'.red
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
if contents.include?("puts")
|
|
169
|
+
puts "You used `puts` in your Dangerfile. To print out text to GitHub use `message` instead"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
self.defined_in_file = path
|
|
173
|
+
instance_eval do
|
|
174
|
+
# rubocop:disable Lint/RescueException
|
|
175
|
+
begin
|
|
176
|
+
# rubocop:disable Eval
|
|
177
|
+
eval(contents, nil, path.to_s)
|
|
178
|
+
# rubocop:enable Eval
|
|
179
|
+
rescue Exception => e
|
|
180
|
+
message = "Invalid `#{path.basename}` file: #{e.message}"
|
|
181
|
+
raise DSLError.new(message, path, e.backtrace, contents)
|
|
182
|
+
end
|
|
183
|
+
# rubocop:enable Lint/RescueException
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def print_results
|
|
188
|
+
status = status_report
|
|
189
|
+
return if (status[:errors] + status[:warnings] + status[:messages] + status[:markdowns]).count == 0
|
|
190
|
+
|
|
191
|
+
puts ""
|
|
192
|
+
puts "danger results:"
|
|
193
|
+
[:errors, :warnings, :messages].each do |current|
|
|
194
|
+
params = {}
|
|
195
|
+
params[:rows] = status[current].map { |item| [item] }
|
|
196
|
+
next unless params[:rows].count > 0
|
|
197
|
+
params[:title] = case current
|
|
198
|
+
when :errors
|
|
199
|
+
current.to_s.capitalize.red
|
|
200
|
+
when :warnings
|
|
201
|
+
current.to_s.capitalize.yellow
|
|
202
|
+
else
|
|
203
|
+
current.to_s.capitalize
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
puts ""
|
|
207
|
+
puts Terminal::Table.new(params)
|
|
208
|
+
puts ""
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
puts "Markdown: ".green if status[:markdowns].count > 0
|
|
212
|
+
status[:markdowns].each do |current_markdown|
|
|
213
|
+
puts current_markdown
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
end
|