fix(workflows): tolerate non-dict registry entries in add and clarify test docstrings

A corrupted-but-parseable registry entry (e.g. a string value) crashed
WorkflowRegistry.add with AttributeError on existing.get. Guard the
non-dict case while still restoring the original raw value on rollback.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
marcelsafin
2026-07-11 00:14:40 +02:00
parent 338f7eecb0
commit 82ecd05331
2 changed files with 14 additions and 4 deletions

View File

@@ -92,8 +92,10 @@ class WorkflowRegistry:
"""Add or update an installed workflow entry."""
from datetime import datetime, timezone
existing = self.data["workflows"].get(workflow_id, {})
raw_existing = self.data["workflows"].get(workflow_id)
had_entry = workflow_id in self.data["workflows"]
# Corrupted-but-parseable registries may hold non-dict entries.
existing = raw_existing if isinstance(raw_existing, dict) else {}
metadata["installed_at"] = existing.get(
"installed_at", datetime.now(timezone.utc).isoformat()
)
@@ -105,7 +107,7 @@ class WorkflowRegistry:
# Roll back the in-memory mutation so a later successful save
# cannot persist metadata for a write that failed.
if had_entry:
self.data["workflows"][workflow_id] = existing
self.data["workflows"][workflow_id] = raw_existing
else:
del self.data["workflows"][workflow_id]
raise

View File

@@ -7555,8 +7555,16 @@ steps:
registry.add("other-wf", {"version": "1.0.0", "source": "catalog"})
assert registry.get("other-wf") is None
def test_registry_add_survives_non_dict_existing_entry(self, project_dir):
from specify_cli.workflows.catalog import WorkflowRegistry
registry = WorkflowRegistry(project_dir)
registry.data["workflows"]["align-wf"] = "corrupted"
registry.add("align-wf", {"version": "1.0.0", "source": "catalog"})
assert registry.get("align-wf")["version"] == "1.0.0"
def test_run_refuses_falsy_non_bool_enabled(self, project_dir, monkeypatch):
""""enabled": 0 shows as disabled in list — run must agree."""
"""A falsy non-bool "enabled" (0) shows as disabled in list — run must agree."""
import json as json_mod
from typer.testing import CliRunner
@@ -8127,7 +8135,7 @@ steps:
assert result.exit_code == 0, result.output
def test_disable_blocks_run_via_path_equivalent_id(self, project_dir, monkeypatch):
""""align-wf/" must not run a disabled workflow by dodging the registry lookup."""
"""Path spelling "align-wf/" must not run a disabled workflow by dodging the registry lookup."""
from typer.testing import CliRunner
from specify_cli import app