fix(workflows): reject a fan-in wait_for that names an unknown step at validation#3225
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR tightens workflow validation to prevent fan-in steps from silently producing empty join results when wait_for references an invalid step id, addressing #3223 and aligning with prior “fail loud” validation work.
Changes:
- Add engine-level validation to ensure
fan-in.wait_foronly references step ids already declared at the point of thefan-in. - Add unit tests covering unknown
wait_forids, valid earlier ids, conditionally declared ids, and forward references.
Show a summary per file
| File | Description |
|---|---|
src/specify_cli/workflows/engine.py |
Adds fan-in wait_for validation against already-seen step ids during workflow validation. |
tests/test_workflows.py |
Adds new test cases asserting validation rejects unknown/forward-referenced wait_for ids and allows earlier/conditional ids. |
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: 2
- Review effort level: Low
…entries Address review feedback on the fan-in wait_for validator: - A fan-in's own id is added to seen_ids before the wait_for check, so `wait_for: [<self>]` passed validation while producing a silent empty join at runtime. Reject self-references explicitly. - Non-string entries (e.g. YAML `wait_for: [123]`) were skipped by the isinstance(str) guard and validated even though they can never match a real step id. Flag them as wiring errors. Add coverage for both cases.
Contributor
Author
|
Thanks @copilot for the review — both points addressed at root cause in d9c867b:
Added coverage: @mnriem would you mind taking a look when you have a moment? 🙏 |
mnriem
approved these changes
Jun 29, 2026
Collaborator
|
Thank you! |
7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Closes #3223. Sibling to #2957 (fail loud when a fan-out
itemsexpression does not resolve to a list).A
fan-inwhosewait_fornames a step id that isn't declared — a typo, or a forward reference to a step declared after the fan-in — currently aggregates an empty result and reportsCOMPLETED, masking the authoring error.validate_workflownow flags it: eachwait_forid must name a step declared at or before the fan-in, checked against theseen_idsset_validate_stepsalready maintains.A step that is declared but only conditionally executed (e.g. inside an
if/switchbranch) is still "seen", so a legitimately-empty join stays valid — only genuinely unknown or forward-referenced ids are rejected. This is validation-time, so there is no runtime behavior change for correctly-authored workflows.Testing
.venv/bin/python -m pytest tests/test_workflows.py— 314 passed, including 4 newTestFanInWaitForValidationcases: unknown id rejected, declared-earlier id passes, conditionally-declared (if-branch) id passes, forward reference rejected.uvx ruff check src/ tests/test_workflows.py— cleanuv run specify --helpAI Disclosure
Code, tests, and this description were authored with AI assistance (Claude Code), from a fan-out/fan-in audit; everything was verified by running the repo's test suite and ruff locally.
@mnriem — small validation-only change; would appreciate your review when you have a moment.