Skip to content

Commit a818f6f

Browse files
committed
test(downstream): cover SWE-bench cloning across Git storage formats
SWE-bench is a current high-download GitPython user, but its latest 5.0.2 release has no tests for the GitPython inference helpers and no matching Git release tag. Retrieve the verified PyPI source and explicitly document that this profile runs a GitPython-authored supplemental integration test, rather than misrepresent unrelated upstream tests as compatibility coverage. Import the real `AutoContextManager` with only its required `chardet` and GitPython dependencies. Exercise clone, commit checkout, reset, untracked cleanup, directory restoration, and clone reuse for SHA-1/SHA-256 with files/reftable. Route its normal URL to a local fixture and permit only file transport during the test. Do not patch production modules or mock GitPython. BM25's Java/Pyserini helpers remain outside this focused check. Add the profile to the local runner and CI. Expand pytest-option paths, cut off unrelated ancestor conftests, and use importlib mode so the supplemental filename cannot shadow the installed upstream package. All four cases pass through the shared runner on Python 3.12 and Git 2.54; they also passed separately on minimum Git 2.52. Ruff and whitespace checks pass. No GitPython compatibility changes were required.
1 parent 39ec26e commit a818f6f

5 files changed

Lines changed: 106 additions & 2 deletions

File tree

‎.github/workflows/downstream.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
project: [langchain, mlflow, bandit]
19+
project: [langchain, mlflow, bandit, swebench]
2020
steps:
2121
- uses: actions/checkout@v7
2222
with:

‎test/downstream/README.md‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ and test-only dependencies are excluded. Downloads are not unique installations.
3333
| LangChain Community | 27,882,881 | 0.4.2 | 2 upstream GitLoader tests: real clones, commits, checkout, tree traversal, ignored paths, and remote validation |
3434
| MLflow (`mlflow-skinny`) | 25,850,354 | 3.16.1 | 47 upstream tests: 31 repository/project/model-versioning cases plus 16 Git context and credential-redaction contract cases |
3535
| Bandit | 24,935,372 | 1.9.4 | 12 upstream baseline CLI tests: real repository creation, commits, branches, resets, discovery, and dirty state |
36+
| SWE-bench | 22,942,741 | 5.0.2 | 4 supplemental integration cases for `AutoContextManager`; no upstream tests cover its GitPython callers |
3637

3738
Source: [top-pypi-packages](https://hugovk.github.io/top-pypi-packages/top-pypi-packages.min.json),
3839
snapshot updated **2026-10-01 12:40:51 UTC**. Its
@@ -61,6 +62,20 @@ upstream autouse fixtures otherwise build wheels and modify conda environments.
6162
No model downloads, cloud credentials, or external tracking server are needed.
6263
CLI examples that train models or need private SSH credentials are excluded.
6364

65+
SWE-bench 5.0.2 ships no upstream tests for its GitPython inference helpers and
66+
has no corresponding Git release tag. Its profile installs the verified PyPI
67+
source archive without unrelated ML dependencies, then imports the real upstream
68+
`AutoContextManager` with `chardet` and GitPython. Our explicitly labeled
69+
[supplemental check](checks/swebench.py) exercises local cloning, commit checkout,
70+
reset, untracked-file cleanup, directory restoration, and clone reuse across
71+
SHA-1/SHA-256 and files/reftable. Git URL rewriting routes the ordinary upstream
72+
URL to a local fixture; `GIT_ALLOW_PROTOCOL=file` prevents network access during
73+
the test. No upstream code, imported modules, or GitPython calls are mocked.
74+
The separate BM25 retrieval helpers require Java/Pyserini and are not covered.
75+
The supplemental filename is intentionally excluded from GitPython's normal test
76+
collection; the runner selects it explicitly with importlib mode to avoid
77+
shadowing the upstream `swebench` package.
78+
6479
CI runs the same command against the latest release and fails when no test passes,
6580
including when all selected tests are skipped. Test dependency ranges only supply
6681
the upstream test harness; they do not pin the dependent's release.

‎test/downstream/checks/swebench.py‎

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"""Supplemental checks: SWE-bench 5.0.2 ships no tests for its GitPython callers.
2+
3+
Import the ordinary upstream utility module. The minimal environment only needs
4+
chardet and GitPython; no SWE-bench code or imported module is replaced.
5+
"""
6+
7+
import subprocess
8+
from pathlib import Path
9+
10+
import pytest
11+
from git import Repo
12+
from swebench.inference.make_datasets.utils import (
13+
AutoContextManager,
14+
ingest_directory_contents,
15+
)
16+
17+
18+
@pytest.mark.parametrize("object_format", ["sha1", "sha256"])
19+
@pytest.mark.parametrize("ref_format", ["files", "reftable"])
20+
def test_auto_context_manager_clones_and_resets(tmp_path, monkeypatch, object_format, ref_format):
21+
"""Clone, revisit commits and reuse the checkout with real GitPython."""
22+
origin = tmp_path / "origin"
23+
origin.mkdir()
24+
config = tmp_path / "gitconfig"
25+
config.write_text("[user]\n name = GitPython Compatibility\n email = tests@example.invalid\n")
26+
monkeypatch.setenv("GIT_CONFIG_GLOBAL", str(config))
27+
monkeypatch.setenv("GIT_CONFIG_NOSYSTEM", "1")
28+
monkeypatch.setenv("GIT_DEFAULT_REF_FORMAT", ref_format)
29+
monkeypatch.setenv("GIT_ALLOW_PROTOCOL", "file")
30+
monkeypatch.setenv("GIT_TERMINAL_PROMPT", "0")
31+
32+
def git(*args):
33+
return subprocess.run(
34+
["git", "-C", str(origin), *args], check=True, text=True, capture_output=True
35+
).stdout.strip()
36+
37+
git("init", "-b", "main", f"--object-format={object_format}", f"--ref-format={ref_format}")
38+
(origin / "README.md").write_text("Local fixture\n")
39+
(origin / "module.py").write_text("value = 1\n")
40+
git("add", "--", "README.md", "module.py")
41+
git("commit", "-m", "initial")
42+
first_commit = git("rev-parse", "HEAD")
43+
(origin / "module.py").write_text("value = 2\n")
44+
git("commit", "-am", "second")
45+
second_commit = git("rev-parse", "HEAD")
46+
47+
# Preserve SWE-bench's ordinary HTTPS URL construction while routing the
48+
# transport to our local fixture. No network access or credentials are used.
49+
git(
50+
"config",
51+
"--global",
52+
f"url.{origin.as_uri()}.insteadOf",
53+
"https://gitpython-tests@github.com/swe-bench-repos/fixture__project.git",
54+
)
55+
git("config", "--global", "protocol.file.allow", "always")
56+
root = tmp_path / "checkouts"
57+
root.mkdir()
58+
instance = {"repo": "fixture/project", "base_commit": first_commit}
59+
original_cwd = Path.cwd()
60+
manager = AutoContextManager(instance, root_dir=str(root), token="gitpython-tests")
61+
checkout = Path(manager.repo_path)
62+
with manager as context:
63+
assert Path.cwd() == checkout
64+
assert context.get_readme_files() == ["README.md"]
65+
assert ingest_directory_contents(checkout, include_tests=True) == {"module.py": "value = 1\n"}
66+
with Repo(checkout) as repo:
67+
assert repo.head.commit.hexsha == first_commit
68+
assert repo.git.rev_parse("--show-object-format") == object_format
69+
assert repo.git.rev_parse("--show-ref-format") == ref_format
70+
assert Path.cwd() == original_cwd
71+
72+
# Reuse the local clone even when its source no longer exists. Reset must
73+
# remove both modified tracked contents and untracked files from a prior run.
74+
origin.rename(tmp_path / "unavailable-origin")
75+
(checkout / "module.py").write_text("dirty = True\n")
76+
(checkout / "untracked.py").write_text("untracked = True\n")
77+
instance["base_commit"] = second_commit
78+
with AutoContextManager(instance, root_dir=str(root), token="gitpython-tests") as context:
79+
assert Path(context.repo_path) == checkout
80+
assert ingest_directory_contents(checkout, include_tests=True) == {"module.py": "value = 2\n"}
81+
assert Path.cwd() == original_cwd

‎test/downstream/projects.json‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,13 @@
4141
"source": "sdist",
4242
"install": ["{source}[baseline]", "pytest", "fixtures", "testtools"],
4343
"tests": ["tests/unit/cli/test_baseline.py"]
44+
},
45+
"swebench": {
46+
"distribution": "swebench",
47+
"source": "sdist",
48+
"install": ["chardet", "pytest"],
49+
"no_deps": ["{source}"],
50+
"pytest_args": ["--confcutdir={checks}", "--import-mode=importlib"],
51+
"tests": ["{checks}/swebench.py"]
4452
}
4553
}

‎test/downstream/run.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ def expand(value):
157157
report = work / "junit.xml"
158158
# Bandit's CLI tests inspect sys.argv and reserve the short spelling `-o`.
159159
command = [str(python), "-m", "pytest", "-q", "--override-ini=addopts=", "--tb=short", f"--junitxml={report}"]
160-
command += list(map(expand, profile["tests"])) + profile.get("pytest_args", [])
160+
command += list(map(expand, profile["tests"] + profile.get("pytest_args", [])))
161161
completed = run(command, cwd=source / profile.get("cwd", ""), env=env, check=False)
162162
result["exit_code"] = completed.returncode
163163
if report.exists():

0 commit comments

Comments
 (0)