fix: install git for durable state recovery

This commit is contained in:
CoolBoy
2026-08-15 19:33:07 +08:00
parent 4260793c03
commit 467eaccd59
5 changed files with 41 additions and 15 deletions

View File

@@ -5,6 +5,10 @@ ENV PYTHONPATH=/app/modelhub_submmit_api
WORKDIR /app WORKDIR /app
RUN apt-get update \
&& apt-get install -y --no-install-recommends ca-certificates git \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt . COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt RUN pip install --no-cache-dir -r requirements.txt

View File

@@ -362,18 +362,19 @@ counts fail closed for older candidates, and no startup or periodic cleanup can
cancel a task by date. It also keeps unclassified/ambiguous historical failures cancel a task by date. It also keeps unclassified/ambiguous historical failures
neutral in GPU/framework success feedback while preserving deterministic OOM neutral in GPU/framework success feedback while preserving deterministic OOM
and architecture cleanup. and architecture cleanup.
Version `2026.08.15.1` replaces the 70/30 quota with hierarchical success-first Version `2026.08.15.2` replaces the 70/30 quota with hierarchical success-first
routing, dynamically gates models through the official GPU/task/framework/config routing, dynamically gates models through the official GPU/task/framework/config
APIs, enriches ModelScope metadata and model lineage, learns only proven safe APIs, enriches ModelScope metadata and model lineage, learns only proven safe
config vectors, and adds crash-safe write-ahead state synchronization to the config vectors, and adds crash-safe write-ahead state synchronization to the
`agent-state` branch. It also exposes `/ready` and extends deterministic cleanup `agent-state` branch. It also exposes `/ready` and extends deterministic cleanup
to officially removed waiting GPU/framework routes. to officially removed waiting GPU/framework routes. The runtime image installs
Git and CA certificates required by state recovery and synchronization.
## Deploy ## Deploy
Create a tag and submit the repository URL plus tag in "我的适配智能体". Create a tag and submit the repository URL plus tag in "我的适配智能体".
```bash ```bash
git tag -a agent-v25 -m "ModelHub agent 2026.08.15.1" git tag -a agent-v26 -m "ModelHub agent 2026.08.15.2"
git push origin main agent-v25 git push origin main agent-v26
``` ```

View File

@@ -222,16 +222,23 @@ class StateGitSync:
return env return env
def _git(self, *args: str, cwd: Path | None = None, check: bool = True) -> subprocess.CompletedProcess[str]: def _git(self, *args: str, cwd: Path | None = None, check: bool = True) -> subprocess.CompletedProcess[str]:
result = subprocess.run( try:
["git", *args], result = subprocess.run(
cwd=str(cwd or self.project_root), ["git", *args],
env=self._git_environment(), cwd=str(cwd or self.project_root),
text=True, env=self._git_environment(),
stdout=subprocess.PIPE, text=True,
stderr=subprocess.PIPE, stdout=subprocess.PIPE,
timeout=45, stderr=subprocess.PIPE,
check=False, timeout=45,
) check=False,
)
except FileNotFoundError as exc:
raise StateSyncError(
"git executable is unavailable; rebuild the service image from the repository Dockerfile"
) from exc
except subprocess.TimeoutExpired as exc:
raise StateSyncError("git operation timed out after 45 seconds") from exc
if check and result.returncode != 0: if check and result.returncode != 0:
reason = _safe_text(result.stderr.strip() or result.stdout.strip() or f"git exited {result.returncode}") reason = _safe_text(result.stderr.strip() or result.stdout.strip() or f"git exited {result.returncode}")
raise StateSyncError(reason) raise StateSyncError(reason)

View File

@@ -1 +1 @@
AGENT_VERSION = "2026.08.15.1" AGENT_VERSION = "2026.08.15.2"

View File

@@ -20,6 +20,7 @@ from hf_discovery import HuggingFaceDiscovery, parse_model_card_front_matter #
from official_capabilities import OfficialCapabilityRegistry # noqa: E402 from official_capabilities import OfficialCapabilityRegistry # noqa: E402
from routing_engine import SuccessFirstRoutingEngine # noqa: E402 from routing_engine import SuccessFirstRoutingEngine # noqa: E402
from state_sync import StateGitSync # noqa: E402 from state_sync import StateGitSync # noqa: E402
from state_sync import StateSyncError # noqa: E402
class OfficialClient: class OfficialClient:
@@ -207,6 +208,19 @@ class SuperAgentTests(unittest.TestCase):
) )
) )
def test_missing_git_has_actionable_state_sync_error(self) -> None:
with tempfile.TemporaryDirectory() as temporary_dir:
manager = StateGitSync(
project_root=Path(temporary_dir),
credentials={"username": "u", "email": "e@example.com", "password": "p"},
remote="unused",
log_fn=lambda _: None,
)
with patch("state_sync.subprocess.run", side_effect=FileNotFoundError("git")):
with self.assertRaisesRegex(StateSyncError, "rebuild the service image"):
manager._git("version")
manager.close()
def test_config_patch_requires_repeated_cross_model_success(self) -> None: def test_config_patch_requires_repeated_cross_model_success(self) -> None:
with tempfile.TemporaryDirectory() as temporary_dir: with tempfile.TemporaryDirectory() as temporary_dir:
root = Path(temporary_dir) root = Path(temporary_dir)