danger 8.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +94 -0
  4. data/bin/danger +5 -0
  5. data/lib/assets/DangerfileTemplate +13 -0
  6. data/lib/danger.rb +44 -0
  7. data/lib/danger/ci_source/appcenter.rb +55 -0
  8. data/lib/danger/ci_source/appveyor.rb +60 -0
  9. data/lib/danger/ci_source/azure_pipelines.rb +44 -0
  10. data/lib/danger/ci_source/bamboo.rb +41 -0
  11. data/lib/danger/ci_source/bitbucket_pipelines.rb +37 -0
  12. data/lib/danger/ci_source/bitrise.rb +65 -0
  13. data/lib/danger/ci_source/buddybuild.rb +62 -0
  14. data/lib/danger/ci_source/buildkite.rb +51 -0
  15. data/lib/danger/ci_source/ci_source.rb +37 -0
  16. data/lib/danger/ci_source/circle.rb +94 -0
  17. data/lib/danger/ci_source/circle_api.rb +51 -0
  18. data/lib/danger/ci_source/cirrus.rb +31 -0
  19. data/lib/danger/ci_source/code_build.rb +57 -0
  20. data/lib/danger/ci_source/codefresh.rb +53 -0
  21. data/lib/danger/ci_source/codeship.rb +44 -0
  22. data/lib/danger/ci_source/dotci.rb +52 -0
  23. data/lib/danger/ci_source/drone.rb +71 -0
  24. data/lib/danger/ci_source/github_actions.rb +43 -0
  25. data/lib/danger/ci_source/gitlab_ci.rb +86 -0
  26. data/lib/danger/ci_source/jenkins.rb +149 -0
  27. data/lib/danger/ci_source/local_git_repo.rb +119 -0
  28. data/lib/danger/ci_source/local_only_git_repo.rb +47 -0
  29. data/lib/danger/ci_source/screwdriver.rb +47 -0
  30. data/lib/danger/ci_source/semaphore.rb +37 -0
  31. data/lib/danger/ci_source/support/commits.rb +17 -0
  32. data/lib/danger/ci_source/support/find_repo_info_from_logs.rb +35 -0
  33. data/lib/danger/ci_source/support/find_repo_info_from_url.rb +42 -0
  34. data/lib/danger/ci_source/support/local_pull_request.rb +14 -0
  35. data/lib/danger/ci_source/support/no_pull_request.rb +7 -0
  36. data/lib/danger/ci_source/support/no_repo_info.rb +5 -0
  37. data/lib/danger/ci_source/support/pull_request_finder.rb +179 -0
  38. data/lib/danger/ci_source/support/remote_pull_request.rb +15 -0
  39. data/lib/danger/ci_source/support/repo_info.rb +10 -0
  40. data/lib/danger/ci_source/surf.rb +37 -0
  41. data/lib/danger/ci_source/teamcity.rb +159 -0
  42. data/lib/danger/ci_source/travis.rb +51 -0
  43. data/lib/danger/ci_source/vsts.rb +73 -0
  44. data/lib/danger/ci_source/xcode_server.rb +48 -0
  45. data/lib/danger/clients/rubygems_client.rb +14 -0
  46. data/lib/danger/commands/dangerfile/gem.rb +43 -0
  47. data/lib/danger/commands/dangerfile/init.rb +30 -0
  48. data/lib/danger/commands/dry_run.rb +54 -0
  49. data/lib/danger/commands/init.rb +297 -0
  50. data/lib/danger/commands/init_helpers/interviewer.rb +92 -0
  51. data/lib/danger/commands/local.rb +83 -0
  52. data/lib/danger/commands/local_helpers/http_cache.rb +36 -0
  53. data/lib/danger/commands/local_helpers/local_setup.rb +46 -0
  54. data/lib/danger/commands/local_helpers/pry_setup.rb +31 -0
  55. data/lib/danger/commands/plugins/plugin_json.rb +46 -0
  56. data/lib/danger/commands/plugins/plugin_lint.rb +54 -0
  57. data/lib/danger/commands/plugins/plugin_readme.rb +45 -0
  58. data/lib/danger/commands/pr.rb +92 -0
  59. data/lib/danger/commands/runner.rb +94 -0
  60. data/lib/danger/commands/staging.rb +53 -0
  61. data/lib/danger/commands/systems.rb +43 -0
  62. data/lib/danger/comment_generators/bitbucket_server.md.erb +20 -0
  63. data/lib/danger/comment_generators/bitbucket_server_inline.md.erb +15 -0
  64. data/lib/danger/comment_generators/bitbucket_server_message_group.md.erb +12 -0
  65. data/lib/danger/comment_generators/github.md.erb +55 -0
  66. data/lib/danger/comment_generators/github_inline.md.erb +26 -0
  67. data/lib/danger/comment_generators/gitlab.md.erb +40 -0
  68. data/lib/danger/comment_generators/gitlab_inline.md.erb +26 -0
  69. data/lib/danger/comment_generators/vsts.md.erb +20 -0
  70. data/lib/danger/core_ext/file_list.rb +18 -0
  71. data/lib/danger/core_ext/string.rb +20 -0
  72. data/lib/danger/danger_core/dangerfile.rb +341 -0
  73. data/lib/danger/danger_core/dangerfile_dsl.rb +29 -0
  74. data/lib/danger/danger_core/dangerfile_generator.rb +11 -0
  75. data/lib/danger/danger_core/environment_manager.rb +123 -0
  76. data/lib/danger/danger_core/executor.rb +92 -0
  77. data/lib/danger/danger_core/message_aggregator.rb +49 -0
  78. data/lib/danger/danger_core/message_group.rb +68 -0
  79. data/lib/danger/danger_core/messages/base.rb +56 -0
  80. data/lib/danger/danger_core/messages/markdown.rb +42 -0
  81. data/lib/danger/danger_core/messages/violation.rb +54 -0
  82. data/lib/danger/danger_core/plugins/dangerfile_bitbucket_cloud_plugin.rb +144 -0
  83. data/lib/danger/danger_core/plugins/dangerfile_bitbucket_server_plugin.rb +211 -0
  84. data/lib/danger/danger_core/plugins/dangerfile_danger_plugin.rb +248 -0
  85. data/lib/danger/danger_core/plugins/dangerfile_git_plugin.rb +158 -0
  86. data/lib/danger/danger_core/plugins/dangerfile_github_plugin.rb +254 -0
  87. data/lib/danger/danger_core/plugins/dangerfile_gitlab_plugin.rb +240 -0
  88. data/lib/danger/danger_core/plugins/dangerfile_local_only_plugin.rb +42 -0
  89. data/lib/danger/danger_core/plugins/dangerfile_messaging_plugin.rb +218 -0
  90. data/lib/danger/danger_core/plugins/dangerfile_vsts_plugin.rb +191 -0
  91. data/lib/danger/danger_core/standard_error.rb +143 -0
  92. data/lib/danger/helpers/array_subclass.rb +61 -0
  93. data/lib/danger/helpers/comment.rb +32 -0
  94. data/lib/danger/helpers/comments_helper.rb +178 -0
  95. data/lib/danger/helpers/comments_parsing_helper.rb +70 -0
  96. data/lib/danger/helpers/emoji_mapper.rb +41 -0
  97. data/lib/danger/helpers/find_max_num_violations.rb +31 -0
  98. data/lib/danger/helpers/message_groups_array_helper.rb +31 -0
  99. data/lib/danger/plugin_support/gems_resolver.rb +77 -0
  100. data/lib/danger/plugin_support/plugin.rb +49 -0
  101. data/lib/danger/plugin_support/plugin_file_resolver.rb +30 -0
  102. data/lib/danger/plugin_support/plugin_linter.rb +161 -0
  103. data/lib/danger/plugin_support/plugin_parser.rb +199 -0
  104. data/lib/danger/plugin_support/templates/readme_table.html.erb +26 -0
  105. data/lib/danger/request_sources/bitbucket_cloud.rb +171 -0
  106. data/lib/danger/request_sources/bitbucket_cloud_api.rb +181 -0
  107. data/lib/danger/request_sources/bitbucket_server.rb +105 -0
  108. data/lib/danger/request_sources/bitbucket_server_api.rb +117 -0
  109. data/lib/danger/request_sources/github/github.rb +530 -0
  110. data/lib/danger/request_sources/github/github_review.rb +126 -0
  111. data/lib/danger/request_sources/github/github_review_resolver.rb +19 -0
  112. data/lib/danger/request_sources/github/github_review_unsupported.rb +25 -0
  113. data/lib/danger/request_sources/gitlab.rb +525 -0
  114. data/lib/danger/request_sources/local_only.rb +53 -0
  115. data/lib/danger/request_sources/request_source.rb +85 -0
  116. data/lib/danger/request_sources/support/get_ignored_violation.rb +17 -0
  117. data/lib/danger/request_sources/vsts.rb +118 -0
  118. data/lib/danger/request_sources/vsts_api.rb +138 -0
  119. data/lib/danger/scm_source/git_repo.rb +181 -0
  120. data/lib/danger/version.rb +4 -0
  121. metadata +339 -0
@@ -0,0 +1,47 @@
1
+ require "git"
2
+ require "danger/request_sources/local_only"
3
+
4
+ module Danger
5
+ # ### CI Setup
6
+ #
7
+ # For setting up LocalOnlyGitRepo there is not much needed. Either `--base` and `--head` need to be specified or
8
+ # origin/master is expected for base and HEAD for head
9
+ #
10
+ class LocalOnlyGitRepo < CI
11
+ attr_accessor :base_commit, :head_commit
12
+ HEAD_VAR = "DANGER_LOCAL_HEAD".freeze
13
+ BASE_VAR = "DANGER_LOCAL_BASE".freeze
14
+
15
+ def self.validates_as_ci?(env)
16
+ env.key? "DANGER_USE_LOCAL_ONLY_GIT"
17
+ end
18
+
19
+ def self.validates_as_pr?(_env)
20
+ false
21
+ end
22
+
23
+ def git
24
+ @git ||= GitRepo.new
25
+ end
26
+
27
+ def run_git(command)
28
+ git.exec(command).encode("UTF-8", "binary", invalid: :replace, undef: :replace, replace: "")
29
+ end
30
+
31
+ def supported_request_sources
32
+ @supported_request_sources ||= [Danger::RequestSources::LocalOnly]
33
+ end
34
+
35
+ def initialize(env = {})
36
+ @env = env
37
+
38
+ # expects --base/--head specified OR origin/master to be base and HEAD head
39
+ self.base_commit = env[BASE_VAR] || run_git("rev-parse --abbrev-ref origin/master")
40
+ self.head_commit = env[HEAD_VAR] || run_git("rev-parse --abbrev-ref HEAD")
41
+ end
42
+
43
+ private
44
+
45
+ attr_reader :env
46
+ end
47
+ end
@@ -0,0 +1,47 @@
1
+ # http://screwdriver.cd
2
+ # https://docs.screwdriver.cd/user-guide/environment-variables
3
+ require "danger/request_sources/github/github"
4
+
5
+ module Danger
6
+ # ### CI Setup
7
+ #
8
+ # Install dependencies and add a danger step to your screwdriver.yaml:
9
+ # ``` yml
10
+ # jobs:
11
+ # danger:
12
+ # requires: [~pr, ~commit]
13
+ # steps:
14
+ # - setup: bundle install --path vendor
15
+ # - danger: bundle exec danger
16
+ # secrets:
17
+ # - DANGER_GITHUB_API_TOKEN
18
+ # ```
19
+ #
20
+ # ### Token Setup
21
+ #
22
+ # Add the `DANGER_GITHUB_API_TOKEN` to your pipeline env as a
23
+ # [build secret](https://docs.screwdriver.cd/user-guide/configuration/secrets)
24
+ #
25
+ class Screwdriver < CI
26
+ def self.validates_as_ci?(env)
27
+ env.key? "SCREWDRIVER"
28
+ end
29
+
30
+ def self.validates_as_pr?(env)
31
+ exists = ["SD_PULL_REQUEST", "SCM_URL"].all? { |x| env[x] && !env[x].empty? }
32
+ exists && env["SD_PULL_REQUEST"].to_i > 0
33
+ end
34
+
35
+ def supported_request_sources
36
+ @supported_request_sources ||= [Danger::RequestSources::GitHub]
37
+ end
38
+
39
+ def initialize(env)
40
+ self.repo_slug = env["SCM_URL"].split(":").last.gsub(".git", "").split("#", 2).first
41
+ self.repo_url = env["SCM_URL"].split("#", 2).first
42
+ if env["SD_PULL_REQUEST"].to_i > 0
43
+ self.pull_request_id = env["SD_PULL_REQUEST"]
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,37 @@
1
+ # https://docs.semaphoreci.com/article/12-environment-variables
2
+ require "danger/request_sources/github/github"
3
+
4
+ module Danger
5
+ # ### CI Setup
6
+ #
7
+ # For Semaphore you will want to go to the settings page of the project. Inside "Build Settings"
8
+ # you should add `bundle exec danger` to the Setup thread. Note that Semaphore only provides
9
+ # the build environment variables necessary for Danger on PRs across forks.
10
+ #
11
+ # ### Token Setup
12
+ #
13
+ # You can add your `DANGER_GITHUB_API_TOKEN` inside the "Environment Variables" section in the settings.
14
+ #
15
+ class Semaphore < CI
16
+ def self.validates_as_ci?(env)
17
+ env.key? "SEMAPHORE"
18
+ end
19
+
20
+ def self.validates_as_pr?(env)
21
+ one = ["SEMAPHORE_REPO_SLUG", "PULL_REQUEST_NUMBER"].all? { |x| env[x] && !env[x].empty? }
22
+ two = ["SEMAPHORE_GIT_REPO_SLUG", "SEMAPHORE_GIT_PR_NUMBER"].all? { |x| env[x] && !env[x].empty? }
23
+
24
+ one || two
25
+ end
26
+
27
+ def supported_request_sources
28
+ @supported_request_sources ||= [Danger::RequestSources::GitHub]
29
+ end
30
+
31
+ def initialize(env)
32
+ self.repo_slug = env["SEMAPHORE_GIT_REPO_SLUG"] || env["SEMAPHORE_REPO_SLUG"]
33
+ self.pull_request_id = env["SEMAPHORE_GIT_PR_NUMBER"] || env["PULL_REQUEST_NUMBER"]
34
+ self.repo_url = env["SEMAPHORE_GIT_URL"] || GitRepo.new.origins
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,17 @@
1
+ class Commits
2
+ def initialize(base_head)
3
+ @base_head = base_head.strip.split(" ".freeze)
4
+ end
5
+
6
+ def base
7
+ base_head.first
8
+ end
9
+
10
+ def head
11
+ base_head.last
12
+ end
13
+
14
+ private
15
+
16
+ attr_reader :base_head
17
+ end
@@ -0,0 +1,35 @@
1
+ require "danger/ci_source/support/repo_info"
2
+
3
+ module Danger
4
+ class FindRepoInfoFromLogs
5
+ def initialize(github_host, remote_logs)
6
+ @github_host = github_host
7
+ @remote_logs = remote_logs
8
+ end
9
+
10
+ def call
11
+ matched = remote.match(regexp)
12
+
13
+ if matched
14
+ RepoInfo.new(matched["repo_slug"], nil)
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ attr_reader :remote_logs, :github_host
21
+
22
+ def remote
23
+ remote_logs.lines.grep(/Fetch URL/)[0].split(": ".freeze, 2)[1]
24
+ end
25
+
26
+ def regexp
27
+ %r{
28
+ #{Regexp.escape(github_host)}
29
+ (:|/|(:/))
30
+ (?<repo_slug>[^/]+/.+?)
31
+ (?:\.git)?$
32
+ }x
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,42 @@
1
+ require "danger/ci_source/support/repo_info"
2
+
3
+ module Danger
4
+ class FindRepoInfoFromURL
5
+ REGEXP = %r{
6
+ ://[^/]+/
7
+ (?<slug>[^/]+(/[^/]+){1,2})
8
+ (/(pull|merge_requests|pull-requests)/)
9
+ (?<id>\d+)
10
+ }x
11
+
12
+ # Regex used to extract info from Bitbucket server URLs, as they use a quite different format
13
+ REGEXPBB = %r{
14
+ (?:[\/:])projects
15
+ \/([^\/.]+)
16
+ \/repos\/([^\/.]+)
17
+ \/pull-requests
18
+ \/(\d+)
19
+ }x
20
+
21
+ def initialize(url)
22
+ @url = url
23
+ end
24
+
25
+ def call
26
+ matched = url.match(REGEXPBB)
27
+
28
+ if matched
29
+ RepoInfo.new("#{matched[1]}/#{matched[2]}", matched[3])
30
+ else
31
+ matched = url.match(REGEXP)
32
+ if matched
33
+ RepoInfo.new(matched[:slug], matched[:id])
34
+ end
35
+ end
36
+ end
37
+
38
+ private
39
+
40
+ attr_reader :url
41
+ end
42
+ end
@@ -0,0 +1,14 @@
1
+ module Danger
2
+ class LocalPullRequest
3
+ attr_reader :pull_request_id, :sha
4
+
5
+ def initialize(log_line)
6
+ @pull_request_id = log_line.match(/#(?<id>[0-9]+)/)[:id]
7
+ @sha = log_line.split(" ".freeze).first
8
+ end
9
+
10
+ def valid?
11
+ pull_request_id && sha
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,7 @@
1
+ module Danger
2
+ class NoPullRequest
3
+ def valid?
4
+ false
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module Danger
2
+ class NoRepoInfo
3
+ attr_reader :slug, :id
4
+ end
5
+ end
@@ -0,0 +1,179 @@
1
+ require "danger/ci_source/support/local_pull_request"
2
+ require "danger/ci_source/support/remote_pull_request"
3
+ require "danger/ci_source/support/no_pull_request"
4
+
5
+ module Danger
6
+ class PullRequestFinder
7
+ def initialize(specific_pull_request_id, repo_slug = nil, remote: false, git_logs: "", remote_url: "", env: nil)
8
+ @specific_pull_request_id = specific_pull_request_id
9
+ @git_logs = git_logs
10
+ @repo_slug = repo_slug
11
+ @remote = to_boolean(remote)
12
+ @remote_url = remote_url
13
+ @env = env
14
+ end
15
+
16
+ def call
17
+ check_if_any_pull_request!
18
+
19
+ pull_request
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :specific_pull_request_id, :git_logs, :repo_slug, :remote, :remote_url, :env
25
+
26
+ def to_boolean(maybe_string)
27
+ ["true", "1", "yes", "y", true].include?(maybe_string)
28
+ end
29
+
30
+ def check_if_any_pull_request!
31
+ unless pull_request.valid?
32
+ if !specific_pull_request_id.empty?
33
+ raise "Could not find the Pull Request (#{specific_pull_request_id}) inside the git history for this repo."
34
+ else
35
+ raise "No recent Pull Requests found for this repo, danger requires at least one Pull Request for the local mode.".freeze
36
+ end
37
+ end
38
+ end
39
+
40
+ # @return [String] Log line of most recent merged Pull Request
41
+ def pull_request
42
+ @pull_request ||= begin
43
+ return if pull_request_ref.empty?
44
+
45
+ if both_present?
46
+ LocalPullRequest.new(pick_the_most_recent_one_from_two_matches)
47
+ elsif only_merged_pull_request_present?
48
+ LocalPullRequest.new(most_recent_merged_pull_request)
49
+ elsif only_squash_and_merged_pull_request_present?
50
+ LocalPullRequest.new(most_recent_squash_and_merged_pull_request)
51
+ elsif remote && remote_pull_request
52
+ generate_remote_pull_request
53
+ else
54
+ NoPullRequest.new
55
+ end
56
+ end
57
+ end
58
+
59
+ # @return [String] "#42"
60
+ def pull_request_ref
61
+ !specific_pull_request_id.empty? ? "##{specific_pull_request_id}" : "#\\d+".freeze
62
+ end
63
+
64
+ def generate_remote_pull_request
65
+ scm_provider = find_scm_provider(remote_url)
66
+
67
+ case scm_provider
68
+ when :bitbucket_cloud
69
+ RemotePullRequest.new(
70
+ remote_pull_request[:id].to_s,
71
+ remote_pull_request[:source][:commit][:hash],
72
+ remote_pull_request[:destination][:commit][:hash]
73
+ )
74
+ when :bitbucket_server
75
+ RemotePullRequest.new(
76
+ remote_pull_request[:id].to_s,
77
+ remote_pull_request[:fromRef][:latestCommit],
78
+ remote_pull_request[:toRef][:latestCommit]
79
+ )
80
+ when :github
81
+ RemotePullRequest.new(
82
+ remote_pull_request.number.to_s,
83
+ remote_pull_request.head.sha,
84
+ remote_pull_request.base.sha
85
+ )
86
+ else
87
+ raise "SCM provider not supported: #{scm_provider}"
88
+ end
89
+ end
90
+
91
+ def remote_pull_request
92
+ @_remote_pull_request ||= begin
93
+ client.pull_request(repo_slug, specific_pull_request_id)
94
+ end
95
+ end
96
+
97
+ def both_present?
98
+ most_recent_merged_pull_request && most_recent_squash_and_merged_pull_request
99
+ end
100
+
101
+ # @return [String] Log line of format: "Merge pull request #42"
102
+ def most_recent_merged_pull_request
103
+ @most_recent_merged_pull_request ||= begin
104
+ git_logs.lines.grep(/Merge pull request #{pull_request_ref} from/)[0]
105
+ end
106
+ end
107
+
108
+ # @return [String] Log line of format: "description (#42)"
109
+ def most_recent_squash_and_merged_pull_request
110
+ @most_recent_squash_and_merged_pull_request ||= begin
111
+ git_logs.lines.grep(/\(#{pull_request_ref}\)/)[0]
112
+ end
113
+ end
114
+
115
+ def pick_the_most_recent_one_from_two_matches
116
+ merged_index = git_logs.lines.index(most_recent_merged_pull_request)
117
+ squash_and_merged_index = git_logs.lines.index(most_recent_squash_and_merged_pull_request)
118
+
119
+ if merged_index > squash_and_merged_index # smaller index is more recent
120
+ most_recent_squash_and_merged_pull_request
121
+ else
122
+ most_recent_merged_pull_request
123
+ end
124
+ end
125
+
126
+ def only_merged_pull_request_present?
127
+ return false if most_recent_squash_and_merged_pull_request
128
+
129
+ !most_recent_merged_pull_request.nil? && !most_recent_merged_pull_request.empty?
130
+ end
131
+
132
+ def only_squash_and_merged_pull_request_present?
133
+ return false if most_recent_merged_pull_request
134
+
135
+ !most_recent_squash_and_merged_pull_request.nil? && !most_recent_squash_and_merged_pull_request.empty?
136
+ end
137
+
138
+ def client
139
+ scm_provider = find_scm_provider(remote_url)
140
+
141
+ case scm_provider
142
+ when :bitbucket_cloud
143
+ require "danger/request_sources/bitbucket_cloud_api"
144
+ branch_name = ENV["DANGER_BITBUCKET_TARGET_BRANCH"] # Optional env variable (specifying the target branch) to help find the PR.
145
+ RequestSources::BitbucketCloudAPI.new(repo_slug, specific_pull_request_id, branch_name, env)
146
+
147
+ when :bitbucket_server
148
+ require "danger/request_sources/bitbucket_server_api"
149
+ project, slug = repo_slug.split("/")
150
+ RequestSources::BitbucketServerAPI.new(project, slug, specific_pull_request_id, env)
151
+
152
+ when :github
153
+ require "octokit"
154
+ Octokit::Client.new(access_token: ENV["DANGER_GITHUB_API_TOKEN"], api_endpoint: api_url)
155
+
156
+ else
157
+ raise "SCM provider not supported: #{scm_provider}"
158
+ end
159
+ end
160
+
161
+ def api_url
162
+ ENV.fetch("DANGER_GITHUB_API_HOST") do
163
+ ENV.fetch("DANGER_GITHUB_API_BASE_URL") do
164
+ "https://api.github.com/".freeze
165
+ end
166
+ end
167
+ end
168
+
169
+ def find_scm_provider(remote_url)
170
+ if remote_url =~ %r{/bitbucket.org/}
171
+ :bitbucket_cloud
172
+ elsif remote_url =~ %r{/pull-requests/}
173
+ :bitbucket_server
174
+ else
175
+ :github
176
+ end
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,15 @@
1
+ module Danger
2
+ class RemotePullRequest
3
+ attr_reader :pull_request_id, :sha, :head, :base
4
+
5
+ def initialize(pull_request_id, head, base)
6
+ @pull_request_id = pull_request_id
7
+ @head = head
8
+ @base = base
9
+ end
10
+
11
+ def valid?
12
+ pull_request_id && head && base
13
+ end
14
+ end
15
+ end