fix: move draft and template context handling out of create_workflow_run (#560)

* fix: move draft and template context handling out of create_workflow_run

create_workflow_run now only creates
the run with the definition_id and initial_context provided by the caller. Test call paths explicitly resolve draft definitions
and merge template context variables before creating the run, while production/runtime paths bind the published definition
without adding template defaults.

* fix: review comments

* chore: format and minor cleanups

---------

Co-authored-by: Abhishek Kumar <abhishek@a6k.me>
This commit is contained in:
Sabiha Khan 2026-07-21 13:24:51 +05:30 committed by GitHub
parent 94dce42209
commit 90c5831984
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 657 additions and 72 deletions

View file

@ -574,21 +574,25 @@ class TestRunDefinitionBinding:
workflow_definition=GRAPH_V2,
)
versions = await db_session.get_workflow_versions(workflow.id)
published = next(v for v in versions if v.status == "published")
# Create a run (simulating campaign dispatch)
run = await db_session.create_workflow_run(
name="Campaign Run",
workflow_id=workflow.id,
mode="webrtc",
user_id=user.id,
definition_id=published.id,
)
# Run should be bound to the published V1, not the draft V2
versions = await db_session.get_workflow_versions(workflow.id)
published = next(v for v in versions if v.status == "published")
# Run should be bound to the caller-selected published V1.
assert run.definition_id == published.id
async def test_test_run_uses_draft_if_exists(self, db_session, workflow_with_v1):
"""A test/phone call should use the draft version for pre-publish testing."""
async def test_run_uses_caller_supplied_draft_definition(
self, db_session, workflow_with_v1
):
"""Test/phone callers bind drafts before creating the run."""
workflow, user = workflow_with_v1
draft = await db_session.save_workflow_draft(
@ -602,15 +606,15 @@ class TestRunDefinitionBinding:
workflow_id=workflow.id,
mode="webrtc", # test mode
user_id=user.id,
use_draft=True,
definition_id=draft.id,
)
assert run.definition_id == draft.id
async def test_run_initial_context_merges_with_template_context(
async def test_run_initial_context_is_stored_as_provided(
self, db_session, workflow_with_v1
):
"""Explicit run context should augment template context, not replace it."""
"""Template context merging is handled before calling the DB client."""
workflow, user = workflow_with_v1
await db_session.save_workflow_draft(
workflow_id=workflow.id,
@ -634,6 +638,37 @@ class TestRunDefinitionBinding:
assert run.initial_context == {
"company_name": "Override Co",
"default_only": "kept",
"provider": "smallwebrtc",
}
async def test_run_rejects_definition_from_another_workflow(
self, db_session, org_and_user
):
"""The DB client must not bind a run to another workflow's definition."""
org, user = org_and_user
workflow_a = await db_session.create_workflow(
name="Workflow A",
workflow_definition=GRAPH_V1,
user_id=user.id,
organization_id=org.id,
)
workflow_b = await db_session.create_workflow(
name="Workflow B",
workflow_definition=GRAPH_V2,
user_id=user.id,
organization_id=org.id,
)
workflow_b_versions = await db_session.get_workflow_versions(workflow_b.id)
workflow_b_definition = next(
v for v in workflow_b_versions if v.status == "published"
)
with pytest.raises(ValueError, match="does not belong"):
await db_session.create_workflow_run(
name="Bad Run",
workflow_id=workflow_a.id,
mode="smallwebrtc",
user_id=user.id,
organization_id=org.id,
definition_id=workflow_b_definition.id,
)