Skip to content

Commit cca84b7

Browse files
committed
fix: KeyboardInterrupt safety, corrupted entry repair, disabled run guard
- Catch BaseException (not just Exception) in update swap/registry to handle KeyboardInterrupt and restore backup on Ctrl+C - Preserve installed_at (or set fresh one) when repairing corrupted non-dict registry entries in WorkflowRegistry.update() - Block 'workflow run' for disabled workflows with clear error message and re-enable hint
1 parent 3906918 commit cca84b7

2 files changed

Lines changed: 18 additions & 6 deletions

File tree

src/specify_cli/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4678,6 +4678,15 @@ def workflow_run(
46784678
console.print(f"[red]Error:[/red] Invalid workflow: {exc}")
46794679
raise typer.Exit(1)
46804680

4681+
# Check if workflow is disabled in registry
4682+
from .workflows.catalog import WorkflowRegistry
4683+
wf_registry = WorkflowRegistry(project_root)
4684+
wf_meta = wf_registry.get(source)
4685+
if isinstance(wf_meta, dict) and not wf_meta.get("enabled", True):
4686+
console.print(f"[red]Error:[/red] Workflow '{source}' is disabled")
4687+
console.print(f"\nTo re-enable: specify workflow enable {source}")
4688+
raise typer.Exit(1)
4689+
46814690
# Validate
46824691
errors = engine.validate(definition)
46834692
if errors:
@@ -5424,8 +5433,8 @@ def workflow_update(
54245433
wf_dir.rename(backup_dir)
54255434
try:
54265435
shutil.move(str(staged_dir), str(wf_dir))
5427-
except Exception:
5428-
# Restore from backup if swap fails
5436+
except BaseException:
5437+
# Restore from backup if swap fails (including KeyboardInterrupt)
54295438
if backup_dir and backup_dir.exists():
54305439
if wf_dir.exists():
54315440
shutil.rmtree(wf_dir)
@@ -5439,8 +5448,8 @@ def workflow_update(
54395448
"name": definition.name or update["name"],
54405449
"description": definition.description or "",
54415450
})
5442-
except Exception:
5443-
# Restore from backup if registry update fails
5451+
except BaseException:
5452+
# Restore from backup if registry update fails (including KeyboardInterrupt)
54445453
if backup_dir and backup_dir.exists():
54455454
if wf_dir.exists():
54465455
shutil.rmtree(wf_dir)

src/specify_cli/workflows/catalog.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,11 @@ def update(self, workflow_id: str, fields: dict[str, Any]) -> None:
122122

123123
existing = self.data["workflows"][workflow_id]
124124
if not isinstance(existing, dict):
125-
self.data["workflows"][workflow_id] = dict(fields)
126-
self.data["workflows"][workflow_id]["updated_at"] = datetime.now(timezone.utc).isoformat()
125+
now = datetime.now(timezone.utc).isoformat()
126+
repaired = dict(fields)
127+
repaired.setdefault("installed_at", now)
128+
repaired["updated_at"] = now
129+
self.data["workflows"][workflow_id] = repaired
127130
self.save()
128131
return
129132
installed_at = existing.get("installed_at")

0 commit comments

Comments
 (0)