feat: deliver installable local alpha sessions
Some checks failed
tamq-ci / test (push) Failing after 6s
Some checks failed
tamq-ci / test (push) Failing after 6s
Assistant: codex Assistant-Model: gpt-5.6-sol Assistant-Session: 01a03397-4d51-7fd1-8ff2-946eb22ea2bc
This commit is contained in:
parent
d56bd3c79f
commit
5774fbd548
18 changed files with 890 additions and 94 deletions
113
tests/test_tmux_integration.py
Normal file
113
tests/test_tmux_integration.py
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import time
|
||||
from pathlib import Path
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from tamq.broker import BrokerIdentity, InputBroker
|
||||
from tamq.control import ControlModeClient
|
||||
from tamq.store import Store
|
||||
from tamq.tmux import LaunchPlan, TmuxManager
|
||||
|
||||
|
||||
@pytest.mark.skipif(shutil.which("tmux") is None, reason="tmux is not installed")
|
||||
def test_real_tmux_starts_two_repo_windows_and_reuses_them(tmp_path, monkeypatch):
|
||||
repo_a = tmp_path / "railiance-platform"
|
||||
repo_b = tmp_path / "activity-core"
|
||||
repo_a.mkdir()
|
||||
repo_b.mkdir()
|
||||
project_src = str(Path(__file__).resolve().parents[1] / "src")
|
||||
existing_pythonpath = os.environ.get("PYTHONPATH")
|
||||
monkeypatch.setenv("PYTHONPATH", project_src if not existing_pythonpath else f"{project_src}:{existing_pythonpath}")
|
||||
monkeypatch.setenv("TAMQ_STATE_DIR", str(tmp_path / "state"))
|
||||
|
||||
socket_name = f"tamq-pytest-{os.getpid()}-{uuid4().hex[:8]}"
|
||||
session = f"tamq-test-{uuid4().hex[:8]}"
|
||||
manager = TmuxManager(
|
||||
session,
|
||||
tmux_command=("tmux", "-L", socket_name),
|
||||
tamq_command=(sys.executable, "-m", "tamq.cli"),
|
||||
)
|
||||
plan = LaunchPlan(
|
||||
("railiance-platform", "activity-core"),
|
||||
{"railiance-platform": str(repo_a), "activity-core": str(repo_b)},
|
||||
("sh", "-c", "printf 'alpha-ready\\n'; exec sleep 30"),
|
||||
)
|
||||
|
||||
try:
|
||||
endpoint = manager.ensure_plan(plan)
|
||||
assert endpoint.created_session is True
|
||||
assert endpoint.created_windows == ("railiance-platform", "activity-core")
|
||||
|
||||
rows = manager._run(
|
||||
"list-windows",
|
||||
"-t",
|
||||
session,
|
||||
"-F",
|
||||
"#{window_name}|#{pane_current_path}|#{pane_pid}",
|
||||
).splitlines()
|
||||
parsed = {name: (path, pid) for name, path, pid in (row.split("|", 2) for row in rows)}
|
||||
assert set(parsed) == {"railiance-platform", "activity-core"}
|
||||
assert parsed["railiance-platform"][0] == str(repo_a)
|
||||
assert parsed["activity-core"][0] == str(repo_b)
|
||||
|
||||
deadline = time.monotonic() + 5
|
||||
while time.monotonic() < deadline:
|
||||
captures = [
|
||||
manager._run("capture-pane", "-p", "-t", f"{session}:{repo}")
|
||||
for repo in plan.repos
|
||||
]
|
||||
if all("alpha-ready" in capture for capture in captures):
|
||||
break
|
||||
time.sleep(0.05)
|
||||
assert all("alpha-ready" in capture for capture in captures)
|
||||
|
||||
reused = manager.ensure_plan(plan)
|
||||
assert reused.created_session is False
|
||||
assert reused.created_windows == ()
|
||||
reused_rows = manager._run(
|
||||
"list-windows",
|
||||
"-t",
|
||||
session,
|
||||
"-F",
|
||||
"#{window_name}|#{pane_current_path}|#{pane_pid}",
|
||||
).splitlines()
|
||||
reused_parsed = {name: (path, pid) for name, path, pid in (row.split("|", 2) for row in reused_rows)}
|
||||
assert reused_parsed == parsed
|
||||
assert reused.instance_id == endpoint.instance_id
|
||||
|
||||
store = Store(tmp_path / "state" / "tamq.sqlite3")
|
||||
control = ControlModeClient(
|
||||
session,
|
||||
tmux_command=("tmux", "-L", socket_name),
|
||||
)
|
||||
try:
|
||||
message_id = store.add("local", "activity-core", "integration-message")
|
||||
control.start()
|
||||
delivered = InputBroker(
|
||||
store,
|
||||
BrokerIdentity(endpoint.instance_id, "railiance-platform"),
|
||||
).deliver_pending(
|
||||
control,
|
||||
window_for_repo=lambda repo: f"{session}:{repo}",
|
||||
)
|
||||
assert delivered == 1
|
||||
assert store.list(state="injected")[0]["message_id"] == message_id
|
||||
|
||||
deadline = time.monotonic() + 5
|
||||
while time.monotonic() < deadline:
|
||||
capture = manager._run(
|
||||
"capture-pane", "-p", "-t", f"{session}:activity-core"
|
||||
)
|
||||
if "#local: integration-message" in capture:
|
||||
break
|
||||
time.sleep(0.05)
|
||||
assert "#local: integration-message" in capture
|
||||
finally:
|
||||
control.close()
|
||||
store.close()
|
||||
finally:
|
||||
manager._run("kill-server", check=False)
|
||||
Loading…
Add table
Add a link
Reference in a new issue