Skip to content

Commit 5f0692f

Browse files
committed
address review: stable fallback IDs, expression-based inter-step test
- Use enumerate() for stable fallback IDs when loop body steps lack an explicit id (step-0, step-1, etc. instead of always step-0). - Rewrite multi-step body test so step B uses expression substitution ({{ steps.step-a.output.stdout }}) instead of reading the counter file directly, making it a true regression test for per-step aliasing.
1 parent d4af331 commit 5f0692f

2 files changed

Lines changed: 9 additions & 16 deletions

File tree

src/specify_cli/workflows/engine.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -678,11 +678,11 @@ def _execute_steps(
678678
# result back to the unprefixed key so that
679679
# later steps in the same body and the loop
680680
# condition see the latest values.
681-
for ns in result.next_steps:
681+
for ns_idx, ns in enumerate(result.next_steps):
682682
ns_copy = dict(ns)
683683
orig = ns_copy.get("id")
684-
if orig:
685-
ns_copy["id"] = f"{step_id}:{orig}:{_loop_iter + 1}"
684+
base_id = orig or f"step-{ns_idx}"
685+
ns_copy["id"] = f"{step_id}:{base_id}:{_loop_iter + 1}"
686686
self._execute_steps(
687687
[ns_copy], context, state, registry,
688688
step_offset=-1,

tests/test_workflows.py

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2114,17 +2114,9 @@ def test_while_loop_multi_step_body_inter_step_refs(self, project_dir):
21142114
encoding="utf-8",
21152115
)
21162116

2117-
# Step B: reads step A's stdout from a marker file written by
2118-
# the test harness (since shell steps can't read context).
2119-
# Instead, step B just echoes its own value — we verify via
2120-
# the engine that step B's namespaced result was aliased back.
2121-
step_b_file = project_dir / "_step_b.py"
2122-
step_b_file.write_text(
2123-
f"import pathlib; p = pathlib.Path(r'{counter_file}')\n"
2124-
"print('b-saw-' + p.read_text().strip(), end='')\n",
2125-
encoding="utf-8",
2126-
)
2127-
2117+
# Step B uses {{ steps.step-a.output.stdout }} expression
2118+
# substitution in its run command so the engine resolves the
2119+
# aliased unprefixed key — this is the real inter-step test.
21282120
yaml_str = f"""
21292121
schema_version: "1.0"
21302122
workflow:
@@ -2142,7 +2134,7 @@ def test_while_loop_multi_step_body_inter_step_refs(self, project_dir):
21422134
run: '"{py}" "{step_a_file}"'
21432135
- id: step-b
21442136
type: shell
2145-
run: '"{py}" "{step_b_file}"'
2137+
run: "echo b-saw-{{{{ steps.step-a.output.stdout }}}}"
21462138
"""
21472139
definition = WorkflowDefinition.from_string(yaml_str)
21482140
engine = WorkflowEngine(project_dir)
@@ -2151,7 +2143,8 @@ def test_while_loop_multi_step_body_inter_step_refs(self, project_dir):
21512143
assert state.status == RunStatus.COMPLETED
21522144
# Both unprefixed keys reflect the latest iteration's results.
21532145
assert state.step_results["step-a"]["output"]["stdout"] == "3"
2154-
assert state.step_results["step-b"]["output"]["stdout"] == "b-saw-3"
2146+
# Step B saw step A's output via expression substitution.
2147+
assert "b-saw-3" in state.step_results["step-b"]["output"]["stdout"]
21552148
# Namespaced keys exist for loop iterations.
21562149
assert "retry-loop:step-a:1" in state.step_results
21572150
assert "retry-loop:step-b:1" in state.step_results

0 commit comments

Comments
 (0)