gitlab-dangerfiles 0.8.1 → 2.0.0
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/.yardopts +5 -0
- data/Gemfile +1 -0
- data/LICENSE.txt +1 -1
- data/README.md +46 -6
- data/gitlab-dangerfiles.gemspec +4 -4
- data/lib/danger/plugins/helper.rb +417 -0
- data/lib/danger/{roulette.rb → plugins/roulette.rb} +83 -64
- data/lib/danger/rules/changes_size/Dangerfile +10 -0
- data/lib/gitlab/dangerfiles.rb +81 -2
- data/lib/gitlab/dangerfiles/changes.rb +22 -0
- data/lib/gitlab/dangerfiles/commit_linter.rb +1 -1
- data/lib/gitlab/dangerfiles/config.rb +17 -0
- data/lib/gitlab/dangerfiles/emoji_checker.rb +1 -0
- data/lib/gitlab/dangerfiles/spec_helper.rb +51 -5
- data/lib/gitlab/dangerfiles/teammate.rb +2 -0
- data/lib/gitlab/dangerfiles/version.rb +1 -1
- data/lib/gitlab/dangerfiles/weightage.rb +1 -0
- data/lib/gitlab/dangerfiles/weightage/maintainers.rb +1 -0
- data/lib/gitlab/dangerfiles/weightage/reviewers.rb +1 -0
- metadata +12 -9
- data/lib/danger/helper.rb +0 -257
@@ -1,9 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "
|
4
|
-
require_relative "
|
5
|
-
require_relative "
|
6
|
-
require_relative "../gitlab/dangerfiles/weightage/reviewers"
|
3
|
+
require_relative "../../gitlab/dangerfiles/teammate"
|
4
|
+
require_relative "../../gitlab/dangerfiles/weightage/maintainers"
|
5
|
+
require_relative "../../gitlab/dangerfiles/weightage/reviewers"
|
7
6
|
|
8
7
|
module Danger
|
9
8
|
# Common helper functions for our danger scripts. See Danger::Helper
|
@@ -17,16 +16,24 @@ module Danger
|
|
17
16
|
}.freeze
|
18
17
|
|
19
18
|
Spin = Struct.new(:category, :reviewer, :maintainer, :optional_role, :timezone_experiment)
|
19
|
+
HTTPError = Class.new(StandardError)
|
20
20
|
|
21
|
+
# Finds the +Gitlab::Dangerfiles::Teammate+ object whose username matches the MR author username.
|
22
|
+
#
|
23
|
+
# @return [Gitlab::Dangerfiles::Teammate]
|
21
24
|
def team_mr_author
|
22
|
-
|
25
|
+
company_members.find { |person| person.username == helper.mr_author }
|
23
26
|
end
|
24
27
|
|
25
28
|
# Assigns GitLab team members to be reviewer and maintainer
|
26
|
-
# for
|
29
|
+
# for the given +categories+.
|
30
|
+
#
|
31
|
+
# @param project [String] A project path.
|
32
|
+
# @param categories [Array<Symbol>] An array of categories symbols.
|
33
|
+
# @param timezone_experiment [Boolean] Whether to select reviewers based in timezone or not.
|
27
34
|
#
|
28
35
|
# @return [Array<Spin>]
|
29
|
-
def spin(project, categories, timezone_experiment: false)
|
36
|
+
def spin(project, categories = [nil], timezone_experiment: false)
|
30
37
|
spins = categories.sort.map do |category|
|
31
38
|
including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(category, timezone_experiment)
|
32
39
|
|
@@ -34,6 +41,7 @@ module Danger
|
|
34
41
|
end
|
35
42
|
|
36
43
|
backend_spin = spins.find { |spin| spin.category == :backend }
|
44
|
+
frontend_spin = spins.find { |spin| spin.category == :frontend }
|
37
45
|
|
38
46
|
spins.each do |spin|
|
39
47
|
including_timezone = INCLUDE_TIMEZONE_FOR_CATEGORY.fetch(spin.category, timezone_experiment)
|
@@ -60,81 +68,37 @@ module Danger
|
|
60
68
|
# Fetch an already picked backend maintainer, or pick one otherwise
|
61
69
|
spin.maintainer = backend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
|
62
70
|
end
|
71
|
+
when :product_intelligence
|
72
|
+
spin.optional_role = :maintainer
|
73
|
+
|
74
|
+
if spin.maintainer.nil?
|
75
|
+
# Fetch an already picked maintainer, or pick one otherwise
|
76
|
+
spin.maintainer = backend_spin&.maintainer || frontend_spin&.maintainer || spin_for_category(project, :backend, timezone_experiment: including_timezone).maintainer
|
77
|
+
end
|
63
78
|
end
|
64
79
|
end
|
65
80
|
|
66
81
|
spins
|
67
82
|
end
|
68
83
|
|
69
|
-
# Looks up the current list of GitLab team members and parses it into a
|
70
|
-
# useful form
|
71
|
-
#
|
72
|
-
# @return [Array<Teammate>]
|
73
|
-
def team
|
74
|
-
@team ||= begin
|
75
|
-
data = helper.http_get_json(ROULETTE_DATA_URL)
|
76
|
-
data.map { |hash| Gitlab::Dangerfiles::Teammate.new(hash) }
|
77
|
-
rescue JSON::ParserError
|
78
|
-
raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
# Like +team+, but only returns teammates in the current project, based on
|
83
|
-
# project_name.
|
84
|
-
#
|
85
|
-
# @return [Array<Teammate>]
|
86
|
-
def project_team(project_name)
|
87
|
-
team.select { |member| member.in_project?(project_name) }
|
88
|
-
rescue => err
|
89
|
-
warn("Reviewer roulette failed to load team data: #{err.message}")
|
90
|
-
[]
|
91
|
-
end
|
92
|
-
|
93
|
-
# Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
|
94
|
-
# selection will change on next spin
|
95
|
-
# @param [Array<Teammate>] people
|
96
|
-
def spin_for_person(people, random:, timezone_experiment: false)
|
97
|
-
shuffled_people = people.shuffle(random: random)
|
98
|
-
|
99
|
-
if timezone_experiment
|
100
|
-
shuffled_people.find(&method(:valid_person_with_timezone?))
|
101
|
-
else
|
102
|
-
shuffled_people.find(&method(:valid_person?))
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
84
|
private
|
107
85
|
|
108
|
-
# @param [Teammate] person
|
86
|
+
# @param [Gitlab::Dangerfiles::Teammate] person
|
109
87
|
# @return [Boolean]
|
110
88
|
def valid_person?(person)
|
111
89
|
!mr_author?(person) && person.available
|
112
90
|
end
|
113
91
|
|
114
|
-
# @param [Teammate] person
|
92
|
+
# @param [Gitlab::Dangerfiles::Teammate] person
|
115
93
|
# @return [Boolean]
|
116
94
|
def valid_person_with_timezone?(person)
|
117
95
|
valid_person?(person) && HOURS_WHEN_PERSON_CAN_BE_PICKED.cover?(person.local_hour)
|
118
96
|
end
|
119
97
|
|
120
|
-
# @param [Teammate] person
|
98
|
+
# @param [Gitlab::Dangerfiles::Teammate] person
|
121
99
|
# @return [Boolean]
|
122
100
|
def mr_author?(person)
|
123
|
-
person.username ==
|
124
|
-
end
|
125
|
-
|
126
|
-
def mr_author_username
|
127
|
-
helper.gitlab_helper&.mr_author || `whoami`
|
128
|
-
end
|
129
|
-
|
130
|
-
def mr_source_branch
|
131
|
-
return `git rev-parse --abbrev-ref HEAD` unless helper.gitlab_helper&.mr_json
|
132
|
-
|
133
|
-
helper.gitlab_helper.mr_json["source_branch"]
|
134
|
-
end
|
135
|
-
|
136
|
-
def mr_labels
|
137
|
-
helper.gitlab_helper&.mr_labels || []
|
101
|
+
person.username == helper.mr_author
|
138
102
|
end
|
139
103
|
|
140
104
|
def new_random(seed)
|
@@ -143,7 +107,23 @@ module Danger
|
|
143
107
|
|
144
108
|
def spin_role_for_category(team, role, project, category)
|
145
109
|
team.select do |member|
|
146
|
-
member.public_send("#{role}?", project, category, mr_labels) # rubocop:disable GitlabSecurity/PublicSend
|
110
|
+
member.public_send("#{role}?", project, category, helper.mr_labels) # rubocop:disable GitlabSecurity/PublicSend
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Known issue: If someone is rejected due to OOO, and then becomes not OOO, the
|
115
|
+
# selection will change on next spin.
|
116
|
+
#
|
117
|
+
# @param [Array<Gitlab::Dangerfiles::Teammate>] people
|
118
|
+
#
|
119
|
+
# @return [Gitlab::Dangerfiles::Teammate]
|
120
|
+
def spin_for_person(people, random:, timezone_experiment: false)
|
121
|
+
shuffled_people = people.shuffle(random: random)
|
122
|
+
|
123
|
+
if timezone_experiment
|
124
|
+
shuffled_people.find(&method(:valid_person_with_timezone?))
|
125
|
+
else
|
126
|
+
shuffled_people.find(&method(:valid_person?))
|
147
127
|
end
|
148
128
|
end
|
149
129
|
|
@@ -154,7 +134,7 @@ module Danger
|
|
154
134
|
spin_role_for_category(team, role, project, category)
|
155
135
|
end
|
156
136
|
|
157
|
-
random = new_random(mr_source_branch)
|
137
|
+
random = new_random(helper.mr_source_branch)
|
158
138
|
|
159
139
|
weighted_reviewers = Gitlab::Dangerfiles::Weightage::Reviewers.new(reviewers, traintainers).execute
|
160
140
|
weighted_maintainers = Gitlab::Dangerfiles::Weightage::Maintainers.new(maintainers).execute
|
@@ -164,5 +144,44 @@ module Danger
|
|
164
144
|
|
165
145
|
Spin.new(category, reviewer, maintainer, false, timezone_experiment)
|
166
146
|
end
|
147
|
+
|
148
|
+
# Fetches the given +url+ and parse its response as JSON.
|
149
|
+
#
|
150
|
+
# @param [String] url
|
151
|
+
#
|
152
|
+
# @return [Hash, Array]
|
153
|
+
def http_get_json(url)
|
154
|
+
rsp = Net::HTTP.get_response(URI.parse(url))
|
155
|
+
|
156
|
+
unless rsp.is_a?(Net::HTTPOK)
|
157
|
+
raise HTTPError, "Failed to read #{url}: #{rsp.code} #{rsp.message}"
|
158
|
+
end
|
159
|
+
|
160
|
+
JSON.parse(rsp.body)
|
161
|
+
end
|
162
|
+
|
163
|
+
# Looks up the current list of GitLab team members and parses it into a
|
164
|
+
# useful form.
|
165
|
+
#
|
166
|
+
# @return [Array<Gitlab::Dangerfiles::Teammate>]
|
167
|
+
def company_members
|
168
|
+
@company_members ||= begin
|
169
|
+
data = http_get_json(ROULETTE_DATA_URL)
|
170
|
+
data.map { |hash| Gitlab::Dangerfiles::Teammate.new(hash) }
|
171
|
+
rescue JSON::ParserError
|
172
|
+
raise "Failed to parse JSON response from #{ROULETTE_DATA_URL}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Like +team+, but only returns teammates in the current project, based on
|
177
|
+
# project_name.
|
178
|
+
#
|
179
|
+
# @return [Array<Gitlab::Dangerfiles::Teammate>]
|
180
|
+
def project_team(project_name)
|
181
|
+
company_members.select { |member| member.in_project?(project_name) }
|
182
|
+
rescue => err
|
183
|
+
warn("Reviewer roulette failed to load team data: #{err.message}")
|
184
|
+
[]
|
185
|
+
end
|
167
186
|
end
|
168
187
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
thresholds = helper.config.code_size_thresholds
|
4
|
+
lines_changed = git.lines_of_code
|
5
|
+
|
6
|
+
if lines_changed > thresholds[:high]
|
7
|
+
warn "This merge request is definitely too big (#{lines_changed} lines changed), please split it into multiple merge requests."
|
8
|
+
elsif lines_changed > thresholds[:medium]
|
9
|
+
warn "This merge request is quite big (#{lines_changed} lines changed), please consider splitting it into multiple merge requests."
|
10
|
+
end
|
data/lib/gitlab/dangerfiles.rb
CHANGED
@@ -2,8 +2,87 @@ require "gitlab/dangerfiles/version"
|
|
2
2
|
|
3
3
|
module Gitlab
|
4
4
|
module Dangerfiles
|
5
|
-
|
6
|
-
|
5
|
+
RULES_DIR = File.expand_path("../danger/rules", __dir__)
|
6
|
+
EXISTING_RULES = Dir.glob(File.join(RULES_DIR, "*")).each_with_object([]) do |path, memo|
|
7
|
+
if File.directory?(path)
|
8
|
+
memo << File.basename(path)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
LOCAL_RULES = %w[
|
12
|
+
changes_size
|
13
|
+
].freeze
|
14
|
+
CI_ONLY_RULES = %w[
|
15
|
+
].freeze
|
16
|
+
|
17
|
+
# This class provides utility methods to import plugins and dangerfiles easily.
|
18
|
+
class Engine
|
19
|
+
# @param dangerfile [Danger::Dangerfile] A +Danger::Dangerfile+ object.
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# # In your main Dangerfile:
|
23
|
+
# dangerfiles = Gitlab::Dangerfiles::Engine.new(self)
|
24
|
+
#
|
25
|
+
# @return [Gitlab::Dangerfiles::Engine]
|
26
|
+
def initialize(dangerfile)
|
27
|
+
@dangerfile = dangerfile
|
28
|
+
end
|
29
|
+
|
30
|
+
# Import all available plugins.
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# # In your main Dangerfile:
|
34
|
+
# dangerfiles = Gitlab::Dangerfiles::Engine.new(self)
|
35
|
+
#
|
36
|
+
# # Import all plugins
|
37
|
+
# dangerfiles.import_plugins
|
38
|
+
def import_plugins
|
39
|
+
danger_plugin.import_plugin(File.expand_path("../danger/plugins/*.rb", __dir__))
|
40
|
+
end
|
41
|
+
|
42
|
+
# Import available Dangerfiles.
|
43
|
+
#
|
44
|
+
# @param rules [Symbol, Array<String>] Can be either +:all+ (default) to import all rules,
|
45
|
+
# or an array of rules.
|
46
|
+
# Available rules are: +changes_size+.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# # In your main Dangerfile:
|
50
|
+
# dangerfiles = Gitlab::Dangerfiles::Engine.new(self)
|
51
|
+
#
|
52
|
+
# # Import all rules
|
53
|
+
# dangerfiles.import_dangerfiles
|
54
|
+
#
|
55
|
+
# # Or import only a subset of rules
|
56
|
+
# dangerfiles.import_dangerfiles(rules: %w[changes_size])
|
57
|
+
def import_dangerfiles(rules: :all)
|
58
|
+
filtered_rules(rules).each do |rule|
|
59
|
+
danger_plugin.import_dangerfile(path: File.join(RULES_DIR, rule))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
attr_reader :dangerfile
|
66
|
+
|
67
|
+
def allowed_rules
|
68
|
+
return LOCAL_RULES unless helper_plugin.respond_to?(:ci?)
|
69
|
+
|
70
|
+
helper_plugin.ci? ? LOCAL_RULES | CI_ONLY_RULES : LOCAL_RULES
|
71
|
+
end
|
72
|
+
|
73
|
+
def filtered_rules(rules)
|
74
|
+
rules = EXISTING_RULES if rules == :all
|
75
|
+
|
76
|
+
Array(rules).map(&:to_s) & EXISTING_RULES & allowed_rules
|
77
|
+
end
|
78
|
+
|
79
|
+
def danger_plugin
|
80
|
+
@danger_plugin ||= dangerfile.plugins[Danger::DangerfileDangerPlugin]
|
81
|
+
end
|
82
|
+
|
83
|
+
def helper_plugin
|
84
|
+
@helper_plugin ||= dangerfile.plugins[Danger::Helper]
|
85
|
+
end
|
7
86
|
end
|
8
87
|
end
|
9
88
|
end
|
@@ -4,41 +4,63 @@ require_relative "title_linting"
|
|
4
4
|
|
5
5
|
module Gitlab
|
6
6
|
module Dangerfiles
|
7
|
+
# @!attribute file
|
8
|
+
# @return [String] the file name that's changed.
|
9
|
+
# @!attribute change_type
|
10
|
+
# @return [Symbol] the type of change (+:added+, +:modified+, +:deleted+, +:renamed_before+, +:renamed_after+).
|
11
|
+
# @!attribute category
|
12
|
+
# @return [Symbol] the category of the change.
|
13
|
+
# This is defined by consumers of the gem through +helper.changes_by_category+ or +helper.changes+.
|
7
14
|
Change = Struct.new(:file, :change_type, :category)
|
8
15
|
|
9
16
|
class Changes < ::SimpleDelegator
|
17
|
+
# Return an +Gitlab::Dangerfiles::Changes+ object with only the changes for the added files.
|
18
|
+
#
|
19
|
+
# @return [Gitlab::Dangerfiles::Changes]
|
10
20
|
def added
|
11
21
|
select_by_change_type(:added)
|
12
22
|
end
|
13
23
|
|
24
|
+
# @return [Gitlab::Dangerfiles::Changes] the changes for the modified files.
|
14
25
|
def modified
|
15
26
|
select_by_change_type(:modified)
|
16
27
|
end
|
17
28
|
|
29
|
+
# @return [Gitlab::Dangerfiles::Changes] the changes for the deleted files.
|
18
30
|
def deleted
|
19
31
|
select_by_change_type(:deleted)
|
20
32
|
end
|
21
33
|
|
34
|
+
# @return [Gitlab::Dangerfiles::Changes] the changes for the renamed files (before the rename).
|
22
35
|
def renamed_before
|
23
36
|
select_by_change_type(:renamed_before)
|
24
37
|
end
|
25
38
|
|
39
|
+
# @return [Gitlab::Dangerfiles::Changes] the changes for the renamed files (after the rename).
|
26
40
|
def renamed_after
|
27
41
|
select_by_change_type(:renamed_after)
|
28
42
|
end
|
29
43
|
|
44
|
+
# @param category [Symbol] A category of change.
|
45
|
+
#
|
46
|
+
# @return [Boolean] whether there are any change for the given +category+.
|
30
47
|
def has_category?(category)
|
31
48
|
any? { |change| change.category == category }
|
32
49
|
end
|
33
50
|
|
51
|
+
# @param category [Symbol] a category of change.
|
52
|
+
#
|
53
|
+
# @return [Gitlab::Dangerfiles::Changes] changes for the given +category+.
|
34
54
|
def by_category(category)
|
35
55
|
Changes.new(select { |change| change.category == category })
|
36
56
|
end
|
37
57
|
|
58
|
+
# @return [Array<Symbol>] an array of the unique categories of changes.
|
38
59
|
def categories
|
39
60
|
map(&:category).uniq
|
40
61
|
end
|
41
62
|
|
63
|
+
# @return [Array<String>] an array of the changed files.
|
42
64
|
def files
|
43
65
|
map(&:file)
|
44
66
|
end
|
@@ -15,7 +15,7 @@ module Gitlab
|
|
15
15
|
{
|
16
16
|
separator_missing: "The commit subject and body must be separated by a blank line",
|
17
17
|
details_too_many_changes: "Commits that change #{MAX_CHANGED_LINES_IN_COMMIT} or more lines across " \
|
18
|
-
"at least #{MAX_CHANGED_FILES_IN_COMMIT} files
|
18
|
+
"at least #{MAX_CHANGED_FILES_IN_COMMIT} files should describe these changes in the commit body",
|
19
19
|
details_line_too_long: "The commit body should not contain more than #{MAX_LINE_LENGTH} characters per line",
|
20
20
|
message_contains_text_emoji: "Avoid the use of Markdown Emoji such as `:+1:`. These add limited value " \
|
21
21
|
"to the commit message, and are displayed as plain text outside of GitLab",
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitlab
|
4
|
+
module Dangerfiles
|
5
|
+
class Config
|
6
|
+
# @!attribute code_size_thresholds
|
7
|
+
# @return [{ high: Integer, medium: Integer }] a hash of the form +{ high: 42, medium: 12 }+ where +:high+ is the lines changed threshold which triggers an error, and +:medium+ is the lines changed threshold which triggers a warning. Also, see +DEFAULT_CHANGES_SIZE_THRESHOLDS+ for the format of the hash.
|
8
|
+
attr_accessor :code_size_thresholds
|
9
|
+
|
10
|
+
DEFAULT_CHANGES_SIZE_THRESHOLDS = { high: 2_000, medium: 500 }.freeze
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@code_size_thresholds = DEFAULT_CHANGES_SIZE_THRESHOLDS
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -45,17 +45,63 @@ end
|
|
45
45
|
|
46
46
|
RSpec.shared_context "with dangerfile" do
|
47
47
|
let(:dangerfile) { DangerSpecHelper.testing_dangerfile }
|
48
|
-
let(:added_files) { %w[
|
49
|
-
let(:modified_files) { %w[
|
50
|
-
let(:deleted_files) { %w[
|
51
|
-
let(:renamed_before_file) { "renamed_before" }
|
52
|
-
let(:renamed_after_file) { "renamed_after" }
|
48
|
+
let(:added_files) { %w[added-from-git] }
|
49
|
+
let(:modified_files) { %w[modified-from-git] }
|
50
|
+
let(:deleted_files) { %w[deleted-from-git] }
|
51
|
+
let(:renamed_before_file) { "renamed_before-from-git" }
|
52
|
+
let(:renamed_after_file) { "renamed_after-from-git" }
|
53
53
|
let(:renamed_files) { [{ before: renamed_before_file, after: renamed_after_file }] }
|
54
54
|
let(:change_class) { Gitlab::Dangerfiles::Change }
|
55
55
|
let(:changes_class) { Gitlab::Dangerfiles::Changes }
|
56
56
|
let(:changes) { changes_class.new([]) }
|
57
57
|
let(:mr_title) { "Fake Title" }
|
58
58
|
let(:mr_labels) { [] }
|
59
|
+
let(:mr_changes_from_api) do
|
60
|
+
{
|
61
|
+
"changes" => [
|
62
|
+
{
|
63
|
+
"old_path" => "added-from-api",
|
64
|
+
"new_path" => "added-from-api",
|
65
|
+
"a_mode" => "100644",
|
66
|
+
"b_mode" => "100644",
|
67
|
+
"new_file" => true,
|
68
|
+
"renamed_file" => false,
|
69
|
+
"deleted_file" => false,
|
70
|
+
"diff" => "@@ -49,6 +49,14 @@\n- vendor/ruby/\n policy: pull\n \n+.danger-review-cache:\n",
|
71
|
+
},
|
72
|
+
{
|
73
|
+
"old_path" => "modified-from-api",
|
74
|
+
"new_path" => "modified-from-api",
|
75
|
+
"a_mode" => "100644",
|
76
|
+
"b_mode" => "100644",
|
77
|
+
"new_file" => false,
|
78
|
+
"renamed_file" => false,
|
79
|
+
"deleted_file" => false,
|
80
|
+
"diff" => "@@ -49,6 +49,14 @@\n- vendor/ruby/\n policy: pull\n \n+.danger-review-cache:\n",
|
81
|
+
},
|
82
|
+
{
|
83
|
+
"old_path" => "renamed_before-from-api",
|
84
|
+
"new_path" => "renamed_after-from-api",
|
85
|
+
"a_mode" => "100644",
|
86
|
+
"b_mode" => "100644",
|
87
|
+
"new_file" => false,
|
88
|
+
"renamed_file" => true,
|
89
|
+
"deleted_file" => false,
|
90
|
+
"diff" => "@@ -49,6 +49,14 @@\n- vendor/ruby/\n policy: pull\n \n+.danger-review-cache:\n",
|
91
|
+
},
|
92
|
+
{
|
93
|
+
"old_path" => "deleted-from-api",
|
94
|
+
"new_path" => "deleted-from-api",
|
95
|
+
"a_mode" => "100644",
|
96
|
+
"b_mode" => "100644",
|
97
|
+
"new_file" => false,
|
98
|
+
"renamed_file" => false,
|
99
|
+
"deleted_file" => true,
|
100
|
+
"diff" => "@@ -49,6 +49,14 @@\n- vendor/ruby/\n policy: pull\n \n+.danger-review-cache:\n",
|
101
|
+
},
|
102
|
+
],
|
103
|
+
}
|
104
|
+
end
|
59
105
|
|
60
106
|
let(:fake_git) { double("fake-git", added_files: added_files, modified_files: modified_files, deleted_files: deleted_files, renamed_files: renamed_files) }
|
61
107
|
let(:fake_helper) { double("fake-helper", changes: changes, mr_iid: 1234, mr_title: mr_title, mr_labels: mr_labels) }
|