Browse Source

feat(codeowners): Support escaping spaces in filenames (#33386)

NisanthanNanthakumar 2 years ago
parent
commit
d9978fbe02
2 changed files with 12 additions and 4 deletions
  1. 9 2
      src/sentry/ownership/grammar.py
  2. 3 2
      tests/sentry/ownership/test_grammar.py

+ 9 - 2
src/sentry/ownership/grammar.py

@@ -379,7 +379,7 @@ def parse_code_owners(data: str) -> Tuple[List[str], List[str], List[str]]:
         if rule.startswith("#") or not len(rule):
             continue
 
-        assignees = rule.strip().split()[1:]
+        _, assignees = get_codeowners_path_and_owners(rule)
         for assignee in assignees:
             if "/" not in assignee:
                 if re.match(r"[^@]+@[^@]+\.[^@]+", assignee):
@@ -393,6 +393,13 @@ def parse_code_owners(data: str) -> Tuple[List[str], List[str], List[str]]:
     return teams, usernames, emails
 
 
+def get_codeowners_path_and_owners(rule):
+    # Regex does a negative lookbehind for a backslash. Matches on whitespace without a preceding backslash.
+    pattern = re.compile(r"(?<!\\)\s")
+    path, *code_owners = (i for i in pattern.split(rule.strip()) if i)
+    return path, code_owners
+
+
 def convert_codeowners_syntax(codeowners, associations, code_mapping):
     """Converts CODEOWNERS text into IssueOwner syntax
     codeowners: CODEOWNERS text
@@ -408,7 +415,7 @@ def convert_codeowners_syntax(codeowners, associations, code_mapping):
             result += f"{rule}\n"
             continue
 
-        path, *code_owners = (x.strip() for x in rule.split())
+        path, code_owners = get_codeowners_path_and_owners(rule)
         # Escape invalid paths https://docs.github.com/en/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-code-owners#syntax-exceptions
         # Check if path has whitespace
         # Check if path has '#' not as first character

+ 3 - 2
tests/sentry/ownership/test_grammar.py

@@ -31,7 +31,7 @@ codeowners:/src/components/  githubuser@sentry.io
 codeowners:frontend/*.ts     githubmod@sentry.io
 """
 
-codeowners_fixture_data = """
+codeowners_fixture_data = r"""
 # cool stuff comment
 *.js                    @getsentry/frontend @NisanthanNanthakumar
 # good comment
@@ -40,6 +40,7 @@ codeowners_fixture_data = """
   docs/*  @getsentry/docs @getsentry/ecosystem
 src/sentry/*       @AnotherUser
 api/*    nisanthan.nanthakumar@sentry.io
+tests/file\ with\ spaces/ @NisanthanNanthakumar
 """
 
 
@@ -563,7 +564,7 @@ def test_codeowners_match_fowardslash(path_details, expected):
 def test_parse_code_owners():
     assert parse_code_owners(codeowners_fixture_data) == (
         ["@getsentry/frontend", "@getsentry/docs", "@getsentry/ecosystem"],
-        ["@NisanthanNanthakumar", "@AnotherUser"],
+        ["@NisanthanNanthakumar", "@AnotherUser", "@NisanthanNanthakumar"],
         ["nisanthan.nanthakumar@sentry.io"],
     )