-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(integrations): Add support for CODEOWNERS sections
Add option to use GitLab CODEOWNERS section syntax - by having one/multiple section owners. Fixes getsentry/sentry-docs#9565
- Loading branch information
1 parent
929e46f
commit 0d32bb3
Showing
4 changed files
with
173 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
import re | ||
|
||
|
||
class SectionLine: | ||
original_line: str | ||
path: str = "" | ||
is_preserved_comment: bool | ||
_path_owners: list[str] = [] | ||
_section_owners: list[str] = [] | ||
_has_valid_path: bool | ||
|
||
def __init__( | ||
self, | ||
original_line: str, | ||
path: str, | ||
path_owners: list[str], | ||
section_owners: list[str], | ||
): | ||
self.original_line = original_line | ||
self.path = path | ||
self.is_preserved_comment = original_line.startswith("#") or not len(original_line) | ||
self._path_owners = path_owners | ||
self._section_owners = section_owners | ||
self._has_valid_path = re.search(r"(\[([^]^\s]*)\])|[\s!#]", path) is None | ||
|
||
def get_dict_key(self) -> str: | ||
return self.path if self._has_valid_path else self.original_line | ||
|
||
def get_owners(self) -> list[str]: | ||
return self._path_owners if len(self._path_owners) > 0 else self._section_owners | ||
|
||
def should_skip(self) -> bool: | ||
if self.is_preserved_comment: | ||
return False | ||
|
||
if re.match(r"^\s*$", self.original_line): | ||
return True | ||
|
||
if not self._has_valid_path: | ||
return True | ||
|
||
return False |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,15 @@ | |
tests/file\ with\ spaces/ @NisanthanNanthakumar | ||
""" | ||
|
||
associations = { | ||
"@getsentry/frontend": "front-sentry", | ||
"@getsentry/docs": "docs-sentry", | ||
"@getsentry/ecosystem": "ecosystem", | ||
"@NisanthanNanthakumar": "[email protected]", | ||
"@AnotherUser": "[email protected]", | ||
"[email protected]": "[email protected]", | ||
} | ||
|
||
|
||
def test_parse_rules(): | ||
assert parse_rules(fixture_data) == [ | ||
|
@@ -920,20 +929,39 @@ def test_convert_codeowners_syntax(): | |
assert ( | ||
convert_codeowners_syntax( | ||
codeowners_fixture_data, | ||
{ | ||
"@getsentry/frontend": "front-sentry", | ||
"@getsentry/docs": "docs-sentry", | ||
"@getsentry/ecosystem": "ecosystem", | ||
"@NisanthanNanthakumar": "[email protected]", | ||
"@AnotherUser": "[email protected]", | ||
"[email protected]": "[email protected]", | ||
}, | ||
associations, | ||
code_mapping, | ||
) | ||
== "\n# cool stuff comment\ncodeowners:*.js front-sentry [email protected]\n# good comment\n\n\ncodeowners:webpack://docs/* docs-sentry ecosystem\ncodeowners:src/sentry/* [email protected]\ncodeowners:api/* [email protected]\n" | ||
) | ||
|
||
|
||
def test_convert_codeowners_multiple_sections_with_overrides(): | ||
code_mapping = type("", (), {})() | ||
code_mapping.stack_root = "" | ||
code_mapping.source_root = "" | ||
|
||
result = convert_codeowners_syntax( | ||
r""" | ||
/fileA.txt @getsentry/frontend | ||
[Docs] @getsentry/docs | ||
/fileC.txt | ||
[Some_Section] | ||
/fileD.txt @getsentry/docs | ||
/fileD.txt @getsentry/frontend | ||
""", | ||
associations, | ||
code_mapping, | ||
) | ||
|
||
assert ( | ||
result | ||
== "\ncodeowners:/fileA.txt front-sentry\n\ncodeowners:/fileC.txt docs-sentry\n\ncodeowners:/fileD.txt front-sentry\n" | ||
) | ||
|
||
|
||
def test_convert_codeowners_syntax_excludes_invalid(): | ||
code_mapping = type("", (), {})() | ||
code_mapping.stack_root = "webpack://static/" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
from sentry.ownership.section_line import SectionLine | ||
|
||
|
||
def test_get_owners_only_path_owners_returns_path_owners(): | ||
line = SectionLine("", "", ["a", "b"], []) | ||
assert line.get_owners() == ["a", "b"] | ||
|
||
|
||
def test_get_owners_only_section_owners_returns_section_owners(): | ||
line = SectionLine("", "", [], ["a", "b"]) | ||
assert line.get_owners() == ["a", "b"] | ||
|
||
|
||
def test_get_owners_both_owners_returns_path_owners(): | ||
line = SectionLine("", "", ["a", "b"], ["c", "d"]) | ||
assert line.get_owners() == ["a", "b"] | ||
|
||
|
||
def test_is_preserved_comment_empty_line_returns_true(): | ||
line = SectionLine("", "", [], []) | ||
assert line.is_preserved_comment is True | ||
|
||
|
||
def test_is_preserved_valid_comment_returns_true(): | ||
line = SectionLine("# some comment", "", [], []) | ||
assert line.is_preserved_comment is True | ||
|
||
|
||
def test_should_skip_valid_comment_returns_false(): | ||
line = SectionLine("# some comment", "", [], []) | ||
assert line.should_skip() is False | ||
|
||
|
||
def test_should_skip_line_with_spaces_returns_true(): | ||
line = SectionLine(" ", " ", [], []) | ||
assert line.should_skip() is True | ||
|
||
|
||
def test_should_skip_line_valid_path_returns_false(): | ||
line = SectionLine("/fileA.txt", "/fileA.txt", [], []) | ||
assert line.should_skip() is False | ||
|
||
|
||
def test_should_skip_line_invalid_path_returns_true(): | ||
line = SectionLine(" cde", " cde", [], []) | ||
assert line.should_skip() is True | ||
|
||
|
||
def test_get_dict_key_invalid_path_returns_original_line(): | ||
line = SectionLine("[Section] owner", "[Section]", [], []) | ||
assert line.get_dict_key() == "[Section] owner" | ||
|
||
|
||
def test_get_dict_key_returns_path_only(): | ||
line = SectionLine("/fileA.txt [email protected]", "/fileA.txt", [], []) | ||
assert line.get_dict_key() == "/fileA.txt" |