jira-agent/tests/test_self_update_e2e.py
2026-10-14 22:26:53 +04:00

79 lines
3.2 KiB
Python

import hashlib
import json
import os
import shutil
import signal
import subprocess
import sys
import tempfile
import time
import unittest
from _common import SETTINGS, SRC
from fake_hub import FakeHub
from fake_jira import FakeJira
def wait_for(pred, timeout=30):
end = time.monotonic() + timeout
while time.monotonic() < end:
if pred():
return True
time.sleep(0.1)
return False
class SelfUpdateE2E(unittest.TestCase):
"""run.py + настоящий agent.py: v5 видит публикацию v6, ставит её, v6 подтверждает; Ctrl-C группе — выход 0."""
def setUp(self):
self.jira = FakeJira()
self.hub = FakeHub(SETTINGS)
self.tmp = tempfile.TemporaryDirectory()
d = self.tmp.name
shutil.copy(os.path.join(SRC, "run.py"), d)
shutil.copy(os.path.join(SRC, "agent.py"), d)
with open(os.path.join(d, "agent.json"), "w", encoding="utf-8") as f:
json.dump({"hub_url": self.hub.base_url, "hub_token": self.hub.token, "timeout": 5, "poll_seconds": 0.2,
"jira": {"base_url": self.jira.base_url,
"auth": {"type": "basic", "user": "me", "password": "secret"}}}, f)
with open(os.path.join(SRC, "agent.py"), encoding="utf-8") as f:
src = f.read()
content = src.replace("AGENT_VERSION = 5\n", "AGENT_VERSION = 6\n", 1)
self.assertNotEqual(content, src)
self.hub.release = {"version": 6, "sha256": hashlib.sha256(content.encode("utf-8")).hexdigest(), "content": content}
self.content = content
self.log = open(os.path.join(d, "out.log"), "wb")
self.proc = subprocess.Popen([sys.executable, os.path.join(d, "run.py")], stdout=self.log,
stderr=subprocess.STDOUT, start_new_session=True)
def tearDown(self):
if self.proc.poll() is None:
os.killpg(self.proc.pid, signal.SIGKILL)
self.proc.wait()
self.log.close()
self.hub.stop()
self.jira.stop()
self.tmp.cleanup()
def state(self):
try:
with open(os.path.join(self.tmp.name, "update.json"), encoding="utf-8") as f:
return json.load(f)
except (OSError, ValueError):
return None
def test_update_to_v6_and_stop_by_ctrl_c(self):
ok = wait_for(lambda: (self.state() or {}).get("state") == "ok", 60)
with open(os.path.join(self.tmp.name, "out.log"), encoding="utf-8", errors="replace") as f:
out = f.read()
self.assertTrue(ok, out)
with open(os.path.join(self.tmp.name, "agent.py"), encoding="utf-8") as f:
self.assertEqual(f.read(), self.content)
self.assertTrue(os.path.exists(os.path.join(self.tmp.name, "agent.py.prev")))
self.assertTrue(wait_for(lambda: any(b.get("agent_version") == 6 for b in self.hub.claim_bodies)))
last = [b for b in self.hub.claim_bodies if b.get("agent_version") == 6][-1]
self.assertEqual(last["launcher_version"], 1)
os.killpg(self.proc.pid, signal.SIGINT) # Ctrl-C в терминале — всей группе
self.assertEqual(self.proc.wait(30), 0)