Skip to content

Commit 273dd70

Browse files
Copilotmnriem
andauthored
Address review feedback: do-while condition preservation and URL scheme validation
Agent-Logs-Url: https://github.com/github/spec-kit/sessions/72a7bb5d-071f-4d67-a507-7e1abae2384d Co-authored-by: mnriem <15701806+mnriem@users.noreply.github.com>
1 parent 51d09c0 commit 273dd70

3 files changed

Lines changed: 20 additions & 3 deletions

File tree

src/specify_cli/workflows/catalog.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,19 @@ def _fetch_single_catalog(
319319
except (json.JSONDecodeError, OSError):
320320
pass
321321

322-
# Fetch from URL
322+
# Fetch from URL — validate scheme before opening
323+
from urllib.parse import urlparse
323324
from urllib.request import urlopen
324325

326+
parsed = urlparse(entry.url)
327+
is_localhost = parsed.hostname in ("localhost", "127.0.0.1", "::1")
328+
if parsed.scheme != "https" and not (
329+
parsed.scheme == "http" and is_localhost
330+
):
331+
raise WorkflowCatalogError(
332+
f"Refusing to fetch catalog from non-HTTPS URL: {entry.url}"
333+
)
334+
325335
try:
326336
with urlopen(entry.url, timeout=30) as resp: # noqa: S310
327337
data = json.loads(resp.read().decode("utf-8"))

src/specify_cli/workflows/steps/do_while/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,25 @@ class DoWhileStep(StepBase):
1212
1313
Continues while condition is truthy. ``max_iterations`` is
1414
required as a safety cap.
15+
16+
The first invocation always returns the nested steps for execution.
17+
The ``condition`` field is stored in the output so the engine can
18+
evaluate it after the body runs and decide whether to re-invoke.
1519
"""
1620

1721
type_key = "do-while"
1822

1923
def execute(self, config: dict[str, Any], context: StepContext) -> StepResult:
2024
max_iterations = config.get("max_iterations", 10)
2125
nested_steps = config.get("steps", [])
26+
condition = config.get("condition", "false")
2227

23-
# Always execute at least once
28+
# Always execute body at least once; the engine layer evaluates
29+
# `condition` after each iteration to decide whether to loop.
2430
return StepResult(
2531
status=StepStatus.COMPLETED,
2632
output={
27-
"condition_result": True,
33+
"condition": condition,
2834
"max_iterations": max_iterations,
2935
"loop_type": "do-while",
3036
},

tests/test_workflows.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,7 @@ def test_execute_always_runs_once(self):
640640
result = step.execute(config, ctx)
641641
assert len(result.next_steps) == 1
642642
assert result.output["loop_type"] == "do-while"
643+
assert result.output["condition"] == "{{ false }}"
643644

644645

645646
class TestFanOutStep:

0 commit comments

Comments
 (0)