diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a617a99..2d35aaf 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -12,7 +12,9 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-python@v4 with: - python-version: "3.x" + # fixit 0.1.4 imports the stdlib ``distutils`` module, which was removed + # in Python 3.12. Pin to 3.11 until the fixit pin is upgraded. + python-version: "3.11" - uses: actions/cache@v3 with: path: | diff --git a/algorithms_keeper/parser/files_parser.py b/algorithms_keeper/parser/files_parser.py index f99da1a..4cb3f8e 100644 --- a/algorithms_keeper/parser/files_parser.py +++ b/algorithms_keeper/parser/files_parser.py @@ -23,6 +23,9 @@ class BaseFilesParser: DOCS_EXTENSIONS: Collection[str] = () ACCEPTED_EXTENSIONS: Collection[str] = () + # Extension-less filenames that are nonetheless valid (e.g. ``Dockerfile``). + ACCEPTED_FILENAMES: Collection[str] = () + def __init__( self, pr_files: Iterable[File], @@ -46,12 +49,15 @@ def validate_extension(self) -> str: `ACCEPTED_EXTENSIONS` constant. NOTE: Extensionless files will be considered valid only if it is present in - the ".github" directory. Eg: ".github/CODEOWNERS" + the ".github" directory (eg: ".github/CODEOWNERS") or if its name is listed in + ``ACCEPTED_FILENAMES`` (eg: "Dockerfile"). """ invalid_filepath = [] for file in self.pr_files: filepath = file.path if not filepath.suffix: + if filepath.name in self.ACCEPTED_FILENAMES: + continue if ".github" not in filepath.parts: if filepath.parent.name: # noqa: SIM114 invalid_filepath.append(file.name) diff --git a/algorithms_keeper/parser/python_parser.py b/algorithms_keeper/parser/python_parser.py index 61cebb9..6b44a23 100644 --- a/algorithms_keeper/parser/python_parser.py +++ b/algorithms_keeper/parser/python_parser.py @@ -72,11 +72,17 @@ class PythonParser(BaseFilesParser): ".csv", ".json", ".txt", + # Lock files (e.g. ``uv.lock``, ``poetry.lock``) are committed to keep CI + # reproducible; a transitive dependency bump lives only here, so allow it. + ".lock", # Good old Python file ".py", *DOCS_EXTENSIONS, ) + # Extension-less files whose exact name is accepted (container/build tooling). + ACCEPTED_FILENAMES: tuple[str, ...] = ("Dockerfile",) + def __init__( self, pr_files: Iterable[File], diff --git a/tests/test_parser.py b/tests/test_parser.py index 6cf830e..923c825 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -56,6 +56,11 @@ def test_contains_testfile(parser: PythonParser, expected: int) -> None: get_parser("test/test.html, test/test.cpp, test/test.py"), "test/test.html, test/test.cpp", ), + # Lock files are committed for reproducible CI, so they are valid. + (get_parser("uv.lock, sol1.py"), ""), + # ``Dockerfile`` is an accepted extension-less filename. + (get_parser("Dockerfile, sol1.py"), ""), + (get_parser(".devcontainer/Dockerfile"), ""), ), ) def test_validate_extension(parser: PythonParser, expected: str) -> None: