danger 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/orta/danger/blob/master/LICENSE)
|
4
|
+
[![Gem](https://img.shields.io/gem/v/danger.svg?style=flat)](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