danger 0.8.1 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/README.md +17 -3
 - data/lib/danger/ci_source/buildkite.rb +13 -7
 - data/lib/danger/ci_source/ci_source.rb +18 -1
 - data/lib/danger/ci_source/circle.rb +11 -3
 - data/lib/danger/ci_source/drone.rb +11 -4
 - data/lib/danger/ci_source/jenkins.rb +12 -10
 - data/lib/danger/ci_source/local_git_repo.rb +4 -0
 - data/lib/danger/ci_source/semaphore.rb +11 -4
 - data/lib/danger/ci_source/teamcity.rb +22 -0
 - data/lib/danger/ci_source/travis.rb +10 -2
 - data/lib/danger/ci_source/xcode_server.rb +8 -1
 - data/lib/danger/commands/runner.rb +18 -4
 - data/lib/danger/comment_generators/github.md.erb +16 -17
 - data/lib/danger/danger_core/dangerfile.rb +1 -1
 - data/lib/danger/danger_core/environment_manager.rb +22 -29
 - data/lib/danger/danger_core/plugins/dangerfile_github_plugin.rb +1 -1
 - data/lib/danger/plugin_support/plugin.rb +10 -9
 - data/lib/danger/request_source/github.rb +180 -156
 - data/lib/danger/request_source/request_source.rb +48 -0
 - data/lib/danger/scm_source/git_repo.rb +4 -0
 - data/lib/danger/version.rb +1 -1
 - metadata +4 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 961961730193f38ada39854b1e3b14a665534539
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 161dfd213ef838bf04dc47c95cd3a59d5e745cc7
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 9c298a712a18d76022aba76603f6946f03ef5999a2203c06c4cc34013e2131d9657fa3ad2972b0bbf9c406f9d6922f5d2677160068482aaf0fbd3572444a31df
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: b657e664d71d270a6118bfe68033f039ac2604f969d9494b2e16631e4a9b65448b7e8de1842909e628da7a97aae65ba72939b7b9dc3e2783d8bd33ec62946056
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -43,7 +43,7 @@ This will look at your `Dangerfile` and update the pull request accordingly. Whi 
     | 
|
| 
       43 
43 
     | 
    
         | 
| 
       44 
44 
     | 
    
         
             
            ## CI Support
         
     | 
| 
       45 
45 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
            Danger currently is supported on Travis CI, Circle CI, Xcode Bots via Buildasaur, BuildKite, Jenkins, Semaphore,  
     | 
| 
      
 46 
     | 
    
         
            +
            Danger currently is supported on Travis CI, Circle CI, Xcode Bots via Buildasaur, BuildKite, Jenkins, Semaphore, Drone CI and TeamCity. These work via environment variables, so it's easy to extend to include your own.
         
     | 
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
            ## What happens?
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
         @@ -62,7 +62,7 @@ Danger runs at the end of a CI build, she will execute a `Dangerfile`. This file 
     | 
|
| 
       62 
62 
     | 
    
         
             
            :busts_in_silhouette:  | `pr_author` | The author who submitted the PR
         
     | 
| 
       63 
63 
     | 
    
         
             
            :bookmark: | `pr_labels` | The labels added to the PR
         
     | 
| 
       64 
64 
     | 
    
         | 
| 
       65 
     | 
    
         
            -
            The `Dangerfile` is a  
     | 
| 
      
 65 
     | 
    
         
            +
            The `Dangerfile` is a Ruby file, so really, you can do anything. However, at this stage you might need selling on the idea a bit more, so lets take some real examples:
         
     | 
| 
       66 
66 
     | 
    
         | 
| 
       67 
67 
     | 
    
         
             
            #### Dealing with WIP pull requests
         
     | 
| 
       68 
68 
     | 
    
         | 
| 
         @@ -192,6 +192,20 @@ Danger will update the comment to cross it out. If you don't want this behavior, 
     | 
|
| 
       192 
192 
     | 
    
         
             
            fail("PR needs labels", sticky: false) if pr_labels.empty?
         
     | 
| 
       193 
193 
     | 
    
         
             
            ```
         
     | 
| 
       194 
194 
     | 
    
         | 
| 
      
 195 
     | 
    
         
            +
            ## Multiple Dangers
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
            If one Danger is not enough for you, you can run several ones on the same PR. Just use the `danger_id` param. For example: 
         
     | 
| 
      
 198 
     | 
    
         
            +
             
     | 
| 
      
 199 
     | 
    
         
            +
            ```
         
     | 
| 
      
 200 
     | 
    
         
            +
            bundle exec danger --danger_id=unit_tests
         
     | 
| 
      
 201 
     | 
    
         
            +
            ```
         
     | 
| 
      
 202 
     | 
    
         
            +
             
     | 
| 
      
 203 
     | 
    
         
            +
            You can have each instance of Danger running on a different CI provider and even doing different validations. An use case would be:
         
     | 
| 
      
 204 
     | 
    
         
            +
             
     | 
| 
      
 205 
     | 
    
         
            +
            * `basic` runs on a Linux environment (such as Circle CI) and validates the PR itself (title, etc)
         
     | 
| 
      
 206 
     | 
    
         
            +
            * `compilation` runs on a Mac after running unit tests for your iOS app and comments about warnings, test failures, etc
         
     | 
| 
      
 207 
     | 
    
         
            +
            * `uitests` runs on a Mac after running UI Unit tests and comments about test failures
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
       195 
209 
     | 
    
         
             
            ## Useful bits of knowledge
         
     | 
| 
       196 
210 
     | 
    
         | 
| 
       197 
211 
     | 
    
         
             
            * You can set the base branch in the command line arguments see: `bundle exec danger --help`, if you commonly merge into non-master branches.
         
     | 
| 
         @@ -206,7 +220,7 @@ Danger allows usage with GitHub Enterprise by setting 2 environment variables: 
     | 
|
| 
       206 
220 
     | 
    
         | 
| 
       207 
221 
     | 
    
         
             
            ## License, Contributor's Guidelines and Code of Conduct
         
     | 
| 
       208 
222 
     | 
    
         | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
      
 223 
     | 
    
         
            +
            We try to keep as much discussion as possible in GitHub issues, but also have a slack, if you'd like an invite ping [@Orta](https://twitter.com/orta/) a DM on twitter with your email. 
         
     | 
| 
       210 
224 
     | 
    
         | 
| 
       211 
225 
     | 
    
         
             
            > 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.
         
     | 
| 
       212 
226 
     | 
    
         | 
| 
         @@ -5,17 +5,23 @@ module Danger 
     | 
|
| 
       5 
5 
     | 
    
         
             
              module CISource
         
     | 
| 
       6 
6 
     | 
    
         
             
                class Buildkite < CI
         
     | 
| 
       7 
7 
     | 
    
         
             
                  def self.validates?(env)
         
     | 
| 
       8 
     | 
    
         
            -
                    return  
     | 
| 
      
 8 
     | 
    
         
            +
                    return false unless env["BUILDKITE"]
         
     | 
| 
      
 9 
     | 
    
         
            +
                    return false unless env["BUILDKITE_REPO"]
         
     | 
| 
      
 10 
     | 
    
         
            +
                    return false unless env["BUILDKITE_PULL_REQUEST"]
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    return true
         
     | 
| 
       9 
13 
     | 
    
         
             
                  end
         
     | 
| 
       10 
14 
     | 
    
         | 
| 
       11 
15 
     | 
    
         
             
                  def initialize(env)
         
     | 
| 
       12 
     | 
    
         
            -
                     
     | 
| 
       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 
     | 
    
         
            -
             
     | 
| 
      
 16 
     | 
    
         
            +
                    self.repo_url = env["BUILDKITE_REPO"]
         
     | 
| 
       18 
17 
     | 
    
         
             
                    self.pull_request_id = env["BUILDKITE_PULL_REQUEST"]
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    repo_matches = self.repo_url.match(%r{([\/:])([^\/]+\/[^\/.]+)(?:.git)?$})
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.repo_slug = repo_matches[2] unless repo_matches.nil?
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
       19 
25 
     | 
    
         
             
                  end
         
     | 
| 
       20 
26 
     | 
    
         
             
                end
         
     | 
| 
       21 
27 
     | 
    
         
             
              end
         
     | 
| 
         @@ -2,7 +2,24 @@ module Danger 
     | 
|
| 
       2 
2 
     | 
    
         
             
              module CISource
         
     | 
| 
       3 
3 
     | 
    
         
             
                # "abstract" CI class
         
     | 
| 
       4 
4 
     | 
    
         
             
                class CI
         
     | 
| 
       5 
     | 
    
         
            -
                  attr_accessor :repo_slug, :pull_request_id
         
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_accessor :repo_slug, :pull_request_id, :repo_url, :supported_request_sources
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def self.inherited(child_class)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    available_ci_sources.add child_class
         
     | 
| 
      
 9 
     | 
    
         
            +
                    super
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def self.available_ci_sources
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @available_ci_sources ||= Set.new
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 17 
     | 
    
         
            +
                    raise "CISource subclass must specify the supported request sources"
         
     | 
| 
      
 18 
     | 
    
         
            +
                  end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  def supports?(request_source)
         
     | 
| 
      
 21 
     | 
    
         
            +
                    supported_request_sources.include? request_source
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
       6 
23 
     | 
    
         | 
| 
       7 
24 
     | 
    
         
             
                  def self.validates?(_env)
         
     | 
| 
       8 
25 
     | 
    
         
             
                    false
         
     | 
| 
         @@ -6,10 +6,16 @@ module Danger 
     | 
|
| 
       6 
6 
     | 
    
         
             
              module CISource
         
     | 
| 
       7 
7 
     | 
    
         
             
                class CircleCI < CI
         
     | 
| 
       8 
8 
     | 
    
         
             
                  def self.validates?(env)
         
     | 
| 
       9 
     | 
    
         
            -
                    return false  
     | 
| 
       10 
     | 
    
         
            -
                    return  
     | 
| 
      
 9 
     | 
    
         
            +
                    return false unless env["CIRCLE_BUILD_NUM"]
         
     | 
| 
      
 10 
     | 
    
         
            +
                    return false unless env["CI_PULL_REQUEST"]
         
     | 
| 
      
 11 
     | 
    
         
            +
                    return false unless env["CIRCLE_PROJECT_USERNAME"]
         
     | 
| 
      
 12 
     | 
    
         
            +
                    return false unless env["CIRCLE_PROJECT_REPONAME"]
         
     | 
| 
       11 
13 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                    return  
     | 
| 
      
 14 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 15 
     | 
    
         
            +
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
       13 
19 
     | 
    
         
             
                  end
         
     | 
| 
       14 
20 
     | 
    
         | 
| 
       15 
21 
     | 
    
         
             
                  def client
         
     | 
| 
         @@ -33,6 +39,8 @@ module Danger 
     | 
|
| 
       33 
39 
     | 
    
         
             
                  end
         
     | 
| 
       34 
40 
     | 
    
         | 
| 
       35 
41 
     | 
    
         
             
                  def initialize(env)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    self.repo_url = GitRepo.new.origins # CircleCI doesn't provide a repo url env variable :/
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
       36 
44 
     | 
    
         
             
                    @circle_token = env["CIRCLE_CI_API_TOKEN"]
         
     | 
| 
       37 
45 
     | 
    
         
             
                    url = pull_request_url(env)
         
     | 
| 
       38 
46 
     | 
    
         | 
| 
         @@ -4,14 +4,21 @@ module Danger 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module CISource
         
     | 
| 
       5 
5 
     | 
    
         
             
                class Drone < CI
         
     | 
| 
       6 
6 
     | 
    
         
             
                  def self.validates?(env)
         
     | 
| 
       7 
     | 
    
         
            -
                    return  
     | 
| 
      
 7 
     | 
    
         
            +
                    return false unless env["DRONE"]
         
     | 
| 
      
 8 
     | 
    
         
            +
                    return false unless env["DRONE_REPO"]
         
     | 
| 
      
 9 
     | 
    
         
            +
                    return false unless env["DRONE_PULL_REQUEST"].to_i > 0
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
       8 
16 
     | 
    
         
             
                  end
         
     | 
| 
       9 
17 
     | 
    
         | 
| 
       10 
18 
     | 
    
         
             
                  def initialize(env)
         
     | 
| 
       11 
19 
     | 
    
         
             
                    self.repo_slug = env["DRONE_REPO"]
         
     | 
| 
       12 
     | 
    
         
            -
                     
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.pull_request_id = env["DRONE_PULL_REQUEST"]
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.repo_url = GitRepo.new.origins # Drone doesn't provide a repo url env variable :/
         
     | 
| 
       15 
22 
     | 
    
         
             
                  end
         
     | 
| 
       16 
23 
     | 
    
         
             
                end
         
     | 
| 
       17 
24 
     | 
    
         
             
              end
         
     | 
| 
         @@ -5,20 +5,22 @@ module Danger 
     | 
|
| 
       5 
5 
     | 
    
         
             
              module CISource
         
     | 
| 
       6 
6 
     | 
    
         
             
                class Jenkins < CI
         
     | 
| 
       7 
7 
     | 
    
         
             
                  def self.validates?(env)
         
     | 
| 
       8 
     | 
    
         
            -
                    return  
     | 
| 
      
 8 
     | 
    
         
            +
                    return false unless env["ghprbPullId"].to_i > 0
         
     | 
| 
      
 9 
     | 
    
         
            +
                    return false unless env["GIT_URL"]
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
       9 
16 
     | 
    
         
             
                  end
         
     | 
| 
       10 
17 
     | 
    
         | 
| 
       11 
18 
     | 
    
         
             
                  def initialize(env)
         
     | 
| 
       12 
     | 
    
         
            -
                     
     | 
| 
       13 
     | 
    
         
            -
                     
     | 
| 
       14 
     | 
    
         
            -
                      repo_matches = repo.match(%r{([\/:])([^\/]+\/[^\/.]+)(?:.git)?$})
         
     | 
| 
       15 
     | 
    
         
            -
                      self.repo_slug = repo_matches[2] unless repo_matches.nil?
         
     | 
| 
       16 
     | 
    
         
            -
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    self.repo_url = env["GIT_URL"]
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.pull_request_id = env["ghprbPullId"]
         
     | 
| 
       17 
21 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                     
     | 
| 
       19 
     | 
    
         
            -
                     
     | 
| 
       20 
     | 
    
         
            -
                      self.pull_request_id = env["ghprbPullId"]
         
     | 
| 
       21 
     | 
    
         
            -
                    end
         
     | 
| 
      
 22 
     | 
    
         
            +
                    repo_matches = self.repo_url.match(%r{([\/:])([^\/]+\/[^\/.]+)(?:.git)?$})
         
     | 
| 
      
 23 
     | 
    
         
            +
                    self.repo_slug = repo_matches[2] unless repo_matches.nil?
         
     | 
| 
       22 
24 
     | 
    
         
             
                  end
         
     | 
| 
       23 
25 
     | 
    
         
             
                end
         
     | 
| 
       24 
26 
     | 
    
         
             
              end
         
     | 
| 
         @@ -4,14 +4,21 @@ module Danger 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module CISource
         
     | 
| 
       5 
5 
     | 
    
         
             
                class Semaphore < CI
         
     | 
| 
       6 
6 
     | 
    
         
             
                  def self.validates?(env)
         
     | 
| 
       7 
     | 
    
         
            -
                    return  
     | 
| 
      
 7 
     | 
    
         
            +
                    return false unless env["SEMAPHORE"]
         
     | 
| 
      
 8 
     | 
    
         
            +
                    return false unless env["SEMAPHORE_REPO_SLUG"]
         
     | 
| 
      
 9 
     | 
    
         
            +
                    return false unless env["PULL_REQUEST_NUMBER"].to_i > 0
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
       8 
16 
     | 
    
         
             
                  end
         
     | 
| 
       9 
17 
     | 
    
         | 
| 
       10 
18 
     | 
    
         
             
                  def initialize(env)
         
     | 
| 
       11 
19 
     | 
    
         
             
                    self.repo_slug = env["SEMAPHORE_REPO_SLUG"]
         
     | 
| 
       12 
     | 
    
         
            -
                     
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
     | 
    
         
            -
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    self.pull_request_id = env["PULL_REQUEST_NUMBER"]
         
     | 
| 
      
 21 
     | 
    
         
            +
                    self.repo_url = GitRepo.new.origins # Semaphore doesn't provide a repo url env variable :/
         
     | 
| 
       15 
22 
     | 
    
         
             
                  end
         
     | 
| 
       16 
23 
     | 
    
         
             
                end
         
     | 
| 
       17 
24 
     | 
    
         
             
              end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Danger
         
     | 
| 
      
 2 
     | 
    
         
            +
              module CISource
         
     | 
| 
      
 3 
     | 
    
         
            +
                class TeamCity < CI
         
     | 
| 
      
 4 
     | 
    
         
            +
                  def self.validates?(env)
         
     | 
| 
      
 5 
     | 
    
         
            +
                    env.key? 'TEAMCITY_VERSION'
         
     | 
| 
      
 6 
     | 
    
         
            +
                  end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 9 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def initialize(env)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    # NB: Unfortunately TeamCity doesn't provide these variables
         
     | 
| 
      
 14 
     | 
    
         
            +
                    # automatically so you have to add these variables manually to your
         
     | 
| 
      
 15 
     | 
    
         
            +
                    # project or build configuration
         
     | 
| 
      
 16 
     | 
    
         
            +
                    self.repo_slug       = env['GITHUB_REPO_SLUG']
         
     | 
| 
      
 17 
     | 
    
         
            +
                    self.pull_request_id = env['GITHUB_PULL_REQUEST_ID'].to_i
         
     | 
| 
      
 18 
     | 
    
         
            +
                    self.repo_url        = env['GITHUB_REPO_URL']
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,15 +5,23 @@ module Danger 
     | 
|
| 
       5 
5 
     | 
    
         
             
              module CISource
         
     | 
| 
       6 
6 
     | 
    
         
             
                class Travis < CI
         
     | 
| 
       7 
7 
     | 
    
         
             
                  def self.validates?(env)
         
     | 
| 
       8 
     | 
    
         
            -
                    return  
     | 
| 
      
 8 
     | 
    
         
            +
                    return false unless env["HAS_JOSH_K_SEAL_OF_APPROVAL"]
         
     | 
| 
      
 9 
     | 
    
         
            +
                    return false unless env["TRAVIS_REPO_SLUG"]
         
     | 
| 
      
 10 
     | 
    
         
            +
                    return false unless env["TRAVIS_PULL_REQUEST"]
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
       9 
17 
     | 
    
         
             
                  end
         
     | 
| 
       10 
18 
     | 
    
         | 
| 
       11 
19 
     | 
    
         
             
                  def initialize(env)
         
     | 
| 
       12 
20 
     | 
    
         
             
                    self.repo_slug = env["TRAVIS_REPO_SLUG"]
         
     | 
| 
       13 
     | 
    
         
            -
                    # from https://docs.travis-ci.com/user/pull-requests, as otherwise it's "false"
         
     | 
| 
       14 
21 
     | 
    
         
             
                    if env["TRAVIS_PULL_REQUEST"].to_i > 0
         
     | 
| 
       15 
22 
     | 
    
         
             
                      self.pull_request_id = env["TRAVIS_PULL_REQUEST"]
         
     | 
| 
       16 
23 
     | 
    
         
             
                    end
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.repo_url = GitRepo.new.origins # Travis doesn't provide a repo url env variable :/
         
     | 
| 
       17 
25 
     | 
    
         
             
                  end
         
     | 
| 
       18 
26 
     | 
    
         
             
                end
         
     | 
| 
       19 
27 
     | 
    
         
             
              end
         
     | 
| 
         @@ -4,7 +4,13 @@ module Danger 
     | 
|
| 
       4 
4 
     | 
    
         
             
              module CISource
         
     | 
| 
       5 
5 
     | 
    
         
             
                class XcodeServer < CI
         
     | 
| 
       6 
6 
     | 
    
         
             
                  def self.validates?(env)
         
     | 
| 
       7 
     | 
    
         
            -
                    return  
     | 
| 
      
 7 
     | 
    
         
            +
                    return false unless env["XCS_BOT_NAME"]
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                    return true
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def supported_request_sources
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @supported_request_sources ||= [Danger::RequestSources::GitHub]
         
     | 
| 
       8 
14 
     | 
    
         
             
                  end
         
     | 
| 
       9 
15 
     | 
    
         | 
| 
       10 
16 
     | 
    
         
             
                  def initialize(env)
         
     | 
| 
         @@ -15,6 +21,7 @@ module Danger 
     | 
|
| 
       15 
21 
     | 
    
         
             
                    self.repo_slug = repo_matches[1] unless repo_matches.nil?
         
     | 
| 
       16 
22 
     | 
    
         
             
                    pull_request_id_matches = bot_name.match(/#(\d+)/)
         
     | 
| 
       17 
23 
     | 
    
         
             
                    self.pull_request_id = pull_request_id_matches[1] unless pull_request_id_matches.nil?
         
     | 
| 
      
 24 
     | 
    
         
            +
                    self.repo_url = GitRepo.new.origins # Xcode Server doesn't provide a repo url env variable :/
         
     | 
| 
       18 
25 
     | 
    
         
             
                  end
         
     | 
| 
       19 
26 
     | 
    
         
             
                end
         
     | 
| 
       20 
27 
     | 
    
         
             
              end
         
     | 
| 
         @@ -15,6 +15,7 @@ module Danger 
     | 
|
| 
       15 
15 
     | 
    
         
             
                  @dangerfile_path = dangerfile if File.exist? dangerfile
         
     | 
| 
       16 
16 
     | 
    
         
             
                  @base = argv.option('base')
         
     | 
| 
       17 
17 
     | 
    
         
             
                  @head = argv.option('head')
         
     | 
| 
      
 18 
     | 
    
         
            +
                  @danger_id = argv.option('danger_id', 'danger')
         
     | 
| 
       18 
19 
     | 
    
         
             
                  super
         
     | 
| 
       19 
20 
     | 
    
         
             
                end
         
     | 
| 
       20 
21 
     | 
    
         | 
| 
         @@ -29,7 +30,8 @@ module Danger 
     | 
|
| 
       29 
30 
     | 
    
         
             
                  [
         
     | 
| 
       30 
31 
     | 
    
         
             
                    ['--base=[master|dev|stable]', 'A branch/tag/commit to use as the base of the diff'],
         
     | 
| 
       31 
32 
     | 
    
         
             
                    ['--head=[master|dev|stable]', 'A branch/tag/commit to use as the head'],
         
     | 
| 
       32 
     | 
    
         
            -
                    ['--dangerfile=<path/to/dangerfile>', 'The location of your Dangerfile']
         
     | 
| 
      
 33 
     | 
    
         
            +
                    ['--dangerfile=<path/to/dangerfile>', 'The location of your Dangerfile'],
         
     | 
| 
      
 34 
     | 
    
         
            +
                    ['--danger_id=<id>', 'The identifier of this Danger instance']
         
     | 
| 
       33 
35 
     | 
    
         
             
                  ].concat(super)
         
     | 
| 
       34 
36 
     | 
    
         
             
                end
         
     | 
| 
       35 
37 
     | 
    
         | 
| 
         @@ -47,8 +49,8 @@ module Danger 
     | 
|
| 
       47 
49 
     | 
    
         
             
                      dm.env.ensure_danger_branches_are_setup
         
     | 
| 
       48 
50 
     | 
    
         | 
| 
       49 
51 
     | 
    
         
             
                      # Offer the chance for a user to specify a branch through the command line
         
     | 
| 
       50 
     | 
    
         
            -
                      ci_base = @base ||  
     | 
| 
       51 
     | 
    
         
            -
                      ci_head = @head ||  
     | 
| 
      
 52 
     | 
    
         
            +
                      ci_base = @base || EnvironmentManager.danger_base_branch
         
     | 
| 
      
 53 
     | 
    
         
            +
                      ci_head = @head || EnvironmentManager.danger_head_branch
         
     | 
| 
       52 
54 
     | 
    
         
             
                      dm.env.scm.diff_for_folder(".", from: ci_base, to: ci_head)
         
     | 
| 
       53 
55 
     | 
    
         | 
| 
       54 
56 
     | 
    
         
             
                      dm.parse Pathname.new(@dangerfile_path)
         
     | 
| 
         @@ -68,7 +70,19 @@ module Danger 
     | 
|
| 
       68 
70 
     | 
    
         
             
                  violations = dm.violation_report
         
     | 
| 
       69 
71 
     | 
    
         
             
                  status = dm.status_report
         
     | 
| 
       70 
72 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
                  gh.update_pull_request!(warnings: violations[:warnings], errors: violations[:errors], messages: violations[:messages], markdowns: status[:markdowns])
         
     | 
| 
      
 73 
     | 
    
         
            +
                  gh.update_pull_request!(warnings: violations[:warnings], errors: violations[:errors], messages: violations[:messages], markdowns: status[:markdowns], danger_id: @danger_id)
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def self.report_error(exception)
         
     | 
| 
      
 77 
     | 
    
         
            +
                  raise exception if exception.kind_of?(SystemExit)
         
     | 
| 
      
 78 
     | 
    
         
            +
                  message = "#{exception.message.red} (#{exception.class.to_s.yellow})"
         
     | 
| 
      
 79 
     | 
    
         
            +
                  if exception.backtrace
         
     | 
| 
      
 80 
     | 
    
         
            +
                    danger_lib = File.expand_path('../../..', __FILE__)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    message << "\n\t" << exception.backtrace.reverse_each.
         
     | 
| 
      
 82 
     | 
    
         
            +
                                         drop_while { |bt| !bt.start_with?(danger_lib) }.reverse.
         
     | 
| 
      
 83 
     | 
    
         
            +
                                         join("\n\t")
         
     | 
| 
      
 84 
     | 
    
         
            +
                  end
         
     | 
| 
      
 85 
     | 
    
         
            +
                  abort(message)
         
     | 
| 
       72 
86 
     | 
    
         
             
                end
         
     | 
| 
       73 
87 
     | 
    
         
             
              end
         
     | 
| 
       74 
88 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,41 +1,40 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
             
     | 
| 
       2 
     | 
    
         
            -
               
     | 
| 
      
 1 
     | 
    
         
            +
            <%- @tables.each do |table| -%>
         
     | 
| 
      
 2 
     | 
    
         
            +
              <%- if table[:content].any? || table[:resolved].any? -%>
         
     | 
| 
       3 
3 
     | 
    
         
             
            <table>
         
     | 
| 
       4 
4 
     | 
    
         
             
              <thead>
         
     | 
| 
       5 
5 
     | 
    
         
             
                <tr>
         
     | 
| 
       6 
6 
     | 
    
         
             
                  <th width="50"></th>
         
     | 
| 
       7 
7 
     | 
    
         
             
                  <th width="100%" data-kind="<%= table[:name] %>">
         
     | 
| 
       8 
     | 
    
         
            -
                     
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
                     
     | 
| 
      
 8 
     | 
    
         
            +
                    <%- if table[:count] > 0 -%>
         
     | 
| 
      
 9 
     | 
    
         
            +
                      <%= table[:count] %> <%= table[:name] %><%= "s" unless table[:count] == 1 %>
         
     | 
| 
      
 10 
     | 
    
         
            +
                    <%- else -%>
         
     | 
| 
      
 11 
     | 
    
         
            +
                      :white_check_mark: <%= random_compliment %>
         
     | 
| 
      
 12 
     | 
    
         
            +
                    <%- end -%>
         
     | 
| 
       13 
13 
     | 
    
         
             
                  </th>
         
     | 
| 
       14 
14 
     | 
    
         
             
                 </tr>
         
     | 
| 
       15 
15 
     | 
    
         
             
              </thead>
         
     | 
| 
       16 
16 
     | 
    
         
             
              <tbody>
         
     | 
| 
       17 
     | 
    
         
            -
                 
     | 
| 
      
 17 
     | 
    
         
            +
                <%- table[:content].each do |violation| -%>
         
     | 
| 
       18 
18 
     | 
    
         
             
                <tr>
         
     | 
| 
       19 
19 
     | 
    
         
             
                  <td>:<%= table[:emoji] %>:</td>
         
     | 
| 
       20 
20 
     | 
    
         
             
                  <td data-sticky="<%= violation.sticky %>"><%= violation.message %></td>
         
     | 
| 
       21 
21 
     | 
    
         
             
                </tr>
         
     | 
| 
       22 
     | 
    
         
            -
                 
     | 
| 
       23 
     | 
    
         
            -
                 
     | 
| 
      
 22 
     | 
    
         
            +
                <%- end -%>
         
     | 
| 
      
 23 
     | 
    
         
            +
                <%- table[:resolved].each do |message| -%>
         
     | 
| 
       24 
24 
     | 
    
         
             
                  <tr>
         
     | 
| 
       25 
25 
     | 
    
         
             
                    <td>:white_check_mark:</td>
         
     | 
| 
       26 
26 
     | 
    
         
             
                    <td data-sticky="true"><del><%= message %></del></td>
         
     | 
| 
       27 
27 
     | 
    
         
             
                  </tr>
         
     | 
| 
       28 
     | 
    
         
            -
                 
     | 
| 
      
 28 
     | 
    
         
            +
                <%- end -%>
         
     | 
| 
       29 
29 
     | 
    
         
             
              </tbody>
         
     | 
| 
       30 
30 
     | 
    
         
             
            </table>
         
     | 
| 
       31 
     | 
    
         
            -
               
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
      
 31 
     | 
    
         
            +
              <%- end -%>
         
     | 
| 
      
 32 
     | 
    
         
            +
            <%- end -%>
         
     | 
| 
       33 
33 
     | 
    
         | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
      
 34 
     | 
    
         
            +
            <%- @markdowns.each do |current| -%>
         
     | 
| 
       35 
35 
     | 
    
         
             
            <%= current %>
         
     | 
| 
       36 
36 
     | 
    
         
             
            <%# the previous line has to be aligned far to the left, otherwise markdown can break easily %>
         
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
            <p align="right" data-meta="generated_by_danger">
         
     | 
| 
      
 37 
     | 
    
         
            +
            <%- end -%>
         
     | 
| 
      
 38 
     | 
    
         
            +
            <p align="right" data-meta="generated_by_<%= @danger_id %>">
         
     | 
| 
       40 
39 
     | 
    
         
             
              Generated by :no_entry_sign: <a href="https://github.com/danger/danger/">danger</a>
         
     | 
| 
       41 
40 
     | 
    
         
             
            </p>
         
     | 
| 
         @@ -82,7 +82,7 @@ module Danger 
     | 
|
| 
       82 
82 
     | 
    
         
             
                # Iterate through available plugin classes and initialize them with
         
     | 
| 
       83 
83 
     | 
    
         
             
                # a reference to this Dangerfile
         
     | 
| 
       84 
84 
     | 
    
         
             
                def refresh_plugins
         
     | 
| 
       85 
     | 
    
         
            -
                  plugins =  
     | 
| 
      
 85 
     | 
    
         
            +
                  plugins = Plugin.all_plugins
         
     | 
| 
       86 
86 
     | 
    
         
             
                  plugins.each do |klass|
         
     | 
| 
       87 
87 
     | 
    
         
             
                    next if klass.respond_to?(:singleton_class?) && klass.singleton_class?
         
     | 
| 
       88 
88 
     | 
    
         
             
                    plugin = klass.new(self)
         
     | 
| 
         @@ -1,17 +1,15 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require "danger/ci_source/ci_source"
         
     | 
| 
       2 
     | 
    
         
            -
            require "danger/request_source/ 
     | 
| 
      
 2 
     | 
    
         
            +
            require "danger/request_source/request_source"
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            module Danger
         
     | 
| 
       5 
5 
     | 
    
         
             
              class EnvironmentManager
         
     | 
| 
       6 
6 
     | 
    
         
             
                attr_accessor :ci_source, :request_source, :scm
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                def initialize(env)
         
     | 
| 
       9 
     | 
    
         
            -
                  CISource. 
     | 
| 
       10 
     | 
    
         
            -
                     
     | 
| 
       11 
     | 
    
         
            -
                    next unless c.kind_of?(Class)
         
     | 
| 
       12 
     | 
    
         
            -
                    next unless c.validates?(env)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  CISource::CI.available_ci_sources.each do |klass|
         
     | 
| 
      
 10 
     | 
    
         
            +
                    next unless klass.validates?(env)
         
     | 
| 
       13 
11 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                    self.ci_source =  
     | 
| 
      
 12 
     | 
    
         
            +
                    self.ci_source = klass.new(env)
         
     | 
| 
       15 
13 
     | 
    
         
             
                    if self.ci_source.repo_slug and self.ci_source.pull_request_id
         
     | 
| 
       16 
14 
     | 
    
         
             
                      break
         
     | 
| 
       17 
15 
     | 
    
         
             
                    else
         
     | 
| 
         @@ -20,12 +18,19 @@ module Danger 
     | 
|
| 
       20 
18 
     | 
    
         
             
                    end
         
     | 
| 
       21 
19 
     | 
    
         
             
                  end
         
     | 
| 
       22 
20 
     | 
    
         | 
| 
       23 
     | 
    
         
            -
                  raise "Could not find a CI  
     | 
| 
      
 21 
     | 
    
         
            +
                  raise "Could not find a valid pull request within the known CI sources".red unless self.ci_source
         
     | 
| 
       24 
22 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                   
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 23 
     | 
    
         
            +
                  RequestSources::RequestSource.available_request_sources.each do |klass|
         
     | 
| 
      
 24 
     | 
    
         
            +
                    next unless self.ci_source.supports?(klass)
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                    request_source = klass.new(self.ci_source, ENV)
         
     | 
| 
      
 27 
     | 
    
         
            +
                    next unless request_source.validates?
         
     | 
| 
      
 28 
     | 
    
         
            +
                    self.request_source = request_source
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  raise "Could not find a Request Source".red unless self.request_source
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
                  self.scm = self.request_source.scm
         
     | 
| 
       29 
34 
     | 
    
         
             
                end
         
     | 
| 
       30 
35 
     | 
    
         | 
| 
       31 
36 
     | 
    
         
             
                def pr?
         
     | 
| 
         @@ -39,40 +44,28 @@ module Danger 
     | 
|
| 
       39 
44 
     | 
    
         
             
                def ensure_danger_branches_are_setup
         
     | 
| 
       40 
45 
     | 
    
         
             
                  clean_up
         
     | 
| 
       41 
46 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                   
     | 
| 
       43 
     | 
    
         
            -
                  pull_id = ci_source.pull_request_id
         
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
                  # TODO: This isn't optimal, should be hidden behind some kind of facade, but the plugin makes that
         
     | 
| 
       46 
     | 
    
         
            -
                  # difficult to do without accessing the dangerfile
         
     | 
| 
       47 
     | 
    
         
            -
                  test_branch = request_source.pr_json[:base][:sha]
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
                  # Next, we want to ensure that we have a version of the current branch at a known location
         
     | 
| 
       50 
     | 
    
         
            -
                  scm.exec "branch #{danger_base_branch} #{test_branch}"
         
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
                  # OK, so we want to ensure that we have a known head branch, this will always represent
         
     | 
| 
       53 
     | 
    
         
            -
                  # the head of the PR ( e.g. the most recent commit that will be merged. )
         
     | 
| 
       54 
     | 
    
         
            -
                  scm.exec "fetch origin +refs/pull/#{pull_id}/merge:#{danger_head_branch}"
         
     | 
| 
      
 47 
     | 
    
         
            +
                  self.request_source.setup_danger_branches
         
     | 
| 
       55 
48 
     | 
    
         
             
                end
         
     | 
| 
       56 
49 
     | 
    
         | 
| 
       57 
50 
     | 
    
         
             
                def clean_up
         
     | 
| 
       58 
     | 
    
         
            -
                  [danger_base_branch,  
     | 
| 
      
 51 
     | 
    
         
            +
                  [EnvironmentManager.danger_base_branch, EnvironmentManager.danger_head_branch].each do |branch|
         
     | 
| 
       59 
52 
     | 
    
         
             
                    scm.exec("branch -D #{branch}") unless scm.exec("rev-parse --quiet --verify #{branch}").empty?
         
     | 
| 
       60 
53 
     | 
    
         
             
                  end
         
     | 
| 
       61 
54 
     | 
    
         
             
                end
         
     | 
| 
       62 
55 
     | 
    
         | 
| 
       63 
56 
     | 
    
         
             
                def meta_info_for_base
         
     | 
| 
       64 
     | 
    
         
            -
                  scm.exec("--no-pager log #{danger_base_branch} -n1")
         
     | 
| 
      
 57 
     | 
    
         
            +
                  scm.exec("--no-pager log #{EnvironmentManager.danger_base_branch} -n1")
         
     | 
| 
       65 
58 
     | 
    
         
             
                end
         
     | 
| 
       66 
59 
     | 
    
         | 
| 
       67 
60 
     | 
    
         
             
                def meta_info_for_head
         
     | 
| 
       68 
     | 
    
         
            -
                  scm.exec("--no-pager log #{danger_head_branch} -n1")
         
     | 
| 
      
 61 
     | 
    
         
            +
                  scm.exec("--no-pager log #{EnvironmentManager.danger_head_branch} -n1")
         
     | 
| 
       69 
62 
     | 
    
         
             
                end
         
     | 
| 
       70 
63 
     | 
    
         | 
| 
       71 
     | 
    
         
            -
                def danger_head_branch
         
     | 
| 
      
 64 
     | 
    
         
            +
                def self.danger_head_branch
         
     | 
| 
       72 
65 
     | 
    
         
             
                  "danger_head"
         
     | 
| 
       73 
66 
     | 
    
         
             
                end
         
     | 
| 
       74 
67 
     | 
    
         | 
| 
       75 
     | 
    
         
            -
                def danger_base_branch
         
     | 
| 
      
 68 
     | 
    
         
            +
                def self.danger_base_branch
         
     | 
| 
       76 
69 
     | 
    
         
             
                  "danger_base"
         
     | 
| 
       77 
70 
     | 
    
         
             
                end
         
     | 
| 
       78 
71 
     | 
    
         
             
              end
         
     | 
| 
         @@ -4,7 +4,7 @@ module Danger 
     | 
|
| 
       4 
4 
     | 
    
         
             
              class DangerfileGitHubPlugin < Plugin
         
     | 
| 
       5 
5 
     | 
    
         
             
                def initialize(dangerfile)
         
     | 
| 
       6 
6 
     | 
    
         
             
                  super(dangerfile)
         
     | 
| 
       7 
     | 
    
         
            -
                  return nil unless dangerfile.env.request_source.class == Danger::GitHub
         
     | 
| 
      
 7 
     | 
    
         
            +
                  return nil unless dangerfile.env.request_source.class == Danger::RequestSources::GitHub
         
     | 
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
                  @github = dangerfile.env.request_source
         
     | 
| 
       10 
10 
     | 
    
         
             
                end
         
     | 
| 
         @@ -5,7 +5,7 @@ module Danger 
     | 
|
| 
       5 
5 
     | 
    
         
             
                end
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
       7 
7 
     | 
    
         
             
                def self.instance_name
         
     | 
| 
       8 
     | 
    
         
            -
                   
     | 
| 
      
 8 
     | 
    
         
            +
                  to_s.gsub("Danger", "").danger_underscore.split('/').last
         
     | 
| 
       9 
9 
     | 
    
         
             
                end
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
11 
     | 
    
         
             
                # Both of these methods exist on all objects
         
     | 
| 
         @@ -13,19 +13,20 @@ module Danger 
     | 
|
| 
       13 
13 
     | 
    
         
             
                # http://ruby-doc.org/core-2.2.3/Kernel.html#method-i-fail
         
     | 
| 
       14 
14 
     | 
    
         
             
                # However, as we're using using them in the DSL, they won't
         
     | 
| 
       15 
15 
     | 
    
         
             
                # get method_missing called correctly.
         
     | 
| 
      
 16 
     | 
    
         
            +
                undef :warn, :fail
         
     | 
| 
       16 
17 
     | 
    
         | 
| 
       17 
     | 
    
         
            -
                 
     | 
| 
       18 
     | 
    
         
            -
             
     | 
| 
      
 18 
     | 
    
         
            +
                # Since we have a reference to the Dangerfile containing all the information
         
     | 
| 
      
 19 
     | 
    
         
            +
                # We need to redirect the self calls to the Dangerfile
         
     | 
| 
      
 20 
     | 
    
         
            +
                def method_missing(method_sym, *arguments, &block)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  @dangerfile.send(method_sym, *arguments, &block)
         
     | 
| 
       19 
22 
     | 
    
         
             
                end
         
     | 
| 
       20 
23 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
                def  
     | 
| 
       22 
     | 
    
         
            -
                   
     | 
| 
      
 24 
     | 
    
         
            +
                def self.all_plugins
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @all_plugins ||= []
         
     | 
| 
       23 
26 
     | 
    
         
             
                end
         
     | 
| 
       24 
27 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
                 
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                def method_missing(method_sym, *arguments, &_block)
         
     | 
| 
       28 
     | 
    
         
            -
                  @dangerfile.send(method_sym, *arguments)
         
     | 
| 
      
 28 
     | 
    
         
            +
                def self.inherited(plugin)
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Plugin.all_plugins.push(plugin)
         
     | 
| 
       29 
30 
     | 
    
         
             
                end
         
     | 
| 
       30 
31 
     | 
    
         
             
              end
         
     | 
| 
       31 
32 
     | 
    
         
             
            end
         
     | 
| 
         @@ -3,201 +3,225 @@ require 'octokit' 
     | 
|
| 
       3 
3 
     | 
    
         
             
            require 'redcarpet'
         
     | 
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            module Danger
         
     | 
| 
       6 
     | 
    
         
            -
               
     | 
| 
       7 
     | 
    
         
            -
                 
     | 
| 
      
 6 
     | 
    
         
            +
              module RequestSources
         
     | 
| 
      
 7 
     | 
    
         
            +
                class GitHub < RequestSource
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_accessor :pr_json, :issue_json, :support_tokenless_auth
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  def initialize(ci_source, environment)
         
     | 
| 
      
 11 
     | 
    
         
            +
                    self.ci_source = ci_source
         
     | 
| 
      
 12 
     | 
    
         
            +
                    self.environment = environment
         
     | 
| 
      
 13 
     | 
    
         
            +
                    self.support_tokenless_auth = false
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    Octokit.auto_paginate = true
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @token = @environment["DANGER_GITHUB_API_TOKEN"]
         
     | 
| 
      
 17 
     | 
    
         
            +
                    if @environment["DANGER_GITHUB_API_HOST"]
         
     | 
| 
      
 18 
     | 
    
         
            +
                      Octokit.api_endpoint = @environment["DANGER_GITHUB_API_HOST"]
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
       8 
21 
     | 
    
         | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
                   
     | 
| 
       12 
     | 
    
         
            -
                  self.support_tokenless_auth = false
         
     | 
| 
      
 22 
     | 
    
         
            +
                  def scm
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @scm ||= GitRepo.new
         
     | 
| 
      
 24 
     | 
    
         
            +
                  end
         
     | 
| 
       13 
25 
     | 
    
         | 
| 
       14 
     | 
    
         
            -
                   
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
                  self.github_host = @environment["DANGER_GITHUB_HOST"] || "github.com"
         
     | 
| 
       17 
     | 
    
         
            -
                  if @environment["DANGER_GITHUB_API_HOST"]
         
     | 
| 
       18 
     | 
    
         
            -
                    Octokit.api_endpoint = @environment["DANGER_GITHUB_API_HOST"]
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def host
         
     | 
| 
      
 27 
     | 
    
         
            +
                    @host = @environment["DANGER_GITHUB_HOST"] || "github.com"
         
     | 
| 
       19 
28 
     | 
    
         
             
                  end
         
     | 
| 
       20 
     | 
    
         
            -
                end
         
     | 
| 
       21 
29 
     | 
    
         | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
      
 30 
     | 
    
         
            +
                  def client
         
     | 
| 
      
 31 
     | 
    
         
            +
                    raise "No API token given, please provide one using `DANGER_GITHUB_API_TOKEN`" if !@token && !support_tokenless_auth
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @client ||= Octokit::Client.new(access_token: @token)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
       26 
34 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def markdown_parser
         
     | 
| 
      
 36 
     | 
    
         
            +
                    @markdown_parser ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML, no_intra_emphasis: true)
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
       30 
38 
     | 
    
         | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
                  def setup_danger_branches
         
     | 
| 
      
 40 
     | 
    
         
            +
                    # we can use a github specific feature here:
         
     | 
| 
      
 41 
     | 
    
         
            +
                    pull_id = self.ci_source.pull_request_id
         
     | 
| 
      
 42 
     | 
    
         
            +
                    test_branch = self.pr_json[:base][:sha]
         
     | 
| 
       36 
43 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
                  return [] if pr_body.nil?
         
     | 
| 
       40 
     | 
    
         
            -
                  pr_body.chomp.scan(/>\s*danger\s*:\s*ignore\s*"(.*)"/i).flatten
         
     | 
| 
       41 
     | 
    
         
            -
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
                    # Next, we want to ensure that we have a version of the current branch at a known location
         
     | 
| 
      
 45 
     | 
    
         
            +
                    self.scm.exec "branch #{EnvironmentManager.danger_base_branch} #{test_branch}"
         
     | 
| 
       42 
46 
     | 
    
         | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
      
 47 
     | 
    
         
            +
                    # OK, so we want to ensure that we have a known head branch, this will always represent
         
     | 
| 
      
 48 
     | 
    
         
            +
                    # the head of the PR ( e.g. the most recent commit that will be merged. )
         
     | 
| 
      
 49 
     | 
    
         
            +
                    self.scm.exec "fetch origin +refs/pull/#{pull_id}/merge:#{EnvironmentManager.danger_head_branch}"
         
     | 
| 
      
 50 
     | 
    
         
            +
                  end
         
     | 
| 
       47 
51 
     | 
    
         | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
      
 52 
     | 
    
         
            +
                  def fetch_details
         
     | 
| 
      
 53 
     | 
    
         
            +
                    self.pr_json = client.pull_request(ci_source.repo_slug, ci_source.pull_request_id)
         
     | 
| 
      
 54 
     | 
    
         
            +
                    fetch_issue_details(self.pr_json)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    self.ignored_violations = ignored_violations_from_pr(self.pr_json)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
       51 
57 
     | 
    
         | 
| 
       52 
     | 
    
         
            -
                   
     | 
| 
       53 
     | 
    
         
            -
             
     | 
| 
      
 58 
     | 
    
         
            +
                  def ignored_violations_from_pr(pr_json)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    pr_body = pr_json[:body]
         
     | 
| 
      
 60 
     | 
    
         
            +
                    return [] if pr_body.nil?
         
     | 
| 
      
 61 
     | 
    
         
            +
                    pr_body.chomp.scan(/>\s*danger\s*:\s*ignore\s*"(.*)"/i).flatten
         
     | 
| 
      
 62 
     | 
    
         
            +
                  end
         
     | 
| 
       54 
63 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                   
     | 
| 
       56 
     | 
    
         
            -
                     
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
                    comment = editable_issues.first[:body]
         
     | 
| 
       59 
     | 
    
         
            -
                    previous_violations = parse_comment(comment)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  def fetch_issue_details(pr_json)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    href = pr_json[:_links][:issue][:href]
         
     | 
| 
      
 66 
     | 
    
         
            +
                    self.issue_json = client.get(href)
         
     | 
| 
       60 
67 
     | 
    
         
             
                  end
         
     | 
| 
       61 
68 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
                   
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                     
     | 
| 
       65 
     | 
    
         
            -
             
     | 
| 
       66 
     | 
    
         
            -
                     
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                                            messages: messages,
         
     | 
| 
       69 
     | 
    
         
            -
                                           markdowns: markdowns,
         
     | 
| 
       70 
     | 
    
         
            -
                                 previous_violations: previous_violations)
         
     | 
| 
      
 69 
     | 
    
         
            +
                  # Sending data to GitHub
         
     | 
| 
      
 70 
     | 
    
         
            +
                  def update_pull_request!(warnings: [], errors: [], messages: [], markdowns: [], danger_id: 'danger')
         
     | 
| 
      
 71 
     | 
    
         
            +
                    comment_result = {}
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                    issues = client.issue_comments(ci_source.repo_slug, ci_source.pull_request_id)
         
     | 
| 
      
 74 
     | 
    
         
            +
                    editable_issues = issues.reject { |issue| issue[:body].include?("generated_by_#{danger_id}") == false }
         
     | 
| 
       71 
75 
     | 
    
         | 
| 
       72 
76 
     | 
    
         
             
                    if editable_issues.empty?
         
     | 
| 
       73 
     | 
    
         
            -
                       
     | 
| 
      
 77 
     | 
    
         
            +
                      previous_violations = {}
         
     | 
| 
       74 
78 
     | 
    
         
             
                    else
         
     | 
| 
       75 
     | 
    
         
            -
                       
     | 
| 
       76 
     | 
    
         
            -
                       
     | 
| 
      
 79 
     | 
    
         
            +
                      comment = editable_issues.first[:body]
         
     | 
| 
      
 80 
     | 
    
         
            +
                      previous_violations = parse_comment(comment)
         
     | 
| 
       77 
81 
     | 
    
         
             
                    end
         
     | 
| 
       78 
     | 
    
         
            -
                  end
         
     | 
| 
       79 
82 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
             
     | 
| 
       81 
     | 
    
         
            -
             
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
      
 83 
     | 
    
         
            +
                    if previous_violations.empty? && (warnings + errors + messages + markdowns).empty?
         
     | 
| 
      
 84 
     | 
    
         
            +
                      # Just remove the comment, if there's nothing to say.
         
     | 
| 
      
 85 
     | 
    
         
            +
                      delete_old_comments!(danger_id: danger_id)
         
     | 
| 
      
 86 
     | 
    
         
            +
                    else
         
     | 
| 
      
 87 
     | 
    
         
            +
                      body = generate_comment(warnings: warnings,
         
     | 
| 
       83 
88 
     | 
    
         
             
                                                errors: errors,
         
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
      
 89 
     | 
    
         
            +
                                              messages: messages,
         
     | 
| 
      
 90 
     | 
    
         
            +
                                             markdowns: markdowns,
         
     | 
| 
      
 91 
     | 
    
         
            +
                                   previous_violations: previous_violations,
         
     | 
| 
      
 92 
     | 
    
         
            +
                                             danger_id: danger_id)
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                      if editable_issues.empty?
         
     | 
| 
      
 95 
     | 
    
         
            +
                        comment_result = client.add_comment(ci_source.repo_slug, ci_source.pull_request_id, body)
         
     | 
| 
      
 96 
     | 
    
         
            +
                      else
         
     | 
| 
      
 97 
     | 
    
         
            +
                        original_id = editable_issues.first[:id]
         
     | 
| 
      
 98 
     | 
    
         
            +
                        comment_result = client.update_comment(ci_source.repo_slug, original_id, body)
         
     | 
| 
      
 99 
     | 
    
         
            +
                      end
         
     | 
| 
      
 100 
     | 
    
         
            +
                    end
         
     | 
| 
       86 
101 
     | 
    
         | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
                    context: "danger/danger",
         
     | 
| 
       93 
     | 
    
         
            -
                    target_url: details_url
         
     | 
| 
       94 
     | 
    
         
            -
                  })
         
     | 
| 
       95 
     | 
    
         
            -
                rescue
         
     | 
| 
       96 
     | 
    
         
            -
                  # This usually means the user has no commit access to this repo
         
     | 
| 
       97 
     | 
    
         
            -
                  # That's always the case for open source projects where you can only
         
     | 
| 
       98 
     | 
    
         
            -
                  # use a read-only GitHub account
         
     | 
| 
       99 
     | 
    
         
            -
                  if errors.count > 0
         
     | 
| 
       100 
     | 
    
         
            -
                    # We need to fail the actual build here
         
     | 
| 
       101 
     | 
    
         
            -
                    abort("\nDanger has failed this build. \nFound #{'error'.danger_pluralize(errors.count)} and I don't have write access to the PR set a PR status.")
         
     | 
| 
       102 
     | 
    
         
            -
                  else
         
     | 
| 
       103 
     | 
    
         
            -
                    puts message
         
     | 
| 
      
 102 
     | 
    
         
            +
                    # Now, set the pull request status.
         
     | 
| 
      
 103 
     | 
    
         
            +
                    # Note: this can terminate the entire process.
         
     | 
| 
      
 104 
     | 
    
         
            +
                    submit_pull_request_status!(warnings: warnings,
         
     | 
| 
      
 105 
     | 
    
         
            +
                                                  errors: errors,
         
     | 
| 
      
 106 
     | 
    
         
            +
                                             details_url: comment_result['html_url'])
         
     | 
| 
       104 
107 
     | 
    
         
             
                  end
         
     | 
| 
       105 
     | 
    
         
            -
                end
         
     | 
| 
       106 
108 
     | 
    
         | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
       111 
     | 
    
         
            -
             
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
      
 109 
     | 
    
         
            +
                  def submit_pull_request_status!(warnings: nil, errors: nil, details_url: nil)
         
     | 
| 
      
 110 
     | 
    
         
            +
                    status = (errors.count == 0 ? 'success' : 'failure')
         
     | 
| 
      
 111 
     | 
    
         
            +
                    message = generate_github_description(warnings: warnings, errors: errors)
         
     | 
| 
      
 112 
     | 
    
         
            +
                    client.create_status(ci_source.repo_slug, latest_pr_commit_ref, status, {
         
     | 
| 
      
 113 
     | 
    
         
            +
                      description: message,
         
     | 
| 
      
 114 
     | 
    
         
            +
                      context: "danger/danger",
         
     | 
| 
      
 115 
     | 
    
         
            +
                      target_url: details_url
         
     | 
| 
      
 116 
     | 
    
         
            +
                    })
         
     | 
| 
      
 117 
     | 
    
         
            +
                  rescue
         
     | 
| 
      
 118 
     | 
    
         
            +
                    # This usually means the user has no commit access to this repo
         
     | 
| 
      
 119 
     | 
    
         
            +
                    # That's always the case for open source projects where you can only
         
     | 
| 
      
 120 
     | 
    
         
            +
                    # use a read-only GitHub account
         
     | 
| 
      
 121 
     | 
    
         
            +
                    if errors.count > 0
         
     | 
| 
      
 122 
     | 
    
         
            +
                      # We need to fail the actual build here
         
     | 
| 
      
 123 
     | 
    
         
            +
                      abort("\nDanger has failed this build. \nFound #{'error'.danger_pluralize(errors.count)} and I don't have write access to the PR set a PR status.")
         
     | 
| 
      
 124 
     | 
    
         
            +
                    else
         
     | 
| 
      
 125 
     | 
    
         
            +
                      puts message
         
     | 
| 
      
 126 
     | 
    
         
            +
                    end
         
     | 
| 
       114 
127 
     | 
    
         
             
                  end
         
     | 
| 
       115 
     | 
    
         
            -
                end
         
     | 
| 
       116 
128 
     | 
    
         | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                   
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
             
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
             
     | 
| 
       125 
     | 
    
         
            -
                    return "All green. #{random_compliment}"
         
     | 
| 
       126 
     | 
    
         
            -
                  else
         
     | 
| 
       127 
     | 
    
         
            -
                    message = "⚠ "
         
     | 
| 
       128 
     | 
    
         
            -
                    message += "#{'Error'.danger_pluralize(errors.count)}. " unless errors.empty?
         
     | 
| 
       129 
     | 
    
         
            -
                    message += "#{'Warning'.danger_pluralize(warnings.count)}. " unless warnings.empty?
         
     | 
| 
       130 
     | 
    
         
            -
                    message += "Don't worry, everything is fixable."
         
     | 
| 
       131 
     | 
    
         
            -
                    return message
         
     | 
| 
      
 129 
     | 
    
         
            +
                  # Get rid of the previously posted comment, to only have the latest one
         
     | 
| 
      
 130 
     | 
    
         
            +
                  def delete_old_comments!(except: nil, danger_id: 'danger')
         
     | 
| 
      
 131 
     | 
    
         
            +
                    issues = client.issue_comments(ci_source.repo_slug, ci_source.pull_request_id)
         
     | 
| 
      
 132 
     | 
    
         
            +
                    issues.each do |issue|
         
     | 
| 
      
 133 
     | 
    
         
            +
                      next unless issue[:body].include?("generated_by_#{danger_id}")
         
     | 
| 
      
 134 
     | 
    
         
            +
                      next if issue[:id] == except
         
     | 
| 
      
 135 
     | 
    
         
            +
                      client.delete_comment(ci_source.repo_slug, issue[:id])
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
       132 
137 
     | 
    
         
             
                  end
         
     | 
| 
       133 
     | 
    
         
            -
                end
         
     | 
| 
       134 
138 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
             
     | 
| 
      
 139 
     | 
    
         
            +
                  def random_compliment
         
     | 
| 
      
 140 
     | 
    
         
            +
                    compliment = ["Well done.", "Congrats.", "Woo!",
         
     | 
| 
      
 141 
     | 
    
         
            +
                                  "Yay.", "Jolly good show.", "Good on 'ya.", "Nice work."]
         
     | 
| 
      
 142 
     | 
    
         
            +
                    compliment.sample
         
     | 
| 
      
 143 
     | 
    
         
            +
                  end
         
     | 
| 
       137 
144 
     | 
    
         | 
| 
       138 
     | 
    
         
            -
                   
     | 
| 
      
 145 
     | 
    
         
            +
                  def generate_github_description(warnings: nil, errors: nil)
         
     | 
| 
      
 146 
     | 
    
         
            +
                    if errors.empty? && warnings.empty?
         
     | 
| 
      
 147 
     | 
    
         
            +
                      return "All green. #{random_compliment}"
         
     | 
| 
      
 148 
     | 
    
         
            +
                    else
         
     | 
| 
      
 149 
     | 
    
         
            +
                      message = "⚠ "
         
     | 
| 
      
 150 
     | 
    
         
            +
                      message += "#{'Error'.danger_pluralize(errors.count)}. " unless errors.empty?
         
     | 
| 
      
 151 
     | 
    
         
            +
                      message += "#{'Warning'.danger_pluralize(warnings.count)}. " unless warnings.empty?
         
     | 
| 
      
 152 
     | 
    
         
            +
                      message += "Don't worry, everything is fixable."
         
     | 
| 
      
 153 
     | 
    
         
            +
                      return message
         
     | 
| 
      
 154 
     | 
    
         
            +
                    end
         
     | 
| 
      
 155 
     | 
    
         
            +
                  end
         
     | 
| 
       139 
156 
     | 
    
         | 
| 
       140 
     | 
    
         
            -
                   
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
                  @tables = [
         
     | 
| 
       143 
     | 
    
         
            -
                    table("Error", "no_entry_sign", errors, previous_violations),
         
     | 
| 
       144 
     | 
    
         
            -
                    table("Warning", "warning", warnings, previous_violations),
         
     | 
| 
       145 
     | 
    
         
            -
                    table("Message", "book", messages, previous_violations)
         
     | 
| 
       146 
     | 
    
         
            -
                  ]
         
     | 
| 
       147 
     | 
    
         
            -
                  @markdowns = markdowns
         
     | 
| 
      
 157 
     | 
    
         
            +
                  def generate_comment(warnings: [], errors: [], messages: [], markdowns: [], previous_violations: {}, danger_id: 'danger')
         
     | 
| 
      
 158 
     | 
    
         
            +
                    require 'erb'
         
     | 
| 
       148 
159 
     | 
    
         | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
                end
         
     | 
| 
      
 160 
     | 
    
         
            +
                    md_template = File.join(Danger.gem_path, "lib/danger/comment_generators/github.md.erb")
         
     | 
| 
       151 
161 
     | 
    
         | 
| 
       152 
     | 
    
         
            -
             
     | 
| 
       153 
     | 
    
         
            -
             
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
             
     | 
| 
       156 
     | 
    
         
            -
             
     | 
| 
       157 
     | 
    
         
            -
             
     | 
| 
       158 
     | 
    
         
            -
             
     | 
| 
       159 
     | 
    
         
            -
             
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
      
 162 
     | 
    
         
            +
                    # erb: http://www.rrn.dk/rubys-erb-templating-system
         
     | 
| 
      
 163 
     | 
    
         
            +
                    # for the extra args: http://stackoverflow.com/questions/4632879/erb-template-removing-the-trailing-line
         
     | 
| 
      
 164 
     | 
    
         
            +
                    @tables = [
         
     | 
| 
      
 165 
     | 
    
         
            +
                      table("Error", "no_entry_sign", errors, previous_violations),
         
     | 
| 
      
 166 
     | 
    
         
            +
                      table("Warning", "warning", warnings, previous_violations),
         
     | 
| 
      
 167 
     | 
    
         
            +
                      table("Message", "book", messages, previous_violations)
         
     | 
| 
      
 168 
     | 
    
         
            +
                    ]
         
     | 
| 
      
 169 
     | 
    
         
            +
                    @markdowns = markdowns
         
     | 
| 
      
 170 
     | 
    
         
            +
                    @danger_id = danger_id
         
     | 
| 
       161 
171 
     | 
    
         | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
       163 
     | 
    
         
            -
                   
     | 
| 
       164 
     | 
    
         
            -
                  violations = {}
         
     | 
| 
       165 
     | 
    
         
            -
                  tables.each do |table|
         
     | 
| 
       166 
     | 
    
         
            -
                    next unless table =~ %r{<th width="100%"(.*?)</th>}im
         
     | 
| 
       167 
     | 
    
         
            -
                    title = Regexp.last_match(1)
         
     | 
| 
       168 
     | 
    
         
            -
                    kind = table_kind_from_title(title)
         
     | 
| 
       169 
     | 
    
         
            -
                    next unless kind
         
     | 
| 
      
 172 
     | 
    
         
            +
                    return ERB.new(File.read(md_template), 0, "-").result(binding)
         
     | 
| 
      
 173 
     | 
    
         
            +
                  end
         
     | 
| 
       170 
174 
     | 
    
         | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
      
 175 
     | 
    
         
            +
                  def table(name, emoji, violations, all_previous_violations)
         
     | 
| 
      
 176 
     | 
    
         
            +
                    content = violations.map { |v| process_markdown(v) }.uniq
         
     | 
| 
      
 177 
     | 
    
         
            +
                    kind = table_kind_from_title(name)
         
     | 
| 
      
 178 
     | 
    
         
            +
                    previous_violations = all_previous_violations[kind] || []
         
     | 
| 
      
 179 
     | 
    
         
            +
                    messages = content.map(&:message)
         
     | 
| 
      
 180 
     | 
    
         
            +
                    resolved_violations = previous_violations.uniq - messages
         
     | 
| 
      
 181 
     | 
    
         
            +
                    count = content.count
         
     | 
| 
      
 182 
     | 
    
         
            +
                    { name: name, emoji: emoji, content: content, resolved: resolved_violations, count: count }
         
     | 
| 
       172 
183 
     | 
    
         
             
                  end
         
     | 
| 
       173 
184 
     | 
    
         | 
| 
       174 
     | 
    
         
            -
                   
     | 
| 
       175 
     | 
    
         
            -
             
     | 
| 
      
 185 
     | 
    
         
            +
                  def parse_comment(comment)
         
     | 
| 
      
 186 
     | 
    
         
            +
                    tables = parse_tables_from_comment(comment)
         
     | 
| 
      
 187 
     | 
    
         
            +
                    violations = {}
         
     | 
| 
      
 188 
     | 
    
         
            +
                    tables.each do |table|
         
     | 
| 
      
 189 
     | 
    
         
            +
                      next unless table =~ %r{<th width="100%"(.*?)</th>}im
         
     | 
| 
      
 190 
     | 
    
         
            +
                      title = Regexp.last_match(1)
         
     | 
| 
      
 191 
     | 
    
         
            +
                      kind = table_kind_from_title(title)
         
     | 
| 
      
 192 
     | 
    
         
            +
                      next unless kind
         
     | 
| 
       176 
193 
     | 
    
         | 
| 
       177 
     | 
    
         
            -
             
     | 
| 
       178 
     | 
    
         
            -
             
     | 
| 
       179 
     | 
    
         
            -
                  table.scan(regex).flatten.map(&:strip)
         
     | 
| 
       180 
     | 
    
         
            -
                end
         
     | 
| 
      
 194 
     | 
    
         
            +
                      violations[kind] = violations_from_table(table)
         
     | 
| 
      
 195 
     | 
    
         
            +
                    end
         
     | 
| 
       181 
196 
     | 
    
         | 
| 
       182 
     | 
    
         
            -
             
     | 
| 
       183 
     | 
    
         
            -
                  if title =~ /error/i
         
     | 
| 
       184 
     | 
    
         
            -
                    :error
         
     | 
| 
       185 
     | 
    
         
            -
                  elsif title =~ /warning/i
         
     | 
| 
       186 
     | 
    
         
            -
                    :warning
         
     | 
| 
       187 
     | 
    
         
            -
                  elsif title =~ /message/i
         
     | 
| 
       188 
     | 
    
         
            -
                    :message
         
     | 
| 
      
 197 
     | 
    
         
            +
                    violations.reject { |_, v| v.empty? }
         
     | 
| 
       189 
198 
     | 
    
         
             
                  end
         
     | 
| 
       190 
     | 
    
         
            -
                end
         
     | 
| 
       191 
199 
     | 
    
         | 
| 
       192 
     | 
    
         
            -
             
     | 
| 
       193 
     | 
    
         
            -
             
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
      
 200 
     | 
    
         
            +
                  def violations_from_table(table)
         
     | 
| 
      
 201 
     | 
    
         
            +
                    regex = %r{<td data-sticky="true">(?:<del>)?(.*?)(?:</del>)?\s*</td>}im
         
     | 
| 
      
 202 
     | 
    
         
            +
                    table.scan(regex).flatten.map(&:strip)
         
     | 
| 
      
 203 
     | 
    
         
            +
                  end
         
     | 
| 
       195 
204 
     | 
    
         | 
| 
       196 
     | 
    
         
            -
             
     | 
| 
       197 
     | 
    
         
            -
             
     | 
| 
       198 
     | 
    
         
            -
             
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
      
 205 
     | 
    
         
            +
                  def table_kind_from_title(title)
         
     | 
| 
      
 206 
     | 
    
         
            +
                    if title =~ /error/i
         
     | 
| 
      
 207 
     | 
    
         
            +
                      :error
         
     | 
| 
      
 208 
     | 
    
         
            +
                    elsif title =~ /warning/i
         
     | 
| 
      
 209 
     | 
    
         
            +
                      :warning
         
     | 
| 
      
 210 
     | 
    
         
            +
                    elsif title =~ /message/i
         
     | 
| 
      
 211 
     | 
    
         
            +
                      :message
         
     | 
| 
      
 212 
     | 
    
         
            +
                    end
         
     | 
| 
      
 213 
     | 
    
         
            +
                  end
         
     | 
| 
      
 214 
     | 
    
         
            +
             
     | 
| 
      
 215 
     | 
    
         
            +
                  def parse_tables_from_comment(comment)
         
     | 
| 
      
 216 
     | 
    
         
            +
                    comment.split('</table>')
         
     | 
| 
      
 217 
     | 
    
         
            +
                  end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  def process_markdown(violation)
         
     | 
| 
      
 220 
     | 
    
         
            +
                    html = markdown_parser.render(violation.message)
         
     | 
| 
      
 221 
     | 
    
         
            +
                    match = html.match(%r{^<p>(.*)</p>$})
         
     | 
| 
      
 222 
     | 
    
         
            +
                    message = match.nil? ? html : match.captures.first
         
     | 
| 
      
 223 
     | 
    
         
            +
                    Violation.new(message, violation.sticky)
         
     | 
| 
      
 224 
     | 
    
         
            +
                  end
         
     | 
| 
       201 
225 
     | 
    
         
             
                end
         
     | 
| 
       202 
226 
     | 
    
         
             
              end
         
     | 
| 
       203 
227 
     | 
    
         
             
            end
         
     | 
| 
         @@ -0,0 +1,48 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Danger
         
     | 
| 
      
 2 
     | 
    
         
            +
              module RequestSources
         
     | 
| 
      
 3 
     | 
    
         
            +
                class RequestSource
         
     | 
| 
      
 4 
     | 
    
         
            +
                  attr_accessor :ci_source, :environment, :scm, :host, :ignored_violations
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                  def self.inherited(child_class)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    available_request_sources.add child_class
         
     | 
| 
      
 8 
     | 
    
         
            +
                    super
         
     | 
| 
      
 9 
     | 
    
         
            +
                  end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def self.available_request_sources
         
     | 
| 
      
 12 
     | 
    
         
            +
                    @available_request_sources ||= Set.new
         
     | 
| 
      
 13 
     | 
    
         
            +
                  end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def initialize(_ci_source, _environment)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    raise "Subclass and overwrite initialize"
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def validates?
         
     | 
| 
      
 20 
     | 
    
         
            +
                    !!self.scm.origins.match(%r{#{Regexp.escape self.host}(:|/)(?<repo_slug>.+/.+?)(?:\.git)?$})
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  def scm
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @scm ||= nil
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  def host
         
     | 
| 
      
 28 
     | 
    
         
            +
                    @host ||= nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  def ignored_violations
         
     | 
| 
      
 32 
     | 
    
         
            +
                    @ignored_violations ||= []
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  def update_pull_request!(_warnings: [], _errors: [], _messages: [], _markdowns: [])
         
     | 
| 
      
 36 
     | 
    
         
            +
                    raise "Subclass and overwrite update_pull_request!"
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                  def setup_danger_branches
         
     | 
| 
      
 40 
     | 
    
         
            +
                    raise "Subclass and overwrite setup_danger_branches"
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                  def fetch_details
         
     | 
| 
      
 44 
     | 
    
         
            +
                    raise "Subclass and overwrite initialize"
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
              end
         
     | 
| 
      
 48 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/danger/version.rb
    CHANGED
    
    
    
        metadata
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: danger
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.8. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.8.2
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Orta Therox
         
     | 
| 
         @@ -9,7 +9,7 @@ authors: 
     | 
|
| 
       9 
9 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       10 
10 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       11 
11 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       12 
     | 
    
         
            -
            date: 2016-06- 
     | 
| 
      
 12 
     | 
    
         
            +
            date: 2016-06-09 00:00:00.000000000 Z
         
     | 
| 
       13 
13 
     | 
    
         
             
            dependencies:
         
     | 
| 
       14 
14 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       15 
15 
     | 
    
         
             
              name: claide
         
     | 
| 
         @@ -273,6 +273,7 @@ files: 
     | 
|
| 
       273 
273 
     | 
    
         
             
            - lib/danger/ci_source/jenkins.rb
         
     | 
| 
       274 
274 
     | 
    
         
             
            - lib/danger/ci_source/local_git_repo.rb
         
     | 
| 
       275 
275 
     | 
    
         
             
            - lib/danger/ci_source/semaphore.rb
         
     | 
| 
      
 276 
     | 
    
         
            +
            - lib/danger/ci_source/teamcity.rb
         
     | 
| 
       276 
277 
     | 
    
         
             
            - lib/danger/ci_source/travis.rb
         
     | 
| 
       277 
278 
     | 
    
         
             
            - lib/danger/ci_source/xcode_server.rb
         
     | 
| 
       278 
279 
     | 
    
         
             
            - lib/danger/commands/init.rb
         
     | 
| 
         @@ -295,6 +296,7 @@ files: 
     | 
|
| 
       295 
296 
     | 
    
         
             
            - lib/danger/plugin_support/plugin.rb
         
     | 
| 
       296 
297 
     | 
    
         
             
            - lib/danger/plugin_support/plugin_parser.rb
         
     | 
| 
       297 
298 
     | 
    
         
             
            - lib/danger/request_source/github.rb
         
     | 
| 
      
 299 
     | 
    
         
            +
            - lib/danger/request_source/request_source.rb
         
     | 
| 
       298 
300 
     | 
    
         
             
            - lib/danger/scm_source/git_repo.rb
         
     | 
| 
       299 
301 
     | 
    
         
             
            - lib/danger/version.rb
         
     | 
| 
       300 
302 
     | 
    
         
             
            homepage: http://github.com/danger/danger
         
     |