Skip to content

Commit ab91bce

Browse files
perryqhschoblaska
andauthored
Fix regex chars in dir name (#91)
* add file to expanded cache if it exists * extracting OwnerAssigner for testing * fixing flake * commenting on the need for adding a file without a glob match Co-authored-by: Joey Schoblaska <[email protected]> * bumping version Co-authored-by: Perry Hertler <[email protected]> * ignoring Gemfile.lock * ignoring Gemfile.lock --------- Co-authored-by: Joey Schoblaska <[email protected]>
1 parent 941127e commit ab91bce

File tree

12 files changed

+180
-196
lines changed

12 files changed

+180
-196
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,7 @@
77
/spec/reports/
88
/tmp/
99

10+
Gemfile.lock
11+
1012
# rspec failure tracking
1113
.rspec_status

Gemfile.lock

Lines changed: 0 additions & 184 deletions
This file was deleted.

code_ownership.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Gem::Specification.new do |spec|
22
spec.name = 'code_ownership'
3-
spec.version = '1.36.1'
3+
spec.version = '1.36.2'
44
spec.authors = ['Gusto Engineers']
55
spec.email = ['[email protected]']
66
spec.summary = 'A gem to help engineering teams declare ownership of code'

lib/code_ownership/private.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
require 'code_ownership/private/codeowners_file'
99
require 'code_ownership/private/parse_js_packages'
1010
require 'code_ownership/private/glob_cache'
11+
require 'code_ownership/private/owner_assigner'
1112
require 'code_ownership/private/validations/files_have_owners'
1213
require 'code_ownership/private/validations/github_codeowners_up_to_date'
1314
require 'code_ownership/private/validations/files_have_unique_owners'
@@ -98,7 +99,6 @@ def self.file_tracked?(file)
9899
in_unowned_globs = configuration.unowned_globs.any? do |unowned_glob|
99100
File.fnmatch?(unowned_glob, file, File::FNM_PATHNAME | File::FNM_EXTGLOB)
100101
end
101-
102102
in_owned_globs && !in_unowned_globs && File.exist?(file)
103103
end
104104

lib/code_ownership/private/glob_cache.rb

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,8 @@ def expanded_cache
5353
@expanded_cache ||= begin
5454
expanded_cache = {}
5555
@raw_cache_contents.each do |mapper_description, globs_by_owner|
56-
expanded_cache[mapper_description] = {}
57-
globs_by_owner.each do |glob, owner|
58-
Dir.glob(glob).each do |file, owner|
59-
expanded_cache[mapper_description][file] = owner
60-
end
61-
end
56+
expanded_cache[mapper_description] = OwnerAssigner.assign_owners(globs_by_owner)
6257
end
63-
6458
expanded_cache
6559
end
6660
end
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
module CodeOwnership
5+
module Private
6+
class OwnerAssigner
7+
extend T::Sig
8+
9+
sig { params(globs_to_owning_team_map: GlobsToOwningTeamMap).returns(GlobsToOwningTeamMap) }
10+
def self.assign_owners(globs_to_owning_team_map)
11+
globs_to_owning_team_map.each_with_object({}) do |(glob, owner), mapping|
12+
# addresses the case where a directory name includes regex characters
13+
# such as `app/services/[test]/some_other_file.ts`
14+
mapping[glob] = owner if File.exist?(glob)
15+
Dir.glob(glob).each do |file|
16+
mapping[file] ||= owner
17+
end
18+
end
19+
end
20+
end
21+
end
22+
end
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
module CodeOwnership
2+
RSpec.describe Private::OwnerAssigner do
3+
describe '.assign_owners' do
4+
subject(:assign_owners) { described_class.assign_owners(globs_to_owning_team_map) }
5+
6+
let(:team_1) { instance_double(CodeTeams::Team) }
7+
let(:team_2) { instance_double(CodeTeams::Team) }
8+
9+
let(:globs_to_owning_team_map) do
10+
{
11+
'app/services/[test]/some_other_file.ts' => team_1,
12+
'app/services/withoutbracket/file.ts' => team_2,
13+
'app/models/*.rb' => team_2
14+
}
15+
end
16+
17+
before do
18+
write_file('app/services/[test]/some_other_file.ts', <<~YML)
19+
// @team Bar
20+
YML
21+
22+
write_file('app/services/withoutbracket/file.ts', <<~YML)
23+
// @team Bar
24+
YML
25+
end
26+
27+
it 'returns a hash with the same keys and the values that are files' do
28+
expect(assign_owners).to eq(
29+
'app/services/[test]/some_other_file.ts' => team_1,
30+
'app/services/withoutbracket/file.ts' => team_2
31+
)
32+
end
33+
34+
context 'when file name includes square brackets' do
35+
let(:globs_to_owning_team_map) do
36+
{
37+
'app/services/[test]/some_other_[test]_file.ts' => team_1,
38+
}
39+
end
40+
41+
before do
42+
write_file('app/services/[test]/some_other_[test]_file.ts', <<~YML)
43+
// @team Bar
44+
YML
45+
46+
write_file('app/services/t/some_other_e_file.ts', <<~YML)
47+
// @team Bar
48+
YML
49+
end
50+
51+
it 'matches the glob pattern' do
52+
expect(assign_owners).to eq(
53+
'app/services/[test]/some_other_[test]_file.ts' => team_1,
54+
'app/services/t/some_other_e_file.ts' => team_1
55+
)
56+
end
57+
end
58+
59+
context 'when glob pattern also exists' do
60+
before do
61+
write_file('app/services/t/some_other_file.ts', <<~YML)
62+
// @team Bar
63+
YML
64+
end
65+
66+
it 'also matches the glob pattern' do
67+
expect(assign_owners).to eq(
68+
'app/services/[test]/some_other_file.ts' => team_1,
69+
'app/services/t/some_other_file.ts' => team_1,
70+
'app/services/withoutbracket/file.ts' => team_2
71+
)
72+
end
73+
end
74+
75+
context 'when * is used in glob pattern' do
76+
before do
77+
write_file('app/models/some_file.rb', <<~YML)
78+
// @team Bar
79+
YML
80+
81+
write_file('app/models/nested/some_file.rb', <<~YML)
82+
// @team Bar
83+
YML
84+
end
85+
86+
it 'also matches the glob pattern' do
87+
expect(assign_owners).to eq(
88+
'app/services/[test]/some_other_file.ts' => team_1,
89+
'app/services/withoutbracket/file.ts' => team_2,
90+
'app/models/some_file.rb' => team_2
91+
)
92+
end
93+
end
94+
end
95+
end
96+
end

spec/lib/code_ownership/private/ownership_mappers/directory_ownership_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ module CodeOwnership
99
CONTENTS
1010
write_file('a/b/c/c_file.jsx')
1111
write_file('a/b/b_file.jsx')
12+
write_file('a/b/[test]/b_file.jsx')
1213
write_file('config/teams/bar.yml', <<~CONTENTS)
1314
name: Bar
1415
CONTENTS
@@ -24,6 +25,10 @@ module CodeOwnership
2425
expect(subject.map_file_to_owner('a/b/b_file.jsx').name).to eq 'Bar'
2526
end
2627

28+
it 'can find the owner of files containing [] dirs' do
29+
expect(subject.map_file_to_owner('a/b/[test]/b_file.jsx').name).to eq 'Bar'
30+
end
31+
2732
it 'can find the owner of files in a sub-directory of a team-owned directory' do
2833
expect(subject.map_file_to_owner('a/b/c/c_file.jsx').name).to eq 'Bar'
2934
end

spec/lib/code_ownership/private/ownership_mappers/js_package_ownership_spec.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,20 @@ module CodeOwnership
3838
}
3939
CONTENTS
4040
write_file('frontend/javascripts/packages/my_other_package/my_file.jsx')
41+
write_file('frontend/javascripts/packages/different_package/test/my_file.ts', <<~CONTENTS)
42+
// @team Bar
43+
CONTENTS
44+
write_file('frontend/javascripts/packages/different_package/[test]/my_file.ts', <<~CONTENTS)
45+
// @team Bar
46+
CONTENTS
4147
write_file('config/teams/bar.yml', <<~CONTENTS)
4248
name: Bar
4349
CONTENTS
4450
end
4551

4652
it 'can find the owner of files in team-owned javascript packages' do
4753
expect(CodeOwnership.for_file('frontend/javascripts/packages/my_other_package/my_file.jsx').name).to eq 'Bar'
54+
expect(CodeOwnership.for_file('frontend/javascripts/packages/different_package/[test]/my_file.ts').name).to eq 'Bar'
4855
end
4956
end
5057
end

0 commit comments

Comments
 (0)