danger 8.2.1 → 8.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/danger/ci_source/azure_pipelines.rb +5 -1
  4. data/lib/danger/ci_source/buildkite.rb +1 -1
  5. data/lib/danger/ci_source/codefresh.rb +7 -13
  6. data/lib/danger/ci_source/codemagic.rb +58 -0
  7. data/lib/danger/ci_source/gitlab_ci.rb +18 -17
  8. data/lib/danger/ci_source/jenkins.rb +1 -1
  9. data/lib/danger/ci_source/local_git_repo.rb +29 -37
  10. data/lib/danger/ci_source/local_only_git_repo.rb +4 -8
  11. data/lib/danger/ci_source/support/commits.rb +14 -12
  12. data/lib/danger/ci_source/support/pull_request_finder.rb +43 -40
  13. data/lib/danger/ci_source/xcode_cloud.rb +38 -0
  14. data/lib/danger/commands/dangerfile/init.rb +1 -1
  15. data/lib/danger/commands/pr.rb +2 -1
  16. data/lib/danger/comment_generators/gitlab_inline.md.erb +2 -7
  17. data/lib/danger/comment_generators/vsts_inline.md.erb +17 -0
  18. data/lib/danger/danger_core/dangerfile.rb +15 -8
  19. data/lib/danger/danger_core/environment_manager.rb +2 -0
  20. data/lib/danger/danger_core/plugins/dangerfile_git_plugin.rb +1 -1
  21. data/lib/danger/danger_core/plugins/dangerfile_github_plugin.rb +8 -0
  22. data/lib/danger/danger_core/plugins/dangerfile_gitlab_plugin.rb +16 -0
  23. data/lib/danger/helpers/array_subclass.rb +2 -2
  24. data/lib/danger/helpers/comments_helper.rb +4 -3
  25. data/lib/danger/helpers/emoji_mapper.rb +1 -1
  26. data/lib/danger/plugin_support/plugin.rb +6 -2
  27. data/lib/danger/request_sources/bitbucket_cloud.rb +0 -1
  28. data/lib/danger/request_sources/bitbucket_cloud_api.rb +7 -6
  29. data/lib/danger/request_sources/bitbucket_server.rb +20 -16
  30. data/lib/danger/request_sources/bitbucket_server_api.rb +17 -9
  31. data/lib/danger/request_sources/code_insights_api.rb +2 -3
  32. data/lib/danger/request_sources/github/github.rb +30 -26
  33. data/lib/danger/request_sources/gitlab.rb +24 -24
  34. data/lib/danger/request_sources/local_only.rb +1 -2
  35. data/lib/danger/request_sources/request_source.rb +16 -4
  36. data/lib/danger/request_sources/vsts.rb +171 -9
  37. data/lib/danger/request_sources/vsts_api.rb +34 -3
  38. data/lib/danger/scm_source/git_repo.rb +2 -1
  39. data/lib/danger/version.rb +1 -1
  40. metadata +17 -8
@@ -49,22 +49,26 @@ module Danger
49
49
  # However, as we're using using them in the DSL, they won't
50
50
  # get method_missing called correctly without overriding them.
51
51
 
52
- def warn(*args, &blk)
53
- method_missing(:warn, *args, &blk)
52
+ def warn(*args, **kargs, &blk)
53
+ method_missing(:warn, *args, **kargs, &blk)
54
54
  end
55
55
 
56
- def fail(*args, &blk)
57
- method_missing(:fail, *args, &blk)
56
+ def fail(*args, **kargs, &blk)
57
+ method_missing(:fail, *args, **kargs, &blk)
58
58
  end
59
59
 
60
60
  # When an undefined method is called, we check to see if it's something
61
61
  # that the core DSLs have, then starts looking at plugins support.
62
62
 
63
63
  # rubocop:disable Style/MethodMissing
64
- def method_missing(method_sym, *arguments, &_block)
64
+ def method_missing(method_sym, *arguments, **keyword_arguments, &_block)
65
65
  @core_plugins.each do |plugin|
66
66
  if plugin.public_methods(false).include?(method_sym)
67
- return plugin.send(method_sym, *arguments)
67
+ if keyword_arguments.empty?
68
+ return plugin.send(method_sym, *arguments)
69
+ else
70
+ return plugin.send(method_sym, *arguments, **keyword_arguments)
71
+ end
68
72
  end
69
73
  end
70
74
  super
@@ -270,7 +274,7 @@ module Danger
270
274
  env.scm.diff_for_folder(".".freeze, from: base_branch, to: head_branch, lookup_top_level: true)
271
275
  end
272
276
 
273
- def run(base_branch, head_branch, dangerfile_path, danger_id, new_comment, remove_previous_comments)
277
+ def run(base_branch, head_branch, dangerfile_path, danger_id, new_comment, remove_previous_comments, report_results = true)
274
278
  # Setup internal state
275
279
  init_plugins
276
280
  env.fill_environment_vars
@@ -285,7 +289,7 @@ module Danger
285
289
  # Push results to the API
286
290
  # Pass along the details of the run to the request source
287
291
  # to send back to the code review site.
288
- post_results(danger_id, new_comment, remove_previous_comments) unless danger_id.nil?
292
+ post_results(danger_id, new_comment, remove_previous_comments) if report_results
289
293
 
290
294
  # Print results in the terminal
291
295
  print_results
@@ -331,6 +335,9 @@ module Danger
331
335
  end
332
336
 
333
337
  def post_exception(ex, danger_id, new_comment)
338
+ return if ENV["DANGER_DO_NOT_POST_INVALID_DANGERFILE_ERROR"]
339
+ return if danger_id.nil?
340
+
334
341
  env.request_source.update_pull_request!(
335
342
  danger_id: danger_id,
336
343
  new_comment: new_comment,
@@ -90,6 +90,8 @@ module Danger
90
90
  RequestSources::GitLab
91
91
  elsif repo_url =~ /bitbucket\.(org|com)/i
92
92
  RequestSources::BitbucketCloud
93
+ elsif repo_url =~ /dev\.azure\.com/i
94
+ RequestSources::VSTS
93
95
  end
94
96
  end
95
97
 
@@ -128,7 +128,7 @@ module Danger
128
128
  # @return [Git::Diff::DiffFile] from the gem `git`
129
129
  #
130
130
  def diff_for_file(file)
131
- (added_files + modified_files).include?(file) ? @git.diff[file] : nil
131
+ (added_files + modified_files + deleted_files).include?(file) ? @git.diff[file] : nil
132
132
  end
133
133
 
134
134
  # @!group Git Metadata
@@ -143,6 +143,14 @@ module Danger
143
143
  @github.issue_json["labels"].map { |l| l[:name] }
144
144
  end
145
145
 
146
+ # @!group PR Metadata
147
+ # Whether the PR is a Draft.
148
+ # @return [Boolean]
149
+ #
150
+ def pr_draft?
151
+ pr_json["draft"] == true
152
+ end
153
+
146
154
  # @!group PR Commit Metadata
147
155
  # The branch to which the PR is going to be merged into.
148
156
  # @return [String]
@@ -131,6 +131,22 @@ module Danger
131
131
  @gitlab.mr_diff
132
132
  end
133
133
 
134
+ # @!group MR Changes
135
+ # The array of changes
136
+ # @return [Array<Gitlab::ObjectifiedHash>]
137
+ #
138
+ def mr_changes
139
+ @gitlab.mr_changes.changes
140
+ end
141
+
142
+ # @!group MR Closes issues
143
+ # The array of issues that this MR closes
144
+ # @return [Array<Gitlab::ObjectifiedHash>]
145
+ #
146
+ def mr_closes_issues
147
+ @gitlab.mr_closes_issues
148
+ end
149
+
134
150
  # @!group MR Commit Metadata
135
151
  # The branch to which the MR is going to be merged into
136
152
  # @deprecated Please use {#branch_for_base} instead
@@ -19,8 +19,8 @@ module Danger
19
19
  respond_to_method(name, *args, &block)
20
20
  end
21
21
 
22
- def respond_to_missing?(name)
23
- __array__.respond_to?(name) || super
22
+ def respond_to_missing?(name, include_all)
23
+ __array__.respond_to?(name, include_all) || super
24
24
  end
25
25
 
26
26
  def to_a
@@ -24,7 +24,8 @@ module Danger
24
24
  # @param [Bool] Should hide any generated link created
25
25
  #
26
26
  # @return [String] The Markdown compatible link
27
- def markdown_link_to_message(message, _)
27
+ def markdown_link_to_message(message, hide_link)
28
+ return "" if hide_link
28
29
  "#{message.file}#L#{message.line}"
29
30
  end
30
31
 
@@ -147,8 +148,8 @@ module Danger
147
148
 
148
149
  def generate_description(warnings: nil, errors: nil, template: "github")
149
150
  emoji_mapper = EmojiMapper.new(template)
150
- if errors.empty? && warnings.empty?
151
- return "All green. #{random_compliment}"
151
+ if (errors.nil? || errors.empty?) && (warnings.nil? || warnings.empty?)
152
+ return ENV['DANGER_SUCCESS_MESSAGE'] || "All green. #{random_compliment}"
152
153
  else
153
154
  message = "#{emoji_mapper.map('warning')} "
154
155
  message += "#{'Error'.danger_pluralize(errors.count)}. " unless errors.empty?
@@ -10,7 +10,7 @@ module Danger
10
10
  "bitbucket_server" => {
11
11
  "no_entry_sign" => ":no_entry_sign:",
12
12
  "warning" => ":warning:",
13
- "book" => ":book:",
13
+ "book" => ":blue_book:",
14
14
  "white_check_mark" => ":white_check_mark:"
15
15
  }
16
16
  }.freeze
@@ -19,8 +19,12 @@ module Danger
19
19
  # We need to redirect the self calls to the Dangerfile
20
20
 
21
21
  # rubocop:disable Style/MethodMissing
22
- def method_missing(method_sym, *arguments, &block)
23
- @dangerfile.send(method_sym, *arguments, &block)
22
+ def method_missing(method_sym, *arguments, **keyword_arguments, &block)
23
+ if keyword_arguments.empty?
24
+ @dangerfile.send(method_sym, *arguments, &block)
25
+ else
26
+ @dangerfile.send(method_sym, *arguments, **keyword_arguments, &block)
27
+ end
24
28
  end
25
29
 
26
30
  def self.all_plugins
@@ -24,7 +24,6 @@ module Danger
24
24
 
25
25
  def initialize(ci_source, environment)
26
26
  self.ci_source = ci_source
27
- self.environment = environment
28
27
 
29
28
  @api = BitbucketCloudAPI.new(ci_source.repo_slug, ci_source.pull_request_id, nil, environment)
30
29
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
3
 
3
4
  require "danger/helpers/comments_helper"
@@ -32,9 +33,8 @@ module Danger
32
33
  def inspect
33
34
  inspected = super
34
35
 
35
- if @password
36
- inspected = inspected.sub! @password, "********".freeze
37
- end
36
+ inspected.gsub!(@password, "********") if @password
37
+ inspected.gsub!(@access_token, "********") if @access_token
38
38
 
39
39
  inspected
40
40
  end
@@ -95,12 +95,13 @@ module Danger
95
95
  "#{base_url(2)}/#{pull_request_id}"
96
96
  end
97
97
 
98
- def prs_api_endpoint(branch_name)
99
- "#{base_url(2)}?q=source.branch.name=\"#{branch_name}\""
98
+ def prs_api_url(branch_name)
99
+ encoded_branch_name = URI.encode_www_form_component(branch_name)
100
+ "#{base_url(2)}?q=source.branch.name=\"#{encoded_branch_name}\""
100
101
  end
101
102
 
102
103
  def fetch_pr_from_branch(branch_name)
103
- uri = URI(URI.escape(prs_api_endpoint(branch_name)))
104
+ uri = URI(prs_api_url(branch_name))
104
105
  fetch_json(uri)[:values][0][:id]
105
106
  end
106
107
 
@@ -20,16 +20,17 @@ module Danger
20
20
  end
21
21
 
22
22
  def self.optional_env_vars
23
- ["DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_KEY",
24
- "DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_TITLE",
25
- "DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_DESCRIPTION",
26
- "DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_LOGO_URL"
23
+ [
24
+ "DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_KEY",
25
+ "DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_TITLE",
26
+ "DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_DESCRIPTION",
27
+ "DANGER_BITBUCKETSERVER_CODE_INSIGHTS_REPORT_LOGO_URL",
28
+ "DANGER_BITBUCKETSERVER_VERIFY_SSL"
27
29
  ]
28
30
  end
29
31
 
30
32
  def initialize(ci_source, environment)
31
33
  self.ci_source = ci_source
32
- self.environment = environment
33
34
 
34
35
  project, slug = ci_source.repo_slug.split("/")
35
36
  @api = BitbucketServerAPI.new(project, slug, ci_source.pull_request_id, environment)
@@ -110,17 +111,20 @@ module Danger
110
111
  markdowns = main_violations[:markdowns] || []
111
112
  end
112
113
 
113
- comment = generate_description(warnings: warnings,
114
- errors: errors)
115
- comment += "\n\n"
116
- comment += generate_comment(warnings: warnings,
117
- errors: errors,
118
- messages: messages,
119
- markdowns: markdowns,
120
- previous_violations: {},
121
- danger_id: danger_id,
122
- template: "bitbucket_server")
123
- @api.post_comment(comment)
114
+ has_comments = (warnings.count > 0 || errors.count > 0 || messages.count > 0 || markdowns.count > 0)
115
+ if has_comments
116
+ comment = generate_description(warnings: warnings,
117
+ errors: errors)
118
+ comment += "\n\n"
119
+ comment += generate_comment(warnings: warnings,
120
+ errors: errors,
121
+ messages: messages,
122
+ markdowns: markdowns,
123
+ previous_violations: {},
124
+ danger_id: danger_id,
125
+ template: "bitbucket_server")
126
+ @api.post_comment(comment)
127
+ end
124
128
  end
125
129
 
126
130
  def delete_old_comments(danger_id: "danger")
@@ -1,16 +1,19 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
3
 
4
+ require "openssl"
3
5
  require "danger/helpers/comments_helper"
4
6
 
5
7
  module Danger
6
8
  module RequestSources
7
9
  class BitbucketServerAPI
8
- attr_accessor :host, :pr_api_endpoint, :key, :project
10
+ attr_accessor :host, :verify_ssl, :pr_api_endpoint, :key, :project
9
11
 
10
12
  def initialize(project, slug, pull_request_id, environment)
11
13
  @username = environment["DANGER_BITBUCKETSERVER_USERNAME"]
12
14
  @password = environment["DANGER_BITBUCKETSERVER_PASSWORD"]
13
15
  self.host = environment["DANGER_BITBUCKETSERVER_HOST"]
16
+ self.verify_ssl = environment["DANGER_BITBUCKETSERVER_VERIFY_SSL"] != "false"
14
17
  if self.host && !(self.host.include? "http://") && !(self.host.include? "https://")
15
18
  self.host = "https://" + self.host
16
19
  end
@@ -22,9 +25,7 @@ module Danger
22
25
  def inspect
23
26
  inspected = super
24
27
 
25
- if @password
26
- inspected = inspected.sub! @password, "********".freeze
27
- end
28
+ inspected.gsub!(@password, "********") if @password
28
29
 
29
30
  inspected
30
31
  end
@@ -57,7 +58,7 @@ module Danger
57
58
  body = { text: text }.to_json
58
59
  post(uri, body)
59
60
  end
60
-
61
+
61
62
  def update_pr_build_status(status, changeset, build_job_link, description)
62
63
  uri = URI("#{self.host}/rest/build-status/1.0/commits/#{changeset}")
63
64
  body = build_status_body(status, build_job_link, description)
@@ -73,7 +74,7 @@ module Danger
73
74
  def fetch_json(uri)
74
75
  req = Net::HTTP::Get.new(uri.request_uri, { "Content-Type" => "application/json" })
75
76
  req.basic_auth @username, @password
76
- res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: use_ssl) do |http|
77
+ res = http(uri).start do |http|
77
78
  http.request(req)
78
79
  end
79
80
  JSON.parse(res.body, symbolize_names: true)
@@ -84,7 +85,7 @@ module Danger
84
85
  req.basic_auth @username, @password
85
86
  req.body = body
86
87
 
87
- res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: use_ssl) do |http|
88
+ res = http(uri).start do |http|
88
89
  http.request(req)
89
90
  end
90
91
 
@@ -99,11 +100,18 @@ module Danger
99
100
  def delete(uri)
100
101
  req = Net::HTTP::Delete.new(uri.request_uri, { "Content-Type" => "application/json" })
101
102
  req.basic_auth @username, @password
102
- Net::HTTP.start(uri.hostname, uri.port, use_ssl: use_ssl) do |http|
103
+ http(uri).start do |http|
103
104
  http.request(req)
104
105
  end
105
106
  end
106
-
107
+
108
+ def http(uri)
109
+ http = Net::HTTP.new(uri.hostname, uri.port)
110
+ http.use_ssl = use_ssl
111
+ http.verify_mode = verify_ssl ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
112
+ http
113
+ end
114
+
107
115
  def build_status_body(status, build_job_link, description)
108
116
  body = Hash.new
109
117
  body["state"] = status
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  # coding: utf-8
2
3
 
3
4
  module Danger
@@ -26,9 +27,7 @@ module Danger
26
27
  def inspect
27
28
  inspected = super
28
29
 
29
- if @password
30
- inspected = inspected.sub! @password, "********".freeze
31
- end
30
+ inspected.gsub!(@password, "********") if @password
32
31
 
33
32
  inspected
34
33
  end
@@ -14,10 +14,10 @@ module Danger
14
14
  class GitHub < RequestSource
15
15
  include Danger::Helpers::CommentsHelper
16
16
 
17
- attr_accessor :pr_json, :issue_json, :support_tokenless_auth, :dismiss_out_of_range_messages
17
+ attr_accessor :pr_json, :issue_json, :use_local_git, :support_tokenless_auth, :dismiss_out_of_range_messages, :host, :api_url, :verify_ssl
18
18
 
19
19
  def self.env_vars
20
- ["DANGER_GITHUB_API_TOKEN"]
20
+ ["DANGER_GITHUB_API_TOKEN", "DANGER_GITHUB_BEARER_TOKEN"]
21
21
  end
22
22
 
23
23
  def self.optional_env_vars
@@ -26,11 +26,22 @@ module Danger
26
26
 
27
27
  def initialize(ci_source, environment)
28
28
  self.ci_source = ci_source
29
- self.environment = environment
29
+ self.use_local_git = environment["DANGER_USE_LOCAL_GIT"]
30
30
  self.support_tokenless_auth = false
31
31
  self.dismiss_out_of_range_messages = false
32
+ self.host = environment.fetch("DANGER_GITHUB_HOST", "github.com")
33
+ # `DANGER_GITHUB_API_HOST` is the old name kept for legacy reasons and
34
+ # backwards compatibility. `DANGER_GITHUB_API_BASE_URL` is the new
35
+ # correctly named variable.
36
+ self.api_url = environment.fetch("DANGER_GITHUB_API_HOST") do
37
+ environment.fetch("DANGER_GITHUB_API_BASE_URL") do
38
+ "https://api.github.com/".freeze
39
+ end
40
+ end
41
+ self.verify_ssl = environment["DANGER_OCTOKIT_VERIFY_SSL"] != "false"
32
42
 
33
- @token = @environment["DANGER_GITHUB_API_TOKEN"]
43
+ @access_token = environment["DANGER_GITHUB_API_TOKEN"]
44
+ @bearer_token = environment["DANGER_GITHUB_BEARER_TOKEN"]
34
45
  end
35
46
 
36
47
  def get_pr_from_branch(repo_name, branch_name, owner)
@@ -45,39 +56,24 @@ module Danger
45
56
  end
46
57
 
47
58
  def validates_as_api_source?
48
- (@token && !@token.empty?) || self.environment["DANGER_USE_LOCAL_GIT"]
59
+ valid_bearer_token? || valid_access_token? || use_local_git
49
60
  end
50
61
 
51
62
  def scm
52
63
  @scm ||= GitRepo.new
53
64
  end
54
65
 
55
- def host
56
- @host = @environment["DANGER_GITHUB_HOST"] || "github.com"
57
- end
58
-
59
- def verify_ssl
60
- @environment["DANGER_OCTOKIT_VERIFY_SSL"] == "false" ? false : true
61
- end
62
-
63
- # `DANGER_GITHUB_API_HOST` is the old name kept for legacy reasons and
64
- # backwards compatibility. `DANGER_GITHUB_API_BASE_URL` is the new
65
- # correctly named variable.
66
- def api_url
67
- @environment.fetch("DANGER_GITHUB_API_HOST") do
68
- @environment.fetch("DANGER_GITHUB_API_BASE_URL") do
69
- "https://api.github.com/".freeze
70
- end
71
- end
72
- end
73
-
74
66
  def client
75
- raise "No API token given, please provide one using `DANGER_GITHUB_API_TOKEN`" if !@token && !support_tokenless_auth
67
+ raise "No API token given, please provide one using `DANGER_GITHUB_API_TOKEN` or `DANGER_GITHUB_BEARER_TOKEN`" if !valid_access_token? && !valid_bearer_token? && !support_tokenless_auth
76
68
  @client ||= begin
77
69
  Octokit.configure do |config|
78
70
  config.connection_options[:ssl] = { verify: verify_ssl }
79
71
  end
80
- Octokit::Client.new(access_token: @token, auto_paginate: true, api_endpoint: api_url)
72
+ if valid_bearer_token?
73
+ Octokit::Client.new(bearer_token: @bearer_token, auto_paginate: true, api_endpoint: api_url)
74
+ elsif valid_access_token?
75
+ Octokit::Client.new(access_token: @access_token, auto_paginate: true, api_endpoint: api_url)
76
+ end
81
77
  end
82
78
  end
83
79
 
@@ -493,6 +489,14 @@ module Danger
493
489
 
494
490
  private
495
491
 
492
+ def valid_access_token?
493
+ @access_token && !@access_token.empty?
494
+ end
495
+
496
+ def valid_bearer_token?
497
+ @bearer_token && !@bearer_token.empty?
498
+ end
499
+
496
500
  def regular_violations_group(warnings: [], errors: [], messages: [], markdowns: [])
497
501
  {
498
502
  warnings: warnings.reject(&:inline?),
@@ -8,7 +8,7 @@ module Danger
8
8
  module RequestSources
9
9
  class GitLab < RequestSource
10
10
  include Danger::Helpers::CommentsHelper
11
- attr_accessor :mr_json, :commits_json, :dismiss_out_of_range_messages
11
+ attr_accessor :mr_json, :commits_json, :dismiss_out_of_range_messages, :endpoint, :host
12
12
 
13
13
  FIRST_GITLAB_GEM_WITH_VERSION_CHECK = Gem::Version.new("4.6.0")
14
14
  FIRST_VERSION_WITH_INLINE_COMMENTS = Gem::Version.new("10.8.0")
@@ -23,20 +23,19 @@ module Danger
23
23
 
24
24
  def initialize(ci_source, environment)
25
25
  self.ci_source = ci_source
26
- self.environment = environment
27
26
  self.dismiss_out_of_range_messages = false
28
-
29
- @token = @environment["DANGER_GITLAB_API_TOKEN"]
27
+ @endpoint = environment["DANGER_GITLAB_API_BASE_URL"] || environment.fetch("CI_API_V4_URL", "https://gitlab.com/api/v4")
28
+ @host = environment.fetch("DANGER_GITLAB_HOST", URI.parse(endpoint).host) || "gitlab.com"
29
+ @token = environment["DANGER_GITLAB_API_TOKEN"]
30
30
  end
31
31
 
32
32
  def client
33
- token = @environment["DANGER_GITLAB_API_TOKEN"]
34
- raise "No API token given, please provide one using `DANGER_GITLAB_API_TOKEN`" unless token
33
+ raise "No API token given, please provide one using `DANGER_GITLAB_API_TOKEN`" unless @token
35
34
 
36
35
  # The require happens inline so that it won't cause exceptions when just using the `danger` gem.
37
36
  require "gitlab"
38
37
 
39
- @client ||= Gitlab.client(endpoint: endpoint, private_token: token)
38
+ @client ||= Gitlab.client(endpoint: endpoint, private_token: @token)
40
39
  rescue LoadError => e
41
40
  if e.path == "gitlab"
42
41
  puts "The GitLab gem was not installed, you will need to change your Gem from `danger` to `danger-gitlab`.".red
@@ -48,7 +47,7 @@ module Danger
48
47
  end
49
48
 
50
49
  def validates_as_ci?
51
- includes_port = self.host.include? ":"
50
+ includes_port = host.include? ":"
52
51
  raise "Port number included in `DANGER_GITLAB_HOST`, this will fail with GitLab CI Runners" if includes_port
53
52
 
54
53
  # We don't call super because in some cases the Git remote doesn't match the GitLab instance host.
@@ -66,14 +65,6 @@ module Danger
66
65
  @scm ||= GitRepo.new
67
66
  end
68
67
 
69
- def endpoint
70
- @endpoint ||= @environment["DANGER_GITLAB_API_BASE_URL"] || @environment["CI_API_V4_URL"] || "https://gitlab.com/api/v4"
71
- end
72
-
73
- def host
74
- @host ||= @environment["DANGER_GITLAB_HOST"] || URI.parse(endpoint).host || "gitlab.com"
75
- end
76
-
77
68
  def base_commit
78
69
  @base_commit ||= self.mr_json.diff_refs.base_sha
79
70
  end
@@ -85,7 +76,7 @@ module Danger
85
76
  if supports_inline_comments
86
77
  @raw_comments = mr_discussions
87
78
  .auto_paginate
88
- .flat_map { |discussion| discussion.notes.map { |note| note.merge({"discussion_id" => discussion.id}) } }
79
+ .flat_map { |discussion| discussion.notes.map { |note| note.to_h.merge({"discussion_id" => discussion.id}) } }
89
80
  @raw_comments
90
81
  .map { |comment| Comment.from_gitlab(comment) }
91
82
  else
@@ -130,6 +121,12 @@ module Danger
130
121
  end
131
122
  end
132
123
 
124
+ def mr_closes_issues
125
+ @mr_closes_issues ||= begin
126
+ client.merge_request_closes_issues(ci_source.repo_slug, ci_source.pull_request_id)
127
+ end
128
+ end
129
+
133
130
  def setup_danger_branches
134
131
  # we can use a GitLab specific feature here:
135
132
  base_branch = self.mr_json.source_branch
@@ -298,6 +295,10 @@ module Danger
298
295
  end
299
296
  end
300
297
 
298
+ def markdown_link_to_message(message, _)
299
+ "#{message.file}#L#{message.line}: "
300
+ end
301
+
301
302
  # @return [String] The organisation name, is nil if it can't be detected
302
303
  def organisation
303
304
  nil # TODO: Implement this
@@ -316,11 +317,10 @@ module Danger
316
317
  # @return [String] A URL to the specific file, ready to be downloaded
317
318
  def file_url(organisation: nil, repository: nil, branch: nil, path: nil)
318
319
  branch ||= 'master'
319
- token = @environment["DANGER_GITLAB_API_TOKEN"]
320
320
  # According to GitLab Repositories API docs path and id(slug) should be encoded.
321
321
  path = URI.encode_www_form_component(path)
322
322
  repository = URI.encode_www_form_component(repository)
323
- "#{endpoint}/projects/#{repository}/repository/files/#{path}/raw?ref=#{branch}&private_token=#{token}"
323
+ "#{endpoint}/projects/#{repository}/repository/files/#{path}/raw?ref=#{branch}&private_token=#{@token}"
324
324
  end
325
325
 
326
326
  def regular_violations_group(warnings: [], errors: [], messages: [], markdowns: [])
@@ -359,7 +359,7 @@ module Danger
359
359
  def submit_inline_comments!(warnings: [], errors: [], messages: [], markdowns: [], previous_violations: [], danger_id: "danger")
360
360
  comments = mr_discussions
361
361
  .auto_paginate
362
- .flat_map { |discussion| discussion.notes.map { |note| note.merge({"discussion_id" => discussion.id}) } }
362
+ .flat_map { |discussion| discussion.notes.map { |note| note.to_h.merge({"discussion_id" => discussion.id}) } }
363
363
  .select { |comment| Comment.from_gitlab(comment).inline? }
364
364
 
365
365
  danger_comments = comments.select { |comment| Comment.from_gitlab(comment).generated_by_danger?(danger_id) }
@@ -410,7 +410,7 @@ module Danger
410
410
  next false unless m.file && m.line
411
411
  # Reject if it's out of range and in dismiss mode
412
412
  next true if dismiss_out_of_range_messages_for(kind) && is_out_of_range(mr_changes.changes, m)
413
-
413
+
414
414
  # Once we know we're gonna submit it, we format it
415
415
  if is_markdown_content
416
416
  body = generate_inline_markdown_body(m, danger_id: danger_id, template: "gitlab")
@@ -531,10 +531,10 @@ module Danger
531
531
  end
532
532
 
533
533
  def is_out_of_range(changes, message)
534
- change = changes.find { |c| c["new_path"] == message.file }
534
+ change = changes.find { |c| c["new_path"] == message.file }
535
535
  # If there is no changes or rename only or deleted, return out of range.
536
536
  return true if change.nil? || change["diff"].empty? || change["deleted_file"]
537
-
537
+
538
538
  # If new file then return in range
539
539
  return false if change["new_file"]
540
540
 
@@ -544,7 +544,7 @@ module Danger
544
544
  return true
545
545
  end
546
546
 
547
- def generate_addition_lines(diff)
547
+ def generate_addition_lines(diff)
548
548
  range_header_regexp = /@@ -(?<old>[0-9]+)(,([0-9]+))? \+(?<new>[0-9]+)(,([0-9]+))? @@.*/
549
549
  addition_lines = []
550
550
  line_number = 0
@@ -13,9 +13,8 @@ module Danger
13
13
  ["DANGER_LOCAL_ONLY"]
14
14
  end
15
15
 
16
- def initialize(ci_source, environment)
16
+ def initialize(ci_source, _environment)
17
17
  self.ci_source = ci_source
18
- self.environment = environment
19
18
  end
20
19
 
21
20
  def validates_as_ci?