|
2 | 2 | import dataclasses |
3 | 3 | import json |
4 | 4 | import os |
| 5 | +import subprocess |
5 | 6 | import time |
6 | 7 | import uuid |
7 | 8 | from dataclasses import dataclass |
|
15 | 16 | from robot_orchestrator.hal.base import ProbeResult |
16 | 17 | from robot_orchestrator.paths import Paths |
17 | 18 | from robot_orchestrator.repos.manager import RELEASE_MARKER, RepoManager |
| 19 | +from robot_orchestrator.repos.venvs import venv_python |
18 | 20 | from robot_orchestrator.secrets import store as secrets_store |
19 | 21 | from robot_orchestrator.secrets.ingest import ingest_payload |
20 | 22 | from robot_orchestrator.secrets.protocol import SecretsPayload |
@@ -174,6 +176,40 @@ def _update_repos(self, facts: BootFacts) -> None: |
174 | 176 | result = manager.sync() |
175 | 177 | if result.error is not None and result.sha is None: |
176 | 178 | facts.repo_update_failures.append(name) |
| 179 | + elif name == "web-core": |
| 180 | + self._ensure_webcore_admin() |
| 181 | + |
| 182 | + def _ensure_webcore_admin(self) -> None: |
| 183 | + repo_state = store.get_repo_state(self.db.conn, "web-core") |
| 184 | + if not repo_state or not repo_state.get("current_release"): |
| 185 | + return |
| 186 | + release_dir = Path(repo_state["current_release"]) |
| 187 | + marker_path = release_dir / RELEASE_MARKER |
| 188 | + if not marker_path.exists(): |
| 189 | + return |
| 190 | + marker = json.loads(marker_path.read_text(encoding="utf-8")) |
| 191 | + venv_hash = marker.get("venv_hash") |
| 192 | + if not venv_hash: |
| 193 | + return |
| 194 | + python = venv_python(self.paths.venv_path("web-core", venv_hash)) |
| 195 | + script = release_dir / "tools" / "create_admin.py" |
| 196 | + if not python.exists() or not script.exists(): |
| 197 | + return |
| 198 | + |
| 199 | + generated = secrets_store.ensure_generated_secrets(self.paths) |
| 200 | + regular = secrets_store.load_secrets(self.paths).get("secrets", {}) or {} |
| 201 | + admin_password = regular.get("WEBCORE_ADMIN_PASSWORD") or generated.get("WEBCORE_ADMIN_PASSWORD") |
| 202 | + if not admin_password: |
| 203 | + return |
| 204 | + |
| 205 | + env = {**os.environ, "ADMIN_PASSWORD": admin_password} |
| 206 | + try: |
| 207 | + subprocess.run( |
| 208 | + [str(python), str(script)], cwd=release_dir, env=env, |
| 209 | + capture_output=True, text=True, timeout=30.0, |
| 210 | + ) |
| 211 | + except (OSError, subprocess.TimeoutExpired): |
| 212 | + pass |
177 | 213 |
|
178 | 214 | def _run_firmware_targets(self, facts: BootFacts) -> None: |
179 | 215 | for name, workflow in self.firmware_workflows.items(): |
|
0 commit comments