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

@ -33,8 +33,8 @@ class WorkflowRunClient(BaseDBClient):
logs: dict = None,
campaign_id: int = None,
queued_run_id: int = None,
use_draft: bool = False,
organization_id: int | None = None,
definition_id: int | None = None,
) -> WorkflowRunModel:
async with self.async_session() as session:
workflow_query = (
@ -54,56 +54,28 @@ class WorkflowRunClient(BaseDBClient):
if not workflow:
raise ValueError(f"Workflow with ID {workflow_id} not found")
# Resolve which definition to bind to this run
target_def = None
if use_draft:
# For test calls: prefer draft if it exists, fall back to published
draft_result = await session.execute(
select(WorkflowDefinitionModel).where(
if definition_id is not None:
definition_result = await session.execute(
select(WorkflowDefinitionModel.id).where(
WorkflowDefinitionModel.id == definition_id,
WorkflowDefinitionModel.workflow_id == workflow.id,
WorkflowDefinitionModel.status == "draft",
)
)
target_def = draft_result.scalars().first()
if target_def is None:
# Use the published version via released_definition_id (preferred)
# or fall back to is_current for backward compatibility
if workflow.released_definition_id:
target_def = await session.get(
WorkflowDefinitionModel, workflow.released_definition_id
if definition_result.scalar_one_or_none() is None:
raise ValueError(
f"Workflow definition {definition_id} does not belong to "
f"workflow {workflow.id}"
)
else:
pub_result = await session.execute(
select(WorkflowDefinitionModel).where(
WorkflowDefinitionModel.workflow_id == workflow.id,
WorkflowDefinitionModel.is_current == True,
)
)
target_def = pub_result.scalars().first()
# Get the current storage backend based on ENABLE_AWS_S3 flag
current_backend = StorageBackend.get_current_backend()
# Use initial_context from the version if available, else from workflow
default_context = (
target_def.template_context_variables
if target_def and target_def.template_context_variables
else workflow.template_context_variables
)
merged_initial_context = {
**(default_context or {}),
**(initial_context or {}),
}
new_run = WorkflowRunModel(
name=name,
workflow=workflow,
mode=mode,
definition_id=target_def.id if target_def else None,
initial_context=merged_initial_context,
definition_id=definition_id,
initial_context=initial_context or {},
gathered_context=gathered_context or {},
logs=logs or {},
campaign_id=campaign_id,