Skip to content

Commit 30148a2

Browse files
authored
Fix: Handle renamed files in package_todo.yml validation (#59)
1 parent 3f208c1 commit 30148a2

File tree

2 files changed

+112
-2
lines changed

2 files changed

+112
-2
lines changed

lib/danger-packwerk/private/todo_yml_changes.rb

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,23 @@ def self.get_reference_offenses(violation_types, git_filesystem)
3333
renamed_files_before = git_filesystem.renamed_files.map { |before_after_file| before_after_file[:before] }
3434
renamed_files_after = git_filesystem.renamed_files.map { |before_after_file| before_after_file[:after] }
3535

36+
# Build a rename mapping to normalize file paths when comparing violations
37+
rename_mapping = build_rename_mapping(git_filesystem.renamed_files)
38+
3639
git_filesystem.modified_files.grep(PACKAGE_TODO_PATTERN).each do |modified_package_todo_yml_file|
3740
# We skip over modified files if one of the modified files is a renamed `package_todo.yml` file.
3841
# This allows us to rename packs while ignoring "new violations" in those renamed packs.
3942
next if renamed_files_before.include?(modified_package_todo_yml_file)
4043

4144
head_commit_violations = BasicReferenceOffense.from(modified_package_todo_yml_file)
4245
base_commit_violations = get_violations_before_patch_for(git_filesystem, modified_package_todo_yml_file)
43-
added_violations += head_commit_violations - base_commit_violations
44-
removed_violations += base_commit_violations - head_commit_violations
46+
47+
# Normalize violations for renames: update old file paths to new file paths
48+
# so that violations referring to renamed files are properly matched
49+
normalized_base_violations = normalize_violations_for_renames(base_commit_violations, rename_mapping)
50+
51+
added_violations += head_commit_violations - normalized_base_violations
52+
removed_violations += normalized_base_violations - head_commit_violations
4553
end
4654

4755
#
@@ -78,6 +86,40 @@ def self.get_reference_offenses(violation_types, git_filesystem)
7886
[relevant_added_violations, relevant_removed_violations]
7987
end
8088

89+
sig do
90+
params(
91+
renamed_files: T::Array[{ after: String, before: String }]
92+
).returns(T::Hash[String, String])
93+
end
94+
def self.build_rename_mapping(renamed_files)
95+
renamed_files.each_with_object({}) do |rename, mapping|
96+
mapping[rename[:before]] = rename[:after]
97+
end
98+
end
99+
100+
sig do
101+
params(
102+
violations: T::Array[BasicReferenceOffense],
103+
rename_mapping: T::Hash[String, String]
104+
).returns(T::Array[BasicReferenceOffense])
105+
end
106+
def self.normalize_violations_for_renames(violations, rename_mapping)
107+
violations.map do |violation|
108+
file = rename_mapping[violation.file]
109+
next violation unless file
110+
111+
# Create a new violation with the updated file path
112+
BasicReferenceOffense.new(
113+
class_name: violation.class_name,
114+
file: file,
115+
to_package_name: violation.to_package_name,
116+
from_package_name: violation.from_package_name,
117+
type: violation.type,
118+
file_location: violation.file_location
119+
)
120+
end
121+
end
122+
81123
sig do
82124
params(
83125
git_filesystem: GitFilesystem,

spec/danger_packwerk/danger_package_todo_yml_changes_spec.rb

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,74 @@ def format_offenses(added_violations, repo_link, org_name, repo_url_builder: nil
914914
subject
915915
expect(dangerfile).to produce_no_danger_messages
916916
end
917+
918+
it 'correctly normalizes file paths when comparing violations' do
919+
expect(slack_notifier).to receive(:notify_slack).with(
920+
{ dependency: { minus: 0, plus: 0 }, privacy: { minus: 0, plus: 0 } },
921+
['packs/some_pack/package_todo.yml']
922+
)
923+
subject
924+
end
925+
end
926+
927+
context 'a package_todo.yml file has been modified with multiple files that have been renamed' do
928+
let(:renamed_files) do
929+
[
930+
{
931+
after: 'packs/some_pack/some_class_with_new_name.rb',
932+
before: 'packs/some_pack/some_class_with_old_name.rb'
933+
},
934+
{
935+
after: 'packs/some_pack/another_renamed_class.rb',
936+
before: 'packs/some_pack/another_old_name.rb'
937+
}
938+
]
939+
end
940+
941+
let(:modified_files) do
942+
[
943+
write_file('packs/some_pack/package_todo.yml', <<~YML.strip)
944+
---
945+
packs/some_other_pack:
946+
"OtherPackClass":
947+
violations:
948+
- privacy
949+
files:
950+
- packs/some_pack/some_class_with_new_name.rb
951+
- packs/some_pack/another_renamed_class.rb
952+
YML
953+
]
954+
end
955+
956+
let(:some_pack_package_todo_before) do
957+
write_file('packs/some_pack/package_todo.yml', <<~YML.strip)
958+
---
959+
packs/some_other_pack:
960+
"OtherPackClass":
961+
violations:
962+
- privacy
963+
files:
964+
- packs/some_pack/some_class_with_old_name.rb
965+
- packs/some_pack/another_old_name.rb
966+
YML
967+
end
968+
969+
before do
970+
['packs/some_pack/another_renamed_class.rb', 'packs/some_pack/another_old_name.rb'].each { |path| write_file(path) }
971+
end
972+
973+
it 'does not display a markdown message' do
974+
subject
975+
expect(dangerfile).to produce_no_danger_messages
976+
end
977+
978+
it 'correctly normalizes all renamed file paths when comparing violations' do
979+
expect(slack_notifier).to receive(:notify_slack).with(
980+
{ dependency: { minus: 0, plus: 0 }, privacy: { minus: 0, plus: 0 } },
981+
['packs/some_pack/package_todo.yml']
982+
)
983+
subject
984+
end
917985
end
918986

919987
context 'a package_todo.yml file has been modified with files that have been renamed AND been added' do

0 commit comments

Comments
 (0)