danger 8.2.1 → 8.6.1

Sign up to get free protection for your applications and to get access to all the features.
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?