Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions tests/fixture_git.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""The one git identity every test repository commits under, given to each command.

No test writes identity or signing into a repository's config. When GIT_DIR leaks in
(``git bisect run`` from a linked worktree, a hook), ``git config`` writes the caller's
repository instead of the fixture's: on 10-23 two fixtures stamped "Citation fixture" and
"Ratchet test" into the shared agent-comms config, and 106 real commits carried the second.
A setting given per command persists nothing, whichever repository git resolves."""

SETTINGS = (
("user.name", "Test fixture"),
("user.email", "fixture@example.invalid"),
("commit.gpgsign", "false"),
)

# Global options for one git command: ("git", *IDENTITY, "-C", path, ...).
IDENTITY = tuple(part for key, value in SETTINGS for part in ("-c", f"{key}={value}"))

# The same settings for a git that the code under test starts, through git's own
# GIT_CONFIG_COUNT channel; set with monkeypatch so they end with the test.
ENVIRONMENT = {
"GIT_CONFIG_COUNT": str(len(SETTINGS)),
**{f"GIT_CONFIG_KEY_{index}": key for index, (key, _) in enumerate(SETTINGS)},
**{f"GIT_CONFIG_VALUE_{index}": value for index, (_, value) in enumerate(SETTINGS)},
}
7 changes: 3 additions & 4 deletions tests/guards/test_debt_ratchet.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from agent_comms.child_process import ObservedProcess, SpawnedProcess
from agent_comms.field_codec import FieldCodec
from fixture_git import IDENTITY
from process_tree_fixture import TREE, identities

from tools.debt_ratchet import (
Expand Down Expand Up @@ -130,12 +131,10 @@ def __init__(self, path: Path, root: str, ratchet: RatchetServer):
self.root = root
self.ratchet = ratchet
self.git("init", "-q")
self.git("config", "user.email", "ratchet@example.invalid")
self.git("config", "user.name", "Ratchet test")

def git(self, *args: str) -> str:
return subprocess.check_output(
["git", "-C", str(self.path), *args], text=True, timeout=10
["git", *IDENTITY, "-C", str(self.path), *args], text=True, timeout=10
).strip()

def commit(self, files: dict[str, str | None]) -> str:
Expand All @@ -147,7 +146,7 @@ def commit(self, files: dict[str, str | None]) -> str:
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(source)
self.git("add", "--all")
self.git("-c", "commit.gpgsign=false", "commit", "-qm", "test", "--allow-empty")
self.git("commit", "-qm", "test", "--allow-empty")
return self.git("rev-parse", "HEAD")

def arguments(self, base: str, head: str) -> tuple[str, ...]:
Expand Down
12 changes: 8 additions & 4 deletions tests/source_revision_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from agent_comms.repository_name import RepositoryName
from agent_comms.change_report import FileLine
from agent_comms.todos import FixScope, FixShape, PullRequestLink
from fixture_git import IDENTITY


class SourceRepository(Repo):
Expand Down Expand Up @@ -36,10 +37,16 @@ def scope(cls) -> FixScope:
parent = next(node for node in ast.parse(cls.main_source).body if isinstance(node, ast.ClassDef))
return FixScope(FixShape(parents=(FileLine('owner.py', parent.lineno),), members=()))

@staticmethod
def _run(checkout: Path | str, *args: str, timeout: float = 60,
input: bytes = b"") -> subprocess.CompletedProcess[bytes]:
"""Repo's one git subprocess, every command carrying the fixture identity."""
return Repo._run(checkout, *IDENTITY, *args, timeout=timeout, input=input)

@staticmethod
def git_input(repository: Path, text: str, *arguments: str) -> str:
return subprocess.run(
('git', '-C', str(repository), *arguments), input=text, text=True,
('git', *IDENTITY, '-C', str(repository), *arguments), input=text, text=True,
capture_output=True, check=True, timeout=30,
).stdout.strip()

Expand All @@ -58,9 +65,6 @@ def create(cls, root: Path, name: RepositoryName = RepositoryName.from_wire('exa
repository.mkdir(parents=True)
remote = cls.remote_for(root, name)
cls.git(repository, 'init', '--initial-branch=main')
cls.git(repository, 'config', 'user.name', 'Citation fixture')
cls.git(repository, 'config', 'user.email', 'citation@example.invalid')
cls.git(repository, 'config', 'commit.gpgsign', 'false')
cls.git(repository, 'remote', 'add', 'origin', str(remote))
main_blob = cls.git_input(repository, cls.main_source,
'hash-object', '-w', '--stdin')
Expand Down
5 changes: 2 additions & 3 deletions tests/test_carry.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from cutover.carry_commander_project import CommanderProjectCarry
from cutover.carry_drop_connectivity import DropConnectivity
from cutover.carry_parked_threads import ParkedThreads
from fixture_git import IDENTITY

REPO = Path(__file__).resolve().parents[1]

Expand All @@ -65,11 +66,9 @@ class Repository:
def __init__(self, path: Path):
self.path = path
self.git("init", "-q")
self.git("config", "user.email", "carry@example.invalid")
self.git("config", "user.name", "Carry test")

def git(self, *args: str) -> str:
return subprocess.check_output(["git", "-C", str(self.path), *args], text=True, timeout=10).strip()
return subprocess.check_output(["git", *IDENTITY, "-C", str(self.path), *args], text=True, timeout=10).strip()

def commit(self, steps: dict[str, str | None]) -> str:
"""One commit per step, in order, as the main line adds steps one at a time."""
Expand Down
3 changes: 2 additions & 1 deletion tests/test_checkout_submodules.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
import pytest

from agent_comms.repo import Checkout, CheckoutHoldsWorkError, ScratchCheckout
from fixture_git import IDENTITY


def git(path: Path, *args: str) -> str:
return subprocess.run(
("git", "-C", str(path), "-c", "user.name=t", "-c", "user.email=t@t", *args),
("git", *IDENTITY, "-C", str(path), *args),
check=True,
capture_output=True,
text=True,
Expand Down
11 changes: 9 additions & 2 deletions tests/test_checkpoint_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
CheckpointCliCommand, CleanCheckpoint, PushUnknownCheckpoint, PushedCheckpoint, RefusedCheckpoint,
)
from bus_record_fixture import context_comms
from fixture_git import ENVIRONMENT


@pytest.fixture(autouse=True)
def _fixture_identity(monkeypatch):
"""The checkpoint command commits through its own git, so the identity rides the
environment that git inherits, never a repository's config."""
for name, value in ENVIRONMENT.items():
monkeypatch.setenv(name, value)


def _git(worktree: Path, *arguments: str):
Expand All @@ -23,8 +32,6 @@ def _repo(tmp_path: Path, name: str, *, remote: bool = True) -> Path:
worktree = tmp_path / name
worktree.mkdir()
_git(worktree, "init", "-q", "-b", "main")
_git(worktree, "config", "user.name", "agent")
_git(worktree, "config", "user.email", "agent@example.com")
if remote:
_git(tmp_path, "init", "-q", "--bare", f"{name}.origin.git")
_git(worktree, "remote", "add", "origin", str(tmp_path / f"{name}.origin.git"))
Expand Down
4 changes: 2 additions & 2 deletions tests/test_installed_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ def test_a_merge_made_after_the_last_fetch_is_fetched_then_answered(tmp_path):
origin, installed = tmp_path / 'origin', tmp_path / 'installed'
origin.mkdir()
git(origin, 'init', '-q', '-b', 'main')
git(origin, '-c', 'user.name=t', '-c', 'user.email=t@t', 'commit', '-q', '--allow-empty', '-m', 'base')
git(origin, 'commit', '-q', '--allow-empty', '-m', 'base')
git(tmp_path, 'clone', '-q', str(origin), str(installed))
git(origin, '-c', 'user.name=t', '-c', 'user.email=t@t', 'commit', '-q', '--allow-empty', '-m', 'merged later')
git(origin, 'commit', '-q', '--allow-empty', '-m', 'merged later')
sha = git(origin, 'rev-parse', 'HEAD')
repo = Repo(checkout=installed, github=RepositoryName.from_wire('test/repo'))

Expand Down
7 changes: 4 additions & 3 deletions tests/test_order_progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import pytest
from test_todos import order
from source_revision_fixture import SourceRepository
from fixture_git import IDENTITY

from agent_comms.comms import wire
from agent_comms.goal_actions import CreateProblemGoalAction
Expand All @@ -28,7 +29,7 @@


def git(checkout, *args):
return subprocess.run(['git', '-C', str(checkout), *args], check=True, capture_output=True, text=True).stdout.strip()
return subprocess.run(['git', *IDENTITY, '-C', str(checkout), *args], check=True, capture_output=True, text=True).stdout.strip()


def test_prior_declarations_do_not_enter_native_request_schemas():
Expand Down Expand Up @@ -58,7 +59,7 @@ def unit_checkout(path):
git(path, 'init', '-q')
(path / 'owner.py').write_text('one\n')
git(path, 'add', 'owner.py')
git(path, '-c', 'user.name=t', '-c', 'user.email=t@t', 'commit', '-q', '-m', 'base')
git(path, 'commit', '-q', '-m', 'base')
return path


Expand Down Expand Up @@ -103,7 +104,7 @@ def test_a_submodule_with_a_missing_git_directory_does_not_stop_reading_edits(tm
package = unit_checkout(tmp_path / 'package')
worktree = unit_checkout(tmp_path / 'worker--P1')
git(worktree, '-c', 'protocol.file.allow=always', 'submodule', 'add', '-q', str(package), 'pinned')
git(worktree, '-c', 'user.name=t', '-c', 'user.email=t@t', 'commit', '-q', '-m', 'pin')
git(worktree, 'commit', '-q', '-m', 'pin')
(worktree / 'pinned' / '.git').write_text('gitdir: ../.git/modules/removed\n')
assert WorkBranches(worktree).uncommitted() == ()
edited(worktree, 'owner.py', 700.0)
Expand Down
17 changes: 9 additions & 8 deletions tests/test_phase_evidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,11 @@
from agent_comms.plan_phases import BusDeletionPhase, FLAG, ExternalBoundariesPhase, PlanPhase, RostersPhase
from agent_comms.repo import Repo
from agent_comms.repository_name import RepositoryName
from fixture_git import IDENTITY


def git(checkout, *args):
return subprocess.run(("git", "-C", str(checkout), *args), check=True,
return subprocess.run(("git", *IDENTITY, "-C", str(checkout), *args), check=True,
capture_output=True, text=True, timeout=30).stdout.strip()


Expand All @@ -41,7 +42,7 @@ def test_evidence_reads_origin_main_and_never_the_worktree(tmp_path):
(tmp_path / "src").mkdir()
(tmp_path / "src/kept.py").write_text("flag = True\n")
git(tmp_path, "add", ".")
git(tmp_path, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qm", "main")
git(tmp_path, "commit", "-qm", "main")
sha = git(tmp_path, "rev-parse", "HEAD")
git(tmp_path, "update-ref", "refs/remotes/origin/main", sha)
(tmp_path / "src/kept.py").unlink()
Expand All @@ -66,7 +67,7 @@ def test_boundary_evidence_ignores_its_declaration_and_exception_groups(tmp_path
"try:\n pass\nexcept ExceptionGroup:\n raise\n"
)
git(tmp_path, "add", ".")
git(tmp_path, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qm", "boundary")
git(tmp_path, "commit", "-qm", "boundary")
sha = git(tmp_path, "rev-parse", "HEAD")
git(tmp_path, "update-ref", "refs/remotes/origin/main", sha)
reading = PlanReading((), MainTree.of(
Expand All @@ -75,7 +76,7 @@ def test_boundary_evidence_ignores_its_declaration_and_exception_groups(tmp_path

source.write_text("try:\n pass\nexcept Exception:\n raise\n")
git(tmp_path, "add", ".")
git(tmp_path, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qm", "broad")
git(tmp_path, "commit", "-qm", "broad")
git(tmp_path, "update-ref", "refs/remotes/origin/main", git(tmp_path, "rev-parse", "HEAD"))
changed = PlanReading((), MainTree.of(reading.main.repo))
assert not changed.holds(ExternalBoundariesPhase.evidence)
Expand All @@ -93,7 +94,7 @@ def main_of(tmp_path, files):
(tmp_path / path).parent.mkdir(parents=True, exist_ok=True)
(tmp_path / path).write_text(text)
git(tmp_path, "add", ".")
git(tmp_path, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qm", "main")
git(tmp_path, "commit", "-qm", "main")
git(tmp_path, "update-ref", "refs/remotes/origin/main", git(tmp_path, "rev-parse", "HEAD"))
return PlanReading((), MainTree.of(
Repo(checkout=tmp_path, github=RepositoryName.from_wire("OpenHCSDev/agent-comms"))))
Expand Down Expand Up @@ -123,7 +124,7 @@ def test_roster_evidence_keeps_external_abi_and_each_remaining_internal_registry
):
(tmp_path / "src/remaining.py").write_text(remaining)
git(tmp_path, "add", ".")
git(tmp_path, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qm", "registry")
git(tmp_path, "commit", "-qm", "registry")
git(tmp_path, "update-ref", "refs/remotes/origin/main", git(tmp_path, "rev-parse", "HEAD"))
changed = PlanReading((), MainTree.of(reading.main.repo))
assert not changed.holds(RostersPhase.evidence), remaining
Expand All @@ -138,7 +139,7 @@ def test_main_tree_grep_uses_the_same_repository_tree_as_its_module_reader(tmp_p
reading = main_of(checkout, {"src/owner.py": "class OtherOwner:\n members = {}\n"})
git(checkout, "-c", "protocol.file.allow=always", "submodule", "add", "-q",
str(dependency), "src/dependency")
git(checkout, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qam", "dependency")
git(checkout, "commit", "-qam", "dependency")
git(checkout, "update-ref", "refs/remotes/origin/main", git(checkout, "rev-parse", "HEAD"))
git(checkout, "config", "submodule.recurse", "true")
assert "src/dependency" in git(checkout, "grep", "--recurse-submodules", "-n",
Expand Down Expand Up @@ -172,7 +173,7 @@ def test_bus_deletion_evidence_reads_uses_without_matching_its_own_declaration(t
):
(tmp_path / "src/uses.py").write_text(source)
git(tmp_path, "add", ".")
git(tmp_path, "-c", "user.name=t", "-c", "user.email=t@t", "commit", "-qm", "use")
git(tmp_path, "commit", "-qm", "use")
git(tmp_path, "update-ref", "refs/remotes/origin/main", git(tmp_path, "rev-parse", "HEAD"))
changed = PlanReading((), MainTree.of(reading.main.repo))
assert not changed.holds(BusDeletionPhase.evidence), source
Expand Down
8 changes: 2 additions & 6 deletions tests/test_proof_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
)
from agent_comms.tool_caller import ThreadCaller
from agent_comms.tools import CommsOrderDoneTool, CommsProblemCloseTool, CommsTodoCreateTool
from fixture_git import IDENTITY
from order_scope_fixture import FIX_SCOPE
from source_revision_fixture import SourceRepository

Expand Down Expand Up @@ -78,12 +79,7 @@ def proof_build_checkouts(
subprocess.run(
(
"git",
"-c",
"user.name=Proof Build",
"-c",
"user.email=proof@example.invalid",
"-c",
"commit.gpgsign=false",
*IDENTITY,
"commit",
"--allow-empty",
"-m",
Expand Down
Loading