Stabilize Local Agent and workstation management v1.26.23
This commit is contained in:
@@ -252,14 +252,50 @@ class Supervisor:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def _validate_staged(staged: Path) -> None:
|
||||
def _validate_staged(staged: Path, expected_version: str = "") -> None:
|
||||
if not staged.exists() or not staged.is_dir():
|
||||
raise RuntimeError(f"Staged update directory not found: {staged}")
|
||||
if not (staged / "erp_local_agent" / "__init__.py").is_file():
|
||||
package_dir = staged / "erp_local_agent"
|
||||
init_path = package_dir / "__init__.py"
|
||||
dashboard_path = package_dir / "dashboard.py"
|
||||
main_path = package_dir / "main.py"
|
||||
if not init_path.is_file():
|
||||
raise RuntimeError("Staged update does not contain erp_local_agent/__init__.py.")
|
||||
if not dashboard_path.is_file() or not main_path.is_file():
|
||||
raise RuntimeError("Staged update is missing dashboard.py or main.py.")
|
||||
if not (staged / "requirements.txt").is_file():
|
||||
raise RuntimeError("Staged update does not contain requirements.txt.")
|
||||
|
||||
# Validate the candidate in-place BEFORE the working worker is stopped.
|
||||
# This specifically protects the dashboard identity contract that caused
|
||||
# older staged builds to fail on: from . import AGENT_NAME, __version__.
|
||||
py = _python(console=True)
|
||||
code = (
|
||||
"import sys;"
|
||||
f"sys.path.insert(0, {str(staged)!r});"
|
||||
"import erp_local_agent;"
|
||||
"assert getattr(erp_local_agent, 'AGENT_NAME', '') == 'ERP Local Agent', 'AGENT_NAME missing/invalid';"
|
||||
"assert getattr(erp_local_agent, '__version__', ''), '__version__ missing';"
|
||||
"from erp_local_agent import dashboard,main,commands,updater;"
|
||||
"print(erp_local_agent.__version__)"
|
||||
)
|
||||
result = subprocess.run(
|
||||
[str(py), "-c", code],
|
||||
cwd=str(staged),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
text=True,
|
||||
creationflags=_create_no_window(),
|
||||
timeout=90,
|
||||
)
|
||||
if result.returncode != 0:
|
||||
raise RuntimeError("Staged update preflight import validation failed:\n" + result.stdout[-4000:])
|
||||
staged_version = (result.stdout or "").strip().splitlines()[-1].strip()
|
||||
if expected_version and staged_version != expected_version:
|
||||
raise RuntimeError(
|
||||
f"Staged update version mismatch: requested={expected_version}, package={staged_version or 'missing'}."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _backup_runtime(version: str) -> Path:
|
||||
backup = UPDATES_DIR / f"supervisor_backup_{time.strftime('%Y%m%d_%H%M%S')}_{version}"
|
||||
@@ -345,7 +381,8 @@ class Supervisor:
|
||||
raise RuntimeError("Dependency installation failed:\n" + result.stdout[-4000:])
|
||||
code = (
|
||||
"import erp_local_agent;"
|
||||
"from erp_local_agent import accounting_store,commands,tally,updater;"
|
||||
"assert getattr(erp_local_agent, 'AGENT_NAME', '') == 'ERP Local Agent', 'AGENT_NAME missing/invalid';"
|
||||
"from erp_local_agent import accounting_store,commands,tally,updater,dashboard,main;"
|
||||
"print(erp_local_agent.__version__)"
|
||||
)
|
||||
result = subprocess.run(
|
||||
@@ -379,7 +416,7 @@ class Supervisor:
|
||||
if not version or not staged_text:
|
||||
raise RuntimeError("Supervisor update request is missing version/staged_dir.")
|
||||
staged = Path(staged_text).resolve()
|
||||
self._validate_staged(staged)
|
||||
self._validate_staged(staged, expected_version=version)
|
||||
|
||||
_update_progress("preparing", 8, f"Preparing ERP Local Agent {version} update.", version=version)
|
||||
_state("installing", f"Installing ERP Local Agent {version}.", target_version=version, progress_pct=8)
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
__version__ = "1.26.22"
|
||||
__version__ = "1.26.23"
|
||||
AGENT_NAME = "ERP Local Agent"
|
||||
|
||||
Reference in New Issue
Block a user