Skip to content
This repository has been archived by the owner on Apr 4, 2024. It is now read-only.

Adding support for asterisk on CodeOwners #753

Merged
merged 5 commits into from
Sep 23, 2019
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 23 additions & 3 deletions lib/github/parse_owner.ex
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ defmodule BorsNG.CodeOwnerParser do
# Convert each file to an array of matching owners
pats = Enum.map(code_owners.patterns, fn owner ->
cond do
# glob matches has an extra '/' in it, don't match on it
String.equivalent?("*", owner.file_pattern) ->
owner.approvers
String.contains?(owner.file_pattern, "**") && process_double_asterisk(x.filename, owner.file_pattern) ->
owner.approvers
# glob matches has an extra '/' in it, don't match on it
:glob.matches(x.filename, owner.file_pattern) && !:glob.matches(x.filename, owner.file_pattern <> "/*") ->
owner.approvers
owner.approvers
String.starts_with?(x.filename, owner.file_pattern) ->
owner.approvers
true ->
Expand All @@ -56,14 +60,30 @@ defmodule BorsNG.CodeOwnerParser do
end
end)
end)

required_reviewers = Enum.filter(required_reviewers, fn x -> x != nil end)

Logger.debug("Required reviewers: #{inspect(required_reviewers)}")

required_reviewers
end

@spec process_double_asterisk(String.t, String.t) :: boolean
def process_double_asterisk(file_name, file_pattern) do
double_asterisk = "**"
cond do
String.starts_with?(file_pattern, double_asterisk) ->
pattern = String.trim_leading(file_pattern, double_asterisk)
String.contains?(file_name, pattern)
String.ends_with?(file_name, double_asterisk) ->
pattern = String.trim_leading(file_pattern, double_asterisk)
notriddle marked this conversation as resolved.
Show resolved Hide resolved
String.starts_with?(file_name, pattern)
String.contains?(file_pattern, double_asterisk) ->
patterns = String.split(file_pattern, double_asterisk, parts: 2)
String.starts_with?(file_name, List.first(patterns)) && String.contains?(file_name, List.last(patterns))
end
end

@spec parse_file(String.t) :: {:ok, %BorsNG.CodeOwners{}}
def parse_file(file_contents) do
# Empty codeowners file
Expand Down
75 changes: 74 additions & 1 deletion test/parse_owners_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,77 @@ defmodule BorsNG.ParseTest do
assert Enum.at(Enum.at(reviewers, 0), 0) == "@my_org/my_other_team"
end

end
test "Test Asterisk" do

IO.inspect(File.cwd())
{:ok, codeowner} = File.read("test/testdata/code_owners_6")

{:ok, owner_file} = BorsNG.CodeOwnerParser.parse_file(codeowner)

files = [%BorsNG.GitHub.File{
filename: "some_folder/some_file"
}]

reviewers = BorsNG.CodeOwnerParser.list_required_reviews(owner_file, files)

assert Enum.count(reviewers) == 1
assert Enum.count(Enum.at(reviewers, 0)) == 2
assert Enum.at(Enum.at(reviewers, 0), 0) == "@my_org/my_team"
assert Enum.at(Enum.at(reviewers, 0), 1) == "@my_org/my_other_team"
end

test "Test Double Asterisk in the middle" do

IO.inspect(File.cwd())
{:ok, codeowner} = File.read("test/testdata/code_owners_7")

{:ok, owner_file} = BorsNG.CodeOwnerParser.parse_file(codeowner)

files = [%BorsNG.GitHub.File{
filename: "src/file1/test"
}]

reviewers = BorsNG.CodeOwnerParser.list_required_reviews(owner_file, files)

assert Enum.count(reviewers) == 1
assert Enum.count(Enum.at(reviewers, 0)) == 1
assert Enum.at(Enum.at(reviewers, 0), 0) == "@my_org/test_team_2"
end

test "Test Double Asterisk in the beggining" do

IO.inspect(File.cwd())
{:ok, codeowner} = File.read("test/testdata/code_owners_7")

{:ok, owner_file} = BorsNG.CodeOwnerParser.parse_file(codeowner)

files = [%BorsNG.GitHub.File{
filename: "file0/file1/test"
}]

reviewers = BorsNG.CodeOwnerParser.list_required_reviews(owner_file, files)

assert Enum.count(reviewers) == 1
assert Enum.count(Enum.at(reviewers, 0)) == 1
assert Enum.at(Enum.at(reviewers, 0), 0) == "@my_org/test_team"
end

test "Test Double Asterisk in the end" do

IO.inspect(File.cwd())
{:ok, codeowner} = File.read("test/testdata/code_owners_7")

{:ok, owner_file} = BorsNG.CodeOwnerParser.parse_file(codeowner)

files = [%BorsNG.GitHub.File{
filename: "other/file1/file2"
}]

reviewers = BorsNG.CodeOwnerParser.list_required_reviews(owner_file, files)

assert Enum.count(reviewers) == 1
assert Enum.count(Enum.at(reviewers, 0)) == 1
assert Enum.at(Enum.at(reviewers, 0), 0) == "@my_org/other_team"
end

end
8 changes: 8 additions & 0 deletions test/testdata/code_owners_6
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence.
* @my_org/my_team @my_org/my_other_team

# The `docs/*` pattern will match files like
# `docs/getting-started.md` but not further nested files like
# `docs/build-app/troubleshooting.md`.
docs/* @my_org/another_team
21 changes: 21 additions & 0 deletions test/testdata/code_owners_7
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# The `docs/*` pattern will match files like
# `docs/getting-started.md` but not further nested files like
# `docs/build-app/troubleshooting.md`.
src/ @my_org/another_team

# A leading "**" followed by a slash means match in all directories.
# For example, "**/foo" matches file or directory "foo" anywhere,
# the same as pattern "foo". "**/foo/bar" matches file or directory "bar"
# anywhere that is directly under directory "foo".
**/test @my_org/test_team

# A trailing "/**" matches everything inside. For example, "abc/**"
# matches all files inside directory "abc", relative to the location of
# the .gitignore file, with infinite depth.
other/** @my_org/other_team

# A slash followed by two consecutive asterisks then a slash matches
# zero or more directories. For example, "a/**/b" matches "a/b", "a/x/b",
# "a/x/y/b" and so on.
src/**/core @my_org/core_team
src/**/test @my_org/test_team_2