fix(workflows): reject bool max_iterations in while/do-while validation (#3237)

* fix(workflows): reject bool max_iterations in while/do-while validation

while/do-while validate() checked 'not isinstance(max_iter, int) or max_iter < 1'. Since bool is a subclass of int, isinstance(True, int) is True and True < 1 is False, so 'max_iterations: true' passed validation and then ran as a single iteration (range(True) == range(1)) instead of being reported as a type error. Reject bools explicitly, matching the fail-fast-on-bool handling already used for number inputs and gate options.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: assert empty error list for the valid do-while max_iterations case

Address Copilot review: the accepted-config assertion only checked that no error mentioned 'max_iterations', which could let an unrelated validation error pass unnoticed. For a known-good config, assert the entire error list is empty (consistent with the other validate tests in this file).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali jawwad
2026-06-30 20:17:05 +05:00
committed by GitHub
parent 6fb7e77b3e
commit 3571ba72d8
3 changed files with 29 additions and 2 deletions

View File

@@ -48,7 +48,10 @@ class DoWhileStep(StepBase):
)
max_iter = config.get("max_iterations")
if max_iter is not None:
if not isinstance(max_iter, int) or max_iter < 1:
# bool is a subclass of int, so isinstance(True, int) is True and
# True < 1 is False; reject bools explicitly so `max_iterations: true`
# is a type error rather than a silent single iteration.
if isinstance(max_iter, bool) or not isinstance(max_iter, int) or max_iter < 1:
errors.append(
f"Do-while step {config.get('id', '?')!r}: "
f"'max_iterations' must be an integer >= 1."

View File

@@ -55,7 +55,10 @@ class WhileStep(StepBase):
)
max_iter = config.get("max_iterations")
if max_iter is not None:
if not isinstance(max_iter, int) or max_iter < 1:
# bool is a subclass of int, so isinstance(True, int) is True and
# True < 1 is False; reject bools explicitly so `max_iterations: true`
# is a type error rather than a silent single iteration.
if isinstance(max_iter, bool) or not isinstance(max_iter, int) or max_iter < 1:
errors.append(
f"While step {config.get('id', '?')!r}: "
f"'max_iterations' must be an integer >= 1."