fix(workflows): guard non-mapping 'inputs:' block in engine._resolve_inputs#3696
fix(workflows): guard non-mapping 'inputs:' block in engine._resolve_inputs#3696jawwad-ali wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
Pull request overview
Prevents malformed workflow inputs blocks from crashing unvalidated workflow execution or resumption.
Changes:
- Treats non-dictionary
inputsas empty. - Adds regression coverage for list and null input blocks.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/workflows/engine.py |
Guards input resolution against non-mapping values. |
tests/test_workflows.py |
Tests list and null inputs blocks. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 0
- Review effort level: Medium
mnriem
left a comment
There was a problem hiding this comment.
Please pull in upstream/main
|
Heads-up: the failing This affects every open PR, not just this one (the |
…inputs
execute()/resume() run UNVALIDATED definitions (load_workflow does not
validate). WorkflowDefinition stores `inputs` raw, so a non-mapping
`inputs:` block (bare `inputs:` -> None, or `inputs: []`) crashed
_resolve_inputs at `for name, input_def in definition.inputs.items()` with
AttributeError, aborting the whole run.
Return {} when inputs is not a mapping, mirroring validate_workflow's own
`isinstance(definition.inputs, dict)` check. Protects both call sites
(execute and resume); normal dict resolution is unchanged.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ed5402b to
ae454b7
Compare
|
Rebased onto the latest One note on the red |
What
WorkflowEngine.execute()/resume()run unvalidated definitions (load_workflow's docstring: "not yet validated; call validate_workflow() separately"), andWorkflowDefinitionstoresinputsraw. So a non-mappinginputs:block — bareinputs:→None, orinputs: []→list— reached:…and crashed the whole run with
AttributeError: 'NoneType'/'list' object has no attribute 'items'. The steps layer is explicitly hardened for exactly this "engine does not auto-validate" case; theinputscontainer was the gap (the existing per-inputisinstanceskip is only reached after the crashing iteration).Fix
Return
{}whendefinition.inputsis not a mapping, mirroringvalidate_workflow's ownisinstance(definition.inputs, dict)check. Protects both call sites (executeandresume); normal dict resolution (defaults + provided overrides) is unchanged, andvalidate_workflowstill reports the malformed shape.Tests
tests/test_workflows.py::TestWorkflowDefinition::test_resolve_inputs_tolerates_non_mapping_inputs(parametrizedinputs: []and bareinputs:) —_resolve_inputsreturns{}instead of raising. Fails before the fix (AttributeError).ruff checkreports no new issues (the pre-existing engine.pyI001is unrelated and present on main).AI-assisted: authored with Claude Code. Verified against the
validate_workflowsibling check and confirmed fail-before/pass-after.