diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 91ae912..a094600 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -44,7 +44,7 @@ jobs: with: retries: 1 # Retry once after initial attempt run: | - python -m pytest tests -v --cov=./ --cov-report=xml:coverage.xml + python -m pytest tests -v --cov=actions --cov-report=xml:coverage.xml - name: Run CLI tests run: | diff --git a/pyproject.toml b/pyproject.toml index c28918f..80a3c68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -104,6 +104,22 @@ version = { attr = "actions.__version__" } addopts = "--doctest-modules --durations=30 --color=yes" norecursedirs = [".git", "dist", "build"] +[tool.coverage.run] +omit = [ + "actions/dependabot.py", + "actions/first_interaction.py", + "actions/format_python_docstrings.py", + "actions/review_pr.py", + "actions/scan_prs.py", + "actions/summarize_pr.py", + "actions/summarize_release.py", + "actions/update_markdown_code_blocks.py", + "actions/utils/common_utils.py", + "actions/utils/github_utils.py", + "actions/utils/openai_utils.py", + "actions/utils/version_utils.py", +] + [tool.ruff] line-length = 120 diff --git a/tests/test_file_headers.py b/tests/test_file_headers.py index 95f80e7..6d8eec3 100644 --- a/tests/test_file_headers.py +++ b/tests/test_file_headers.py @@ -90,6 +90,21 @@ def test_update_file_no_changes(): assert result is False # No changes made +def test_update_file_edge_cases(): + """Test header handling for empty, unreadable, and block-comment files.""" + with TemporaryDirectory() as tmp_dir: + tmp_path = Path(tmp_dir) + empty_file = tmp_path / "empty.py" + empty_file.write_text("") + assert update_file(empty_file, "# ", None, None, "Ultralytics 🚀 Test Header") is False + assert update_file(tmp_path, "# ", None, None, "Ultralytics 🚀 Test Header") is False + + css_file = tmp_path / "style.css" + css_file.write_text("body { color: black; }\n") + assert update_file(css_file, None, "/* ", " */", "Ultralytics 🚀 Test Header") is True + assert css_file.read_text().startswith("/* Ultralytics 🚀 Test Header */\n\n") + + def test_comment_map_coverage(): """Test that all supported file extensions have defined comment styles.""" # Check for a few key extensions @@ -132,3 +147,44 @@ def test_main_with_custom_header(): mock_event.repository = "test/repo" main() mock_action.assert_called_once() + + +def test_main_private_and_skipped_repos(): + """Test main selects private headers and skips repos without a header source.""" + with TemporaryDirectory() as tmp_dir: + tmp_path = Path(tmp_dir) + (tmp_path / "app.py").write_text("print('hello')\n") + + with patch("actions.update_file_headers.Path.cwd", return_value=tmp_path): + with patch("actions.update_file_headers.update_file", return_value=False) as mock_update: + with patch("actions.update_file_headers.Action") as mock_action: + mock_event = mock_action.return_value + mock_event.repository = "ultralytics/private" + mock_event.is_repo_private.return_value = True + main() + assert any("CONFIDENTIAL" in call.args[4] for call in mock_update.call_args_list) + + with patch("actions.update_file_headers.update_file", return_value=False) as mock_update: + with patch("actions.update_file_headers.HEADER", None): + with patch("actions.update_file_headers.Action") as mock_action: + mock_action.return_value.repository = "other/repo" + main() + mock_action.return_value.is_repo_private.assert_not_called() + mock_update.assert_not_called() + + +def test_main_updates_files_in_current_directory(): + """Test main updates supported files under the current directory.""" + with TemporaryDirectory() as tmp_dir: + tmp_path = Path(tmp_dir) + test_file = tmp_path / "app.py" + test_file.write_text("print('hello')\n") + + with patch("actions.update_file_headers.Path.cwd", return_value=tmp_path): + with patch("actions.update_file_headers.Action") as mock_action: + mock_event = mock_action.return_value + mock_event.repository = "ultralytics/actions" + mock_event.is_repo_private.return_value = False + main() + + assert test_file.read_text().startswith("# Ultralytics 🚀 AGPL-3.0 License")