danger 0.1.0 → 0.1.1
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/LICENSE +1 -1
- data/README.md +43 -23
- data/bin/danger +5 -0
- data/lib/assets/DangerfileTemplate +15 -0
- data/lib/danger.rb +17 -34
- data/lib/danger/available_values.rb +27 -0
- data/lib/danger/ci_source/buildkite.rb +22 -0
- data/lib/danger/ci_source/ci_source.rb +16 -0
- data/lib/danger/ci_source/circle.rb +11 -13
- data/lib/danger/ci_source/travis.rb +12 -11
- data/lib/danger/comment_generators/github.md.erb +32 -0
- data/lib/danger/{Dangerfile.rb → dangerfile.rb} +8 -19
- data/lib/danger/dangerfile_dsl.rb +34 -34
- data/lib/danger/environment_manager.rb +22 -11
- data/lib/danger/init.rb +25 -0
- data/lib/danger/request_sources/github.rb +71 -15
- data/lib/danger/runner.rb +35 -0
- data/lib/danger/scm_source/{git.rb → git_repo.rb} +6 -7
- data/lib/danger/standard_error.rb +4 -4
- data/lib/danger/version.rb +2 -1
- metadata +75 -21
- data/.gitignore +0 -44
- data/.rspec +0 -2
- data/.travis.yml +0 -4
- data/CHANGELOG.md +0 -7
- data/Gemfile +0 -6
- data/Rakefile +0 -6
- data/bin/console +0 -11
- data/bin/setup +0 -7
- data/danger.gemspec +0 -29
- data/example/Dangerfile +0 -2
- data/exe/danger +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c2df0507da13cc40eb7f1d93256d1c5da4363ee0
|
4
|
+
data.tar.gz: 89be5c58b12e017286d8d0dedafcd5adc80f05bf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 44a07b2b9aca7eac7d487576fc1efb3332e3e978120c49046428ae623e8b76c5ed965ec44b5482bb3b5024206301490933118537275723ba1acdc8d14fdc6690
|
7
|
+
data.tar.gz: 10c85b4daeb7feff0c22d8c3b39746aaa14963bba02788b9a83d310334670c857eb4a5d651801e74803b68c4d9c7a92b373fcaa8747d5844a4fcd7653ef259aa
|
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,23 @@
|
|
1
1
|
# Danger :no_entry_sign:
|
2
2
|
|
3
|
+
[](https://github.com/orta/danger/blob/master/LICENSE)
|
4
|
+
[](http://rubygems.org/gems/danger)
|
5
|
+
|
3
6
|
Formalize your Pull Request etiquette.
|
4
7
|
|
5
|
-
*Note:* Not ready for public usage yet.
|
8
|
+
*Note:* Not ready for public usage yet. Work in progress
|
9
|
+
|
10
|
+
-------
|
11
|
+
<p align="center">
|
12
|
+
<a href="#installation">Installation</a> •
|
13
|
+
<a href="#usage">Usage</a> •
|
14
|
+
<a href="#dsl">DSL</a> •
|
15
|
+
<a href="#constraints">Constraints</a> •
|
16
|
+
<a href="#advanced">Advanced</a> •
|
17
|
+
<a href="#contributing">Contributing</a>
|
18
|
+
</p>
|
19
|
+
|
20
|
+
-------
|
6
21
|
|
7
22
|
## Installation
|
8
23
|
|
@@ -12,31 +27,27 @@ Add this line to your application's [Gemfile](https://guides.cocoapods.org/using
|
|
12
27
|
gem 'danger'
|
13
28
|
```
|
14
29
|
|
30
|
+
and then run the following to set up `danger` for your repository
|
31
|
+
|
32
|
+
```
|
33
|
+
danger init
|
34
|
+
```
|
35
|
+
|
15
36
|
## Usage
|
16
37
|
|
17
38
|
In CI run `bundle exec danger`. This will look at your `Dangerfile` and provide some feedback based on that.
|
18
39
|
|
19
40
|
## DSL
|
20
41
|
|
21
|
-
|
42
|
+
| | Danger :no_entry_sign:
|
22
43
|
-------------: | ------------- | ----
|
23
44
|
:sparkles: | `lines_of_code` | The total amount of lines of code in the diff
|
24
|
-
:
|
45
|
+
:pencil2: | `files_modified` | The list of files modified
|
25
46
|
:ship: | `files_added` | The list of files added
|
26
|
-
:
|
27
|
-
:
|
28
|
-
:
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
You can access more detailed information by looking through:
|
33
|
-
|
34
|
-
Danger :no_entry_sign: | |
|
35
|
-
-------------: | ------------- | ----
|
36
|
-
| :sparkles: | `env.travis` | Details on the travis integration
|
37
|
-
| :tophat: |`env.circle` | Details on the circle integration
|
38
|
-
| :octocat: | `env.github.pr_json` | The full JSON for the pull request
|
39
|
-
| :ghost: | `env.git.diff` | The full [GitDiff](https://github.com/schacon/ruby-git/blob/master/lib/git/diff.rb) file for the diff.
|
47
|
+
:recycle: | `files_removed` | The list of files removed
|
48
|
+
:abc: | `pr_title` | The title of the PR
|
49
|
+
:book: | `pr_body` | The body of the PR
|
50
|
+
:busts_in_silhouette: | `pr_author` | The author who submitted the PR
|
40
51
|
|
41
52
|
You can then create a `Dangerfile` like the following:
|
42
53
|
|
@@ -52,6 +63,9 @@ end
|
|
52
63
|
if lines_of_code > 50 && pr_title.include? "📱" == false
|
53
64
|
fail("Needs testing on a Phone if change is non-trivial")
|
54
65
|
end
|
66
|
+
|
67
|
+
message("This pull request adds #{lines_of_code} new lines")
|
68
|
+
warn("Author @#{pr_author} is not a contributor") unless ["KrauseFx", "orta"].include?(pr_author)
|
55
69
|
```
|
56
70
|
|
57
71
|
## Constraints
|
@@ -59,14 +73,20 @@ end
|
|
59
73
|
* **GitHub** - Built with same-repo PRs in mind
|
60
74
|
* **Git** - Built with master as the merge branch
|
61
75
|
|
62
|
-
|
76
|
+
## Advanced
|
77
|
+
|
78
|
+
You can access more detailed information by accessing the following variables
|
63
79
|
|
64
|
-
|
80
|
+
| Danger :no_entry_sign:
|
81
|
+
------------- | ----
|
82
|
+
`env.request_source.pr_json` | The full JSON for the pull request
|
83
|
+
`env.scm.diff` | The full [GitDiff](https://github.com/schacon/ruby-git/blob/master/lib/git/diff.rb) file for the diff.
|
84
|
+
`env.ci_source` | To get information like the repo slug or pull request ID
|
65
85
|
|
66
|
-
|
86
|
+
## Special Thanks
|
67
87
|
|
68
|
-
|
88
|
+
Thanks [@orta](https://twitter.com/orta) for starting this project
|
69
89
|
|
70
|
-
##
|
90
|
+
## License
|
71
91
|
|
72
|
-
|
92
|
+
> This project is open source under the MIT license, which means you have full access to the source code and can modify it to fit your own needs.
|
data/bin/danger
ADDED
data/lib/danger.rb
CHANGED
@@ -1,43 +1,26 @@
|
|
1
1
|
require "danger/version"
|
2
2
|
require "danger/dangerfile"
|
3
3
|
require "danger/environment_manager"
|
4
|
+
require "danger/runner"
|
5
|
+
require "danger/init"
|
6
|
+
require "danger/available_values"
|
4
7
|
|
5
|
-
require
|
6
|
-
require
|
8
|
+
require "claide"
|
9
|
+
require "colored"
|
10
|
+
require "pathname"
|
7
11
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
self.command = 'danger'
|
13
|
-
|
14
|
-
def initialize(argv)
|
15
|
-
@dangerfile_path = "Dangerfile" if File.exist? "Dangerfile"
|
16
|
-
super
|
17
|
-
end
|
18
|
-
|
19
|
-
def validate!
|
20
|
-
super
|
21
|
-
unless @dangerfile_path
|
22
|
-
help! "Could not find a Dangerfile."
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def run
|
27
|
-
dm = Dangerfile.new
|
28
|
-
dm.env = EnvironmentManager.new(ENV)
|
29
|
-
dm.env.fill_environment_vars
|
30
|
-
dm.update_from_env
|
31
|
-
dm.env.git.diff_for_folder(".")
|
32
|
-
dm.parse Pathname.new(@dangerfile_path)
|
12
|
+
# Import all the Sources (CI, Request and SCM)
|
13
|
+
Dir[File.expand_path('danger/*source/*.rb', File.dirname(__FILE__))].each do |file|
|
14
|
+
require file
|
15
|
+
end
|
33
16
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
17
|
+
module Danger
|
18
|
+
# @return [String] The path to the local gem directory
|
19
|
+
def self.gem_path
|
20
|
+
gem_name = "danger"
|
21
|
+
unless Gem::Specification.find_all_by_name(gem_name).any?
|
22
|
+
raise "Couldn't find gem directory for 'danger'"
|
40
23
|
end
|
41
|
-
|
24
|
+
return Gem::Specification.find_by_name(gem_name).gem_dir
|
42
25
|
end
|
43
26
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Danger
|
2
|
+
# Defines all the values that should be available in someone's Dangerfile
|
3
|
+
class AvailableValues
|
4
|
+
def self.all
|
5
|
+
self.scm + self.request_source
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.scm
|
9
|
+
[
|
10
|
+
:lines_of_code,
|
11
|
+
:files_modified,
|
12
|
+
:files_removed,
|
13
|
+
:files_added,
|
14
|
+
:deletions,
|
15
|
+
:insertions
|
16
|
+
]
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.request_source
|
20
|
+
[
|
21
|
+
:pr_title,
|
22
|
+
:pr_body,
|
23
|
+
:pr_author
|
24
|
+
]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# https://buildkite.com/docs/agent/osx
|
2
|
+
# https://buildkite.com/docs/guides/environment-variables
|
3
|
+
|
4
|
+
module Danger
|
5
|
+
module CISource
|
6
|
+
class Buildkite < CI
|
7
|
+
def self.validates?(env)
|
8
|
+
return !env["BUILDKITE"].nil?
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(env)
|
12
|
+
repo = env["BUILDKITE_REPO"]
|
13
|
+
unless repo.nil?
|
14
|
+
repo_matches = repo.match(%r{([\/:])([^\/]+\/[^\/.]+)(?:.git)?$})
|
15
|
+
self.repo_slug = repo_matches[2] unless repo_matches.nil?
|
16
|
+
end
|
17
|
+
|
18
|
+
self.pull_request_id = env["BUILDKITE_PULL_REQUEST"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Danger
|
2
|
+
module CISource
|
3
|
+
# "abstract" CI class
|
4
|
+
class CI
|
5
|
+
attr_accessor :repo_slug, :pull_request_id
|
6
|
+
|
7
|
+
def self.validates?(_env)
|
8
|
+
false
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(_env)
|
12
|
+
raise "Subclass and overwrite initialize"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -2,20 +2,18 @@
|
|
2
2
|
require 'uri'
|
3
3
|
|
4
4
|
module Danger
|
5
|
-
|
5
|
+
module CISource
|
6
|
+
class CircleCI < CI
|
7
|
+
def self.validates?(env)
|
8
|
+
return !env["CIRCLE_BUILD_NUM"].nil? && !env["CI_PULL_REQUEST"].nil?
|
9
|
+
end
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(env)
|
14
|
-
paths = URI::parse(env["CI_PULL_REQUEST"]).path.split("/")
|
15
|
-
# the first one is an extra slash, ignore it
|
16
|
-
self.repo_slug = paths[1] + "/" + paths[2]
|
17
|
-
self.pull_request_id = paths[4]
|
11
|
+
def initialize(env)
|
12
|
+
paths = URI.parse(env["CI_PULL_REQUEST"]).path.split("/")
|
13
|
+
# the first one is an extra slash, ignore it
|
14
|
+
self.repo_slug = paths[1] + "/" + paths[2]
|
15
|
+
self.pull_request_id = paths[4]
|
16
|
+
end
|
18
17
|
end
|
19
|
-
|
20
18
|
end
|
21
19
|
end
|
@@ -2,18 +2,19 @@
|
|
2
2
|
# http://docs.travis-ci.com/user/environment-variables/
|
3
3
|
|
4
4
|
module Danger
|
5
|
-
|
5
|
+
module CISource
|
6
|
+
class Travis < CI
|
7
|
+
def self.validates?(env)
|
8
|
+
return !env["HAS_JOSH_K_SEAL_OF_APPROVAL"].nil?
|
9
|
+
end
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
self.repo_slug = env["TRAVIS_REPO_SLUG"]
|
15
|
-
self.pull_request_id = env["TRAVIS_PULL_REQUEST"]
|
11
|
+
def initialize(env)
|
12
|
+
self.repo_slug = env["TRAVIS_REPO_SLUG"]
|
13
|
+
# from https://docs.travis-ci.com/user/pull-requests, as otherwise it's "false"
|
14
|
+
if env["TRAVIS_PULL_REQUEST"].to_i > 0
|
15
|
+
self.pull_request_id = env["TRAVIS_PULL_REQUEST"]
|
16
|
+
end
|
17
|
+
end
|
16
18
|
end
|
17
|
-
|
18
19
|
end
|
19
20
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<% if @errors.count > 0 %>
|
2
|
+
| <%= @errors.count %> Error<%= "s" unless @errors.count == 1 %>
|
3
|
+
------------- | ------------ <% @errors.each do |error| %>
|
4
|
+
:no_entry_sign: | <%= error %><% end %>
|
5
|
+
<% else %>
|
6
|
+
:white_check_mark: | No errors found
|
7
|
+
------------- | ------------
|
8
|
+
<% end %>
|
9
|
+
|
10
|
+
<% if @warnings.count > 0 %>
|
11
|
+
| <%= @warnings.count %> Warning<%= "s" unless @warnings.count == 1 %>
|
12
|
+
------------- | ------------ <% @warnings.each do |warning| %>
|
13
|
+
:warning: | <%= warning %><% end %>
|
14
|
+
<% else %>
|
15
|
+
:white_check_mark: | No warnings found
|
16
|
+
------------- | ------------
|
17
|
+
<% end %>
|
18
|
+
|
19
|
+
<% if @messages.count > 0 %>
|
20
|
+
| <%= @messages.count %> Message<%= "s" unless @messages.count == 1 %>
|
21
|
+
------------- | ------------ <% @messages.each do |message| %>
|
22
|
+
:book: | <%= message %><% end %>
|
23
|
+
<% end %>
|
24
|
+
|
25
|
+
<p align="right">
|
26
|
+
Generated by
|
27
|
+
<a href="https://github.com/KrauseFx/danger">danger</a>
|
28
|
+
on
|
29
|
+
<i><%= Time.now.strftime("%Y-%m-%d") %></i>
|
30
|
+
</p>
|
31
|
+
|
32
|
+
<% "" # the reason why we have the each in the same line is because we don't want a new line in the markdown file %>
|
@@ -5,16 +5,12 @@ require 'danger/standard_error'
|
|
5
5
|
|
6
6
|
module Danger
|
7
7
|
class Dangerfile
|
8
|
-
|
9
8
|
include Danger::Dangerfile::DSL
|
10
9
|
|
11
|
-
|
12
|
-
# we make them readwrite in here
|
13
|
-
attr_accessor :files_modified, :files_removed, :files_added, :pr_title, :pr_body
|
14
|
-
attr_accessor :env, :warnings, :failures
|
10
|
+
attr_accessor :env, :warnings, :errors, :messages
|
15
11
|
|
16
12
|
# @return [Pathname] the path where the Dangerfile was loaded from. It is nil
|
17
|
-
# if the
|
13
|
+
# if the Dangerfile was generated programmatically.
|
18
14
|
#
|
19
15
|
attr_accessor :defined_in_file
|
20
16
|
|
@@ -28,9 +24,7 @@ module Danger
|
|
28
24
|
# Parses the file at a path, optionally takes the content of the file for DI
|
29
25
|
#
|
30
26
|
def parse(path, contents = nil)
|
31
|
-
|
32
|
-
|
33
|
-
contents ||= File.open(path, 'r:utf-8') { |f| f.read }
|
27
|
+
contents ||= File.open(path, 'r:utf-8', &:read)
|
34
28
|
|
35
29
|
# Work around for Rubinius incomplete encoding in 1.9 mode
|
36
30
|
if contents.respond_to?(:encoding) && contents.encoding.name != 'UTF-8'
|
@@ -39,12 +33,16 @@ module Danger
|
|
39
33
|
|
40
34
|
if contents.tr!('“”‘’‛', %(""'''))
|
41
35
|
# Changes have been made
|
42
|
-
puts
|
36
|
+
puts "Your #{path.basename} has had smart quotes sanitised. " \
|
43
37
|
'To avoid issues in the future, you should not use ' \
|
44
38
|
'TextEdit for editing it. If you are not using TextEdit, ' \
|
45
39
|
'you should turn off smart quotes in your editor of choice.'.red
|
46
40
|
end
|
47
41
|
|
42
|
+
if contents.include?("puts")
|
43
|
+
puts "You used `puts` in your Dangerfile. To print out text to GitHub use `message` instead"
|
44
|
+
end
|
45
|
+
|
48
46
|
self.defined_in_file = path
|
49
47
|
instance_eval do
|
50
48
|
# rubocop:disable Lint/RescueException
|
@@ -59,14 +57,5 @@ module Danger
|
|
59
57
|
# rubocop:enable Lint/RescueException
|
60
58
|
end
|
61
59
|
end
|
62
|
-
|
63
|
-
def update_from_env
|
64
|
-
self.files_modified = env.git.modified_files
|
65
|
-
self.files_removed = env.git.removed_files
|
66
|
-
self.files_added = env.git.added_files
|
67
|
-
self.pr_title = env.github.pr_title
|
68
|
-
self.pr_body = env.github.pr_body
|
69
|
-
end
|
70
|
-
|
71
60
|
end
|
72
61
|
end
|
@@ -1,51 +1,27 @@
|
|
1
1
|
module Danger
|
2
2
|
class Dangerfile
|
3
3
|
module DSL
|
4
|
-
|
5
|
-
public
|
6
|
-
|
7
4
|
# @!group Enviroment
|
8
|
-
# @return [EnvironmentManager] Provides access to the raw Travis/Circle/GitHub
|
5
|
+
# @return [EnvironmentManager] Provides access to the raw Travis/Circle/Buildkite/GitHub
|
9
6
|
# objects, which you can use to pull out extra bits of information. _Warning_
|
10
7
|
# the api of these objects is **not** considered a part of the Dangerfile public
|
11
8
|
# API, and is viable to change occasionally on the whims of developers.
|
12
9
|
|
13
10
|
attr_reader :env
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
# @return [Array of Strings] The list of files modified
|
21
|
-
#
|
22
|
-
attr_reader :files_modified
|
23
|
-
|
24
|
-
# @return [Array of Strings] The list of files removed
|
25
|
-
#
|
26
|
-
attr_reader :files_removed
|
27
|
-
|
28
|
-
# @return [Array of Strings] The list of files added
|
29
|
-
#
|
30
|
-
attr_reader :files_added
|
31
|
-
|
32
|
-
# @!group Pull Request Meta
|
33
|
-
# @return [String] The title of the PR
|
34
|
-
#
|
35
|
-
attr_reader :pr_title
|
36
|
-
|
37
|
-
# @return [String] The body of the PR
|
38
|
-
#
|
39
|
-
attr_reader :pr_body
|
40
|
-
|
12
|
+
def initialize
|
13
|
+
self.warnings = []
|
14
|
+
self.errors = []
|
15
|
+
self.messages = []
|
16
|
+
end
|
41
17
|
|
42
18
|
# Declares a CI blocking error
|
43
19
|
#
|
44
20
|
# @param [String] message
|
45
21
|
# The message to present to the user
|
46
22
|
def fail(message)
|
47
|
-
self.
|
48
|
-
puts "
|
23
|
+
self.errors << message
|
24
|
+
puts "Raising error '#{message}'"
|
49
25
|
end
|
50
26
|
|
51
27
|
# Specifies a problem, but not critical
|
@@ -53,10 +29,34 @@ module Danger
|
|
53
29
|
# @param [String] message
|
54
30
|
# The message to present to the user
|
55
31
|
def warn(message)
|
56
|
-
self.warnings <<
|
57
|
-
puts "
|
32
|
+
self.warnings << message
|
33
|
+
puts "Printing warning '#{message}'"
|
58
34
|
end
|
59
35
|
|
36
|
+
# Print out a generate message on the PR
|
37
|
+
#
|
38
|
+
# @param [String] message
|
39
|
+
# The message to present to the user
|
40
|
+
def message(message)
|
41
|
+
self.messages << message
|
42
|
+
puts "Printing message '#{message}'"
|
43
|
+
end
|
44
|
+
|
45
|
+
def method_missing(method_sym, *_arguments, &_block)
|
46
|
+
unless AvailableValues.all.include?(method_sym)
|
47
|
+
raise "Unknown method '#{method_sym}', please check out the documentation for available variables".red
|
48
|
+
end
|
49
|
+
|
50
|
+
if AvailableValues.scm.include?(method_sym)
|
51
|
+
# SCM Source
|
52
|
+
return env.scm.send(method_sym)
|
53
|
+
end
|
54
|
+
|
55
|
+
if AvailableValues.request_source.include?(method_sym)
|
56
|
+
# Request Source
|
57
|
+
return env.request_source.send(method_sym)
|
58
|
+
end
|
59
|
+
end
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
@@ -1,24 +1,35 @@
|
|
1
|
-
require "danger/ci_source/
|
2
|
-
require "danger/ci_source/circle"
|
1
|
+
require "danger/ci_source/ci_source"
|
3
2
|
require "danger/request_sources/github"
|
4
3
|
|
5
4
|
module Danger
|
6
5
|
class EnvironmentManager
|
7
|
-
|
8
|
-
attr_accessor :travis, :circle, :github, :git
|
6
|
+
attr_accessor :ci_source, :request_source, :scm
|
9
7
|
|
10
8
|
def initialize(env)
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
CISource.constants.each do |symb|
|
10
|
+
c = CISource.const_get(symb)
|
11
|
+
next unless c.kind_of?(Class)
|
12
|
+
next unless c.validates?(env)
|
13
|
+
|
14
|
+
self.ci_source = c.new(env)
|
15
|
+
if self.ci_source.repo_slug and self.ci_source.pull_request_id
|
16
|
+
break
|
17
|
+
else
|
18
|
+
puts "Not a Pull Request - skipping `danger` run"
|
19
|
+
self.ci_source = nil
|
20
|
+
return nil
|
21
|
+
end
|
22
|
+
end
|
14
23
|
|
15
|
-
|
24
|
+
raise "Could not find a CI source".red unless self.ci_source
|
25
|
+
|
26
|
+
self.request_source = GitHub.new(self.ci_source) # for now
|
16
27
|
end
|
17
28
|
|
18
29
|
def fill_environment_vars
|
19
|
-
|
20
|
-
|
21
|
-
self.
|
30
|
+
request_source.fetch_details
|
31
|
+
|
32
|
+
self.scm = GitRepo.new # For now
|
22
33
|
end
|
23
34
|
end
|
24
35
|
end
|
data/lib/danger/init.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Danger
|
2
|
+
class Init < Danger::Runner
|
3
|
+
self.description = 'Creates a Dangerfile.'
|
4
|
+
self.command = 'init'
|
5
|
+
|
6
|
+
def initialize(argv)
|
7
|
+
@dangerfile_path = "Dangerfile" if File.exist? "Dangerfile"
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate!
|
12
|
+
if @dangerfile_path
|
13
|
+
help! "Found an existing Dangerfile."
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
dir = Danger.gem_path
|
19
|
+
|
20
|
+
content = File.read(File.join(dir, "lib", "assets", "DangerfileTemplate"))
|
21
|
+
File.write("Dangerfile", content)
|
22
|
+
puts "Successfully created 'Dangerfile'"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,41 +1,97 @@
|
|
1
1
|
require 'rest'
|
2
2
|
require 'json'
|
3
|
+
require 'base64'
|
4
|
+
require 'octokit'
|
3
5
|
|
4
6
|
module Danger
|
5
7
|
class GitHub
|
6
|
-
|
7
8
|
attr_accessor :ci_source, :pr_json
|
8
9
|
|
9
10
|
def initialize(ci_source)
|
10
11
|
self.ci_source = ci_source
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
-
"
|
14
|
+
def client
|
15
|
+
token = ENV["DANGER_GITHUB_API_TOKEN"]
|
16
|
+
raise "No API given, please provide one using `DANGER_GITHUB_API_TOKEN`" unless token
|
17
|
+
|
18
|
+
@client ||= Octokit::Client.new(
|
19
|
+
access_token: token
|
20
|
+
)
|
15
21
|
end
|
16
22
|
|
17
|
-
def
|
18
|
-
|
19
|
-
if response.ok?
|
20
|
-
self.pr_json = JSON.parse(response.body)
|
21
|
-
else
|
22
|
-
puts "Something went wrong getting GitHub details for #{api_url} - (#{response.status_code})"
|
23
|
-
puts response.body
|
24
|
-
raise "Could not get the pull request details from GitHub."
|
25
|
-
end
|
23
|
+
def fetch_details
|
24
|
+
self.pr_json = client.pull_request(ci_source.repo_slug, ci_source.pull_request_id)
|
26
25
|
end
|
27
26
|
|
28
27
|
def latest_pr_commit_ref
|
29
|
-
self.pr_json[
|
28
|
+
self.pr_json[:head][:sha]
|
30
29
|
end
|
31
30
|
|
32
31
|
def pr_title
|
33
|
-
self.pr_json[
|
32
|
+
self.pr_json[:title]
|
34
33
|
end
|
35
34
|
|
36
35
|
def pr_body
|
37
|
-
self.pr_json[
|
36
|
+
self.pr_json[:body]
|
37
|
+
end
|
38
|
+
|
39
|
+
def pr_author
|
40
|
+
self.pr_json[:user][:login]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Sending data to GitHub
|
44
|
+
def update_pull_request!(warnings: nil, errors: nil, messages: nil)
|
45
|
+
# First, add a comment
|
46
|
+
body = generate_comment(warnings: warnings, errors: errors, messages: messages)
|
47
|
+
result = client.add_comment(ci_source.repo_slug, ci_source.pull_request_id, body)
|
48
|
+
delete_old_comment!(except: result[:id])
|
49
|
+
|
50
|
+
# Now, set the pull request status
|
51
|
+
submit_pull_request_status!(warnings: warnings,
|
52
|
+
errors: errors,
|
53
|
+
details_url: result['html_url'])
|
54
|
+
end
|
55
|
+
|
56
|
+
def submit_pull_request_status!(warnings: nil, errors: nil, details_url: nil)
|
57
|
+
status = (errors.count == 0 ? 'success' : 'failure')
|
58
|
+
client.create_status(ci_source.repo_slug, latest_pr_commit_ref, status, {
|
59
|
+
description: generate_github_description(warnings: warnings, errors: errors),
|
60
|
+
context: "KrauseFx/danger",
|
61
|
+
target_url: details_url
|
62
|
+
})
|
38
63
|
end
|
39
64
|
|
65
|
+
# Get rid of the previously posted comment, to only have the latest one
|
66
|
+
def delete_old_comment!(except: nil)
|
67
|
+
issues = client.issue_comments(ci_source.repo_slug, ci_source.pull_request_id)
|
68
|
+
issues.each do |issue|
|
69
|
+
next unless issue[:body].gsub(/\s+/, "").include?("Generatedby<ahref=")
|
70
|
+
next if issue[:id] == except
|
71
|
+
client.delete_comment(ci_source.repo_slug, issue[:id])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def generate_github_description(warnings: nil, errors: nil)
|
76
|
+
if errors.count > 0
|
77
|
+
"danger found errors"
|
78
|
+
elsif warnings.count > 0
|
79
|
+
"⚠️ danger found warnings, merge with caution"
|
80
|
+
else
|
81
|
+
"danger was successful"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def generate_comment(warnings: nil, errors: nil, messages: nil)
|
86
|
+
require 'erb'
|
87
|
+
|
88
|
+
@warnings = warnings
|
89
|
+
@errors = errors
|
90
|
+
@messages = messages
|
91
|
+
|
92
|
+
md_template = File.join(Danger.gem_path, "lib/danger/comment_generators/github.md.erb")
|
93
|
+
comment = ERB.new(File.read(md_template)).result(binding) # http://www.rrn.dk/rubys-erb-templating-system
|
94
|
+
return comment
|
95
|
+
end
|
40
96
|
end
|
41
97
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Danger
|
2
|
+
class Runner < CLAide::Command
|
3
|
+
self.description = 'Run the Dangerfile.'
|
4
|
+
self.command = 'danger'
|
5
|
+
|
6
|
+
def initialize(argv)
|
7
|
+
@dangerfile_path = "Dangerfile" if File.exist? "Dangerfile"
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate!
|
12
|
+
super
|
13
|
+
unless @dangerfile_path
|
14
|
+
help! "Could not find a Dangerfile."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
# The order of the following commands is *really* important
|
20
|
+
dm = Dangerfile.new
|
21
|
+
dm.env = EnvironmentManager.new(ENV)
|
22
|
+
return unless dm.env.ci_source # if it's not a PR
|
23
|
+
dm.env.fill_environment_vars
|
24
|
+
dm.env.scm.diff_for_folder(".")
|
25
|
+
dm.parse Pathname.new(@dangerfile_path)
|
26
|
+
|
27
|
+
post_results(dm)
|
28
|
+
end
|
29
|
+
|
30
|
+
def post_results(dm)
|
31
|
+
gh = dm.env.request_source
|
32
|
+
gh.update_pull_request!(warnings: dm.warnings, errors: dm.errors, messages: dm.messages)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -11,16 +11,16 @@ module Danger
|
|
11
11
|
self.diff = g.diff(to, from)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
@diff.to_a.map
|
14
|
+
def files_modified
|
15
|
+
@diff.to_a.map(&:path)
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
19
|
-
@diff.to_a.select { |d| d.type == "deleted" }
|
18
|
+
def files_removed
|
19
|
+
@diff.to_a.select { |d| d.type == "deleted" }.map(&:path)
|
20
20
|
end
|
21
21
|
|
22
|
-
def
|
23
|
-
@diff.to_a.select { |d| d.type == "new" }
|
22
|
+
def files_added
|
23
|
+
@diff.to_a.select { |d| d.type == "new" }.map(&:path)
|
24
24
|
end
|
25
25
|
|
26
26
|
def lines_of_code
|
@@ -34,6 +34,5 @@ module Danger
|
|
34
34
|
def insertions
|
35
35
|
@diff.insertions
|
36
36
|
end
|
37
|
-
|
38
37
|
end
|
39
38
|
end
|
@@ -78,16 +78,16 @@ module Danger
|
|
78
78
|
|
79
79
|
lines = contents.lines
|
80
80
|
indent = ' # '
|
81
|
-
indicator = indent.
|
81
|
+
indicator = indent.tr('#', '>')
|
82
82
|
first_line = (line_numer.zero?)
|
83
83
|
last_line = (line_numer == (lines.count - 1))
|
84
84
|
|
85
85
|
m << "\n"
|
86
86
|
m << "#{indent}from #{trace_line.gsub(/:in.*$/, '')}\n"
|
87
87
|
m << "#{indent}-------------------------------------------\n"
|
88
|
-
m << "#{indent}#{
|
89
|
-
m << "#{indicator}#{
|
90
|
-
m << "#{indent}#{
|
88
|
+
m << "#{indent}#{lines[line_numer - 1]}" unless first_line
|
89
|
+
m << "#{indicator}#{lines[line_numer]}"
|
90
|
+
m << "#{indent}#{lines[line_numer + 1]}" unless last_line
|
91
91
|
m << "\n" unless m.end_with?("\n")
|
92
92
|
m << "#{indent}-------------------------------------------\n"
|
93
93
|
end
|
data/lib/danger/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: danger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Orta Therox
|
8
8
|
- Felix Krause
|
9
9
|
autorequire:
|
10
|
-
bindir:
|
10
|
+
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-01-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: claide
|
@@ -67,6 +67,20 @@ dependencies:
|
|
67
67
|
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: octokit
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
70
84
|
- !ruby/object:Gem::Dependency
|
71
85
|
name: bundler
|
72
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,41 +123,81 @@ dependencies:
|
|
109
123
|
- - ">="
|
110
124
|
- !ruby/object:Gem::Version
|
111
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: webmock
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - ">="
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '0'
|
140
|
+
- !ruby/object:Gem::Dependency
|
141
|
+
name: fastlane
|
142
|
+
requirement: !ruby/object:Gem::Requirement
|
143
|
+
requirements:
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 1.49.0
|
147
|
+
type: :development
|
148
|
+
prerelease: false
|
149
|
+
version_requirements: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - ">="
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 1.49.0
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: rubocop
|
156
|
+
requirement: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
type: :development
|
162
|
+
prerelease: false
|
163
|
+
version_requirements: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ">="
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
112
168
|
description: Create a Dangerfile to introspect your pull request in CI, makes it easy
|
113
169
|
to enforce social conventions like changelogs and tests.
|
114
170
|
email:
|
115
171
|
- orta.therox@gmail.com
|
116
|
-
-
|
172
|
+
- danger@krausefx.com
|
117
173
|
executables:
|
118
174
|
- danger
|
119
175
|
extensions: []
|
120
176
|
extra_rdoc_files: []
|
121
177
|
files:
|
122
|
-
- ".gitignore"
|
123
|
-
- ".rspec"
|
124
|
-
- ".travis.yml"
|
125
|
-
- CHANGELOG.md
|
126
|
-
- Gemfile
|
127
178
|
- LICENSE
|
128
179
|
- README.md
|
129
|
-
-
|
130
|
-
-
|
131
|
-
- bin/setup
|
132
|
-
- danger.gemspec
|
133
|
-
- example/Dangerfile
|
134
|
-
- exe/danger
|
180
|
+
- bin/danger
|
181
|
+
- lib/assets/DangerfileTemplate
|
135
182
|
- lib/danger.rb
|
136
|
-
- lib/danger/
|
183
|
+
- lib/danger/available_values.rb
|
184
|
+
- lib/danger/ci_source/buildkite.rb
|
185
|
+
- lib/danger/ci_source/ci_source.rb
|
137
186
|
- lib/danger/ci_source/circle.rb
|
138
187
|
- lib/danger/ci_source/travis.rb
|
188
|
+
- lib/danger/comment_generators/github.md.erb
|
189
|
+
- lib/danger/dangerfile.rb
|
139
190
|
- lib/danger/dangerfile_dsl.rb
|
140
191
|
- lib/danger/environment_manager.rb
|
192
|
+
- lib/danger/init.rb
|
141
193
|
- lib/danger/request_sources/github.rb
|
142
|
-
- lib/danger/
|
194
|
+
- lib/danger/runner.rb
|
195
|
+
- lib/danger/scm_source/git_repo.rb
|
143
196
|
- lib/danger/standard_error.rb
|
144
197
|
- lib/danger/version.rb
|
145
198
|
homepage: http://github.com/orta/danger
|
146
|
-
licenses:
|
199
|
+
licenses:
|
200
|
+
- MIT
|
147
201
|
metadata: {}
|
148
202
|
post_install_message:
|
149
203
|
rdoc_options: []
|
@@ -153,7 +207,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
207
|
requirements:
|
154
208
|
- - ">="
|
155
209
|
- !ruby/object:Gem::Version
|
156
|
-
version:
|
210
|
+
version: 2.0.0
|
157
211
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
212
|
requirements:
|
159
213
|
- - ">="
|
@@ -161,8 +215,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
215
|
version: '0'
|
162
216
|
requirements: []
|
163
217
|
rubyforge_project:
|
164
|
-
rubygems_version: 2.4.
|
218
|
+
rubygems_version: 2.4.6
|
165
219
|
signing_key:
|
166
220
|
specification_version: 4
|
167
|
-
summary: Ensure your pull request is up to standard with a nice DSL
|
221
|
+
summary: Ensure your pull request is up to standard with a nice DSL
|
168
222
|
test_files: []
|
data/.gitignore
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
/.bundle/
|
2
|
-
/.yardoc
|
3
|
-
/Gemfile.lock
|
4
|
-
/_yardoc/
|
5
|
-
/coverage/
|
6
|
-
/doc/
|
7
|
-
/pkg/
|
8
|
-
/spec/reports/
|
9
|
-
/tmp/
|
10
|
-
*.gem
|
11
|
-
*.rbc
|
12
|
-
/.config
|
13
|
-
/coverage/
|
14
|
-
/InstalledFiles
|
15
|
-
/pkg/
|
16
|
-
/spec/reports/
|
17
|
-
/test/tmp/
|
18
|
-
/test/version_tmp/
|
19
|
-
/tmp/
|
20
|
-
|
21
|
-
## Specific to RubyMotion:
|
22
|
-
.dat*
|
23
|
-
.repl_history
|
24
|
-
build/
|
25
|
-
|
26
|
-
## Documentation cache and generated files:
|
27
|
-
/.yardoc/
|
28
|
-
/_yardoc/
|
29
|
-
/doc/
|
30
|
-
/rdoc/
|
31
|
-
|
32
|
-
## Environment normalisation:
|
33
|
-
/.bundle/
|
34
|
-
/vendor/bundle
|
35
|
-
/lib/bundler/man/
|
36
|
-
|
37
|
-
# for a library or gem, you might want to ignore these files since the code is
|
38
|
-
# intended to run in multiple environments; otherwise, check them in:
|
39
|
-
# Gemfile.lock
|
40
|
-
# .ruby-version
|
41
|
-
# .ruby-gemset
|
42
|
-
|
43
|
-
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
|
44
|
-
.rvmrc
|
data/.rspec
DELETED
data/.travis.yml
DELETED
data/CHANGELOG.md
DELETED
data/Gemfile
DELETED
data/Rakefile
DELETED
data/bin/console
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
require "bundler/setup"
|
4
|
-
require "danger"
|
5
|
-
|
6
|
-
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
-
# with your gem easier. You can also use a different console, if you like.
|
8
|
-
|
9
|
-
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
-
require "pry"
|
11
|
-
Pry.start
|
data/bin/setup
DELETED
data/danger.gemspec
DELETED
@@ -1,29 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
lib = File.expand_path('../lib', __FILE__)
|
3
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require 'danger/version'
|
5
|
-
|
6
|
-
Gem::Specification.new do |spec|
|
7
|
-
spec.name = "danger"
|
8
|
-
spec.version = Danger::VERSION
|
9
|
-
spec.authors = ["Orta Therox", "Felix Krause"]
|
10
|
-
spec.email = ["orta.therox@gmail.com", "fastlane@krausefx.com"]
|
11
|
-
|
12
|
-
spec.summary = 'Ensure your pull request is up to standard with a nice DSL.'
|
13
|
-
spec.description = 'Create a Dangerfile to introspect your pull request in CI, makes it easy to enforce social conventions like changelogs and tests.'
|
14
|
-
spec.homepage = "http://github.com/orta/danger"
|
15
|
-
|
16
|
-
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
-
spec.bindir = "exe"
|
18
|
-
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
-
spec.require_paths = ["lib"]
|
20
|
-
|
21
|
-
spec.add_runtime_dependency 'claide', "~> 0.8"
|
22
|
-
spec.add_runtime_dependency 'git', "~> 1.2.9"
|
23
|
-
spec.add_runtime_dependency 'colored'
|
24
|
-
spec.add_runtime_dependency 'nap'
|
25
|
-
|
26
|
-
spec.add_development_dependency "bundler", "~> 1.10"
|
27
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
-
spec.add_development_dependency "rspec"
|
29
|
-
end
|
data/example/Dangerfile
DELETED