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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e9d3bed0d3e1f30e4a29d4eef41445ccd9f5b00d
4
- data.tar.gz: eaf83e5b95373942ac5f56ecaa1cd7bfdb25cd5a
3
+ metadata.gz: c2df0507da13cc40eb7f1d93256d1c5da4363ee0
4
+ data.tar.gz: 89be5c58b12e017286d8d0dedafcd5adc80f05bf
5
5
  SHA512:
6
- metadata.gz: 340a33da5826421c3e7ddcfe7b8d7f8f23ac12260da1d81933e672df55987a1b341d23f9fcfe373c1177e541a8b45e194c74df7ffeeae7fc382dd6ee8baf12ea
7
- data.tar.gz: 8e5f6adafea5d67c8b1799123ff02cfb0752dbfc4d1113efec734c2c79dace8bab00f8c68848e2ab441f44b8a7b46125bbac15277b7acf1a8e851532c506ce8b
6
+ metadata.gz: 44a07b2b9aca7eac7d487576fc1efb3332e3e978120c49046428ae623e8b76c5ed965ec44b5482bb3b5024206301490933118537275723ba1acdc8d14fdc6690
7
+ data.tar.gz: 10c85b4daeb7feff0c22d8c3b39746aaa14963bba02788b9a83d310334670c857eb4a5d651801e74803b68c4d9c7a92b373fcaa8747d5844a4fcd7653ef259aa
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2015 Orta
3
+ Copyright (c) 2015 Orta, Felix Krause
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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. Still needs work to ensure Travis/CircleCI hook up correctly.
8
+ *Note:* Not ready for public usage yet. Work in progress
9
+
10
+ -------
11
+ <p align="center">
12
+ <a href="#installation">Installation</a> &bull;
13
+ <a href="#usage">Usage</a> &bull;
14
+ <a href="#dsl">DSL</a> &bull;
15
+ <a href="#constraints">Constraints</a> &bull;
16
+ <a href="#advanced">Advanced</a> &bull;
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
- Danger :no_entry_sign: | &nbsp; | &nbsp;
42
+ &nbsp; | &nbsp; | Danger :no_entry_sign:
22
43
  -------------: | ------------- | ----
23
44
  :sparkles: | `lines_of_code` | The total amount of lines of code in the diff
24
- :monorail: | `files_modified` | The list of files modified
45
+ :pencil2: | `files_modified` | The list of files modified
25
46
  :ship: | `files_added` | The list of files added
26
- :pencil2: | `files_removed` | The list of files removed
27
- :wrench: | `pr_title` | The title of the PR
28
- :thought_balloon: | `pr_body` | The body of the PR
29
-
30
-
31
-
32
- You can access more detailed information by looking through:
33
-
34
- Danger :no_entry_sign: | &nbsp; | &nbsp;
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
- PRs welcome on these
76
+ ## Advanced
77
+
78
+ You can access more detailed information by accessing the following variables
63
79
 
64
- ## Development
80
+ &nbsp; | 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
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
86
+ ## Special Thanks
67
87
 
68
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
88
+ Thanks [@orta](https://twitter.com/orta) for starting this project
69
89
 
70
- ## Contributing
90
+ ## License
71
91
 
72
- Bug reports and pull requests are welcome on GitHub at https://github.com/orta/danger.
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.
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.push File.expand_path("../../lib", __FILE__)
3
+
4
+ require 'danger'
5
+ Danger::Runner.run ARGV
@@ -0,0 +1,15 @@
1
+ puts "OK"
2
+ puts "Lines"
3
+ puts lines_of_code
4
+ puts "Added"
5
+ puts files_added
6
+ puts "modified"
7
+ puts files_modified
8
+
9
+ puts ""
10
+ puts pr_body
11
+ puts ""
12
+ puts pr_title
13
+
14
+ warn("Some random warning")
15
+ fail("Orta is not really orta")
@@ -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 'claide'
6
- require 'colored'
8
+ require "claide"
9
+ require "colored"
10
+ require "pathname"
7
11
 
8
- module Danger
9
- class DangerRunner < CLAide::Command
10
-
11
- self.description = 'Run the Dangerfile.'
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
- if dm.failures
35
- puts "Uh Oh failed"
36
- exit(1)
37
- else
38
- puts "The Danger has passed. Phew."
39
- end
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
- class CircleCI
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
- attr_accessor :repo_slug, :pull_request_id
8
-
9
- def self.validates?(env)
10
- return env["CIRCLE_BUILD_NUM"] != nil && ["CI_PULL_REQUEST"] != nil
11
- end
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
- class Travis
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
- attr_accessor :repo_slug, :pull_request_id
8
-
9
- def self.validates?(env)
10
- return env["HAS_JOSH_K_SEAL_OF_APPROVAL"] != nil
11
- end
12
-
13
- def initialize(env)
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
+ &nbsp; | <%= @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
+ &nbsp; | <%= @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
+ &nbsp; | <%= @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
- # The DSL includes a bunch of read only attributes + docs
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 podfile was generated programmatically.
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
- warnings = [], failures =[]
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 "Your #{path.basename} has had smart quotes sanitised. " \
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
- # @!group Code
16
- # @return [Number] The total amount of lines of code in the diff
17
- #
18
- attr_reader :lines_of_code
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.failures << message
48
- puts "fail #{fail}"
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 << "message"
57
- puts "warn #{fail}"
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/travis"
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
- self.travis = Travis.new(env) if Travis.validates?(env)
12
- self.circle = CircleCI.new(env) if CircleCI.validates?(env)
13
- raise "Could not find a CI source" unless self.travis || self.circle
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
- self.github = GitHub.new( travis || circle)
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
- github.get_details
20
-
21
- self.git = GitRepo.new
30
+ request_source.fetch_details
31
+
32
+ self.scm = GitRepo.new # For now
22
33
  end
23
34
  end
24
35
  end
@@ -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 api_url
14
- "https://api.github.com/repos/#{ci_source.repo_slug}/pulls/#{ci_source.pull_request_id}"
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 get_details
18
- response = REST.get api_url
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['base']['sha']
28
+ self.pr_json[:head][:sha]
30
29
  end
31
30
 
32
31
  def pr_title
33
- self.pr_json['title']
32
+ self.pr_json[:title]
34
33
  end
35
34
 
36
35
  def pr_body
37
- self.pr_json['body']
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 modified_files
15
- @diff.to_a.map { |d| d.path }
14
+ def files_modified
15
+ @diff.to_a.map(&:path)
16
16
  end
17
17
 
18
- def removed_files
19
- @diff.to_a.select { |d| d.type == "deleted" } .map { |d| d.path }
18
+ def files_removed
19
+ @diff.to_a.select { |d| d.type == "deleted" }.map(&:path)
20
20
  end
21
21
 
22
- def added_files
23
- @diff.to_a.select { |d| d.type == "new" } .map { |d| d.path }
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.gsub('#', '>')
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}#{ lines[line_numer - 1] }" unless first_line
89
- m << "#{indicator}#{ lines[line_numer] }"
90
- m << "#{indent}#{ lines[line_numer + 1] }" unless last_line
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
@@ -1,3 +1,4 @@
1
1
  module Danger
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
+ DESCRIPTION = "Ensure your pull request is up to standard with a nice DSL"
3
4
  end
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.0
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: exe
10
+ bindir: bin
11
11
  cert_chain: []
12
- date: 2015-09-29 00:00:00.000000000 Z
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
- - fastlane@krausefx.com
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
- - Rakefile
130
- - bin/console
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/Dangerfile.rb
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/scm_source/git.rb
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: '0'
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.8
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
@@ -1,2 +0,0 @@
1
- --format documentation
2
- --color
@@ -1,4 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.1.3
4
- before_install: gem install bundler -v 1.10.6
@@ -1,7 +0,0 @@
1
- ## 0.1
2
-
3
- * Parses a `Dangerfile` - orta
4
- * Gets GitHub details from Travis & CircleCI - orta
5
- * Gets PR details from GitHub - orta
6
- * Gets Git details from local Git - orta
7
- * Fails when you say it's failed in the Dangerfile - orta
data/Gemfile DELETED
@@ -1,6 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- # Specify your gem's dependencies in danger.gemspec
4
- gemspec
5
-
6
- gem "pry"
data/Rakefile DELETED
@@ -1,6 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec)
5
-
6
- task :default => :spec
@@ -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
@@ -1,7 +0,0 @@
1
- #!/bin/bash
2
- set -euo pipefail
3
- IFS=$'\n\t'
4
-
5
- bundle install
6
-
7
- # Do any other automated setup that you need to do here
@@ -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
@@ -1,2 +0,0 @@
1
- puts "Hi"
2
- puts lines_of_code
data/exe/danger DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
4
- $LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
5
-
6
- require 'danger'
7
- Danger::DangerRunner.run ARGV