diff --git a/tests/conftest.py b/tests/conftest.py index 526d5eeb6..495d2fd54 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,8 @@ import logging import os +from pathlib import Path + +import pytest from tests.shared.codemod.models import Size @@ -74,3 +77,39 @@ def pytest_configure(config): filename=f"build/logs/tests_{worker_id}.log", level=config.getini("log_file_level"), ) + + +def is_git_lfs_pointer(file_path: Path) -> bool: + """Check if a file is a git LFS pointer file""" + try: + with open(file_path) as f: + first_line = f.readline().strip() + return first_line == "version https://git-lfs.github.com/spec/v1" + except Exception: + return False + + +@pytest.hookimpl(hookwrapper=True) +def pytest_runtest_makereport(item, call): + outcome = yield + report = outcome.get_result() + + if report.when == "call" and report.failed: + if "NodeJS or npm is not installed" in str(report.longrepr): + pytest.skip("Test requires NodeJS and npm to be installed") + + +@pytest.fixture(autouse=True) +def skip_lfs_tests(request): + """Skip tests that depend on git LFS files if they haven't been pulled""" + # Get the test module path + test_path = Path(request.module.__file__) + + # Only run for integration tests + if not str(test_path).startswith(str(Path.cwd() / "tests" / "integration")): + return + + # Get the expected diff path from the test's expected fixture + expected = request.getfixturevalue("expected") + if isinstance(expected, Path) and is_git_lfs_pointer(expected): + pytest.skip(f"Test requires git LFS file {expected} which hasn't been pulled") diff --git a/tests/integration/codemod/conftest.py b/tests/integration/codemod/conftest.py index 33363c3a9..84ff4df0b 100644 --- a/tests/integration/codemod/conftest.py +++ b/tests/integration/codemod/conftest.py @@ -141,6 +141,10 @@ def token(request): def op(repo: Repo, token: str | None) -> YieldFixture[LocalRepoOperator]: with filelock.FileLock(BASE_TMP_DIR / "locks" / repo.name): op = repo.to_op(repo.name, token) + if isinstance(op, tuple): + # This means we got (None, error_message) + _, msg = op + pytest.skip(msg or "Could not create repo operator") yield op diff --git a/tests/shared/codemod/models.py b/tests/shared/codemod/models.py index 35106d27b..62f028fcf 100644 --- a/tests/shared/codemod/models.py +++ b/tests/shared/codemod/models.py @@ -60,17 +60,23 @@ class Repo(BaseModel): def from_json(cls, json_str: str) -> "Repo": return cls.model_validate(json.loads(json_str)) - def to_op(self, name: str, token: str | None) -> LocalRepoOperator: + def to_op(self, name: str, token: str | None) -> LocalRepoOperator | tuple[None, str | None]: base_path = BASE_TMP_DIR / ("extra_repos" if self.extra_repo else "oss_repos") / name base_path.mkdir(exist_ok=True, parents=True) url = self.url if token: url = url.replace("://", f"://{token}@") elif self.repo_id is not None: - print("Setting up auth using the github cli") + # TODO: this is a very messy hack to check whether we should prompt the user for auth + # if REPO_ID_TO_URL is not set, we probably don't need auth. this is assuming that for + # OSS repos, we don't need to pull any private repos. + if not REPO_ID_TO_URL: + return (None, "Could not create repo operator - skipping test") + if not which("gh"): - os.system("brew install gh") + return (None, "GitHub CLI (gh) is not installed. Please install it first. Skipping test.") if '[credential "https://github.codegen.app"]' not in (Path.home() / ".gitconfig").read_text(): + print("Setting up auth using the github cli") os.system("gh auth login -h github.codegen.app") os.system("gh auth setup-git -h github.codegen.app") return LocalRepoOperator.create_from_commit(str(base_path), self.default_branch, self.commit, url) diff --git a/uv.lock b/uv.lock index fd229456f..d7df49d4c 100644 --- a/uv.lock +++ b/uv.lock @@ -358,7 +358,7 @@ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593 } wheels = [ @@ -2554,7 +2554,7 @@ name = "tqdm" version = "4.67.1" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "colorama", marker = "platform_system == 'Windows'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a8/4b/29b4ef32e036bb34e4ab51796dd745cdba7ed47ad142a9f4a1eb8e0c744d/tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2", size = 169737 } wheels = [