mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
feat(sdk): allow overriding worker tag when running jobs (WIN-2105) (#9807)
* feat(sdk): allow overriding worker tag when running jobs Add an optional `tag` parameter to every job-running helper across the TypeScript, Python, PowerShell and Rust client SDKs. When set, it is forwarded as the `tag` query param on the `jobs/run/*` endpoints, which the backend already honors as a worker-tag override. The parameter is appended last and defaults to null/None everywhere, so existing positional and keyword callers are unaffected. Rust has no optional params, so its existing `run_script_async`/`run_script_sync` signatures are left untouched and new `*_with_tag` variants are added. Fixes WIN-2105 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore(system_prompts): regenerate SDK docs for tag param Regenerate auto-generated system prompts so the TypeScript/Python SDK references (and the script skills that embed them) reflect the new optional `tag` parameter on the job-running helpers. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(powershell-sdk): preserve original RunScriptAsync/RunFlowAsync arities PowerShell class methods dispatch by exact argument count and have no default parameter values, so adding `$Tag` in place dropped the old 4-arg `RunScriptAsync` / 3-arg `RunFlowAsync` overloads — existing direct class calls would fail with "Cannot find an overload". Re-add the original arities as thin overloads that forward `$null` for `$Tag`. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(system_prompts): generate prompts.d.ts to stop literal-content drift prompts.d.ts was a tracked declaration file with string-literal types baked in, but generate.py never regenerated it — only prompts.ts and the hand-written index.d.ts. So every prompt change (e.g. the new SDK `tag` param) left prompts.d.ts stale, and check-freshness didn't catch it because generate.py never wrote the file. Emit prompts.d.ts from generate.py as plain `export declare const X: string;` declarations. The contents now live only in prompts.ts, so the declaration file can't drift, and check-freshness covers it going forward. 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:
@@ -168,16 +168,17 @@ class Windmill:
|
||||
hash_: str = None,
|
||||
args: dict = None,
|
||||
scheduled_in_secs: int = None,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a script job and return its job id.
|
||||
|
||||
|
||||
.. deprecated:: Use run_script_by_path_async or run_script_by_hash_async instead.
|
||||
"""
|
||||
logging.warning(
|
||||
"run_script_async is deprecated. Use run_script_by_path_async or run_script_by_hash_async instead.",
|
||||
)
|
||||
assert not (path and hash_), "path and hash_ are mutually exclusive"
|
||||
return self._run_script_async_internal(path=path, hash_=hash_, args=args, scheduled_in_secs=scheduled_in_secs)
|
||||
return self._run_script_async_internal(path=path, hash_=hash_, args=args, scheduled_in_secs=scheduled_in_secs, tag=tag)
|
||||
|
||||
def _run_script_async_internal(
|
||||
self,
|
||||
@@ -185,10 +186,13 @@ class Windmill:
|
||||
hash_: str = None,
|
||||
args: dict = None,
|
||||
scheduled_in_secs: int = None,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Internal helper for running scripts asynchronously."""
|
||||
args = args or {}
|
||||
params = {"scheduled_in_secs": scheduled_in_secs} if scheduled_in_secs else {}
|
||||
if tag:
|
||||
params["tag"] = tag
|
||||
if os.environ.get("WM_JOB_ID"):
|
||||
params["parent_job"] = os.environ.get("WM_JOB_ID")
|
||||
if os.environ.get("WM_ROOT_FLOW_JOB_ID"):
|
||||
@@ -208,18 +212,20 @@ class Windmill:
|
||||
path: str,
|
||||
args: dict = None,
|
||||
scheduled_in_secs: int = None,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a script job by path and return its job id."""
|
||||
return self._run_script_async_internal(path=path, args=args, scheduled_in_secs=scheduled_in_secs)
|
||||
return self._run_script_async_internal(path=path, args=args, scheduled_in_secs=scheduled_in_secs, tag=tag)
|
||||
|
||||
def run_script_by_hash_async(
|
||||
self,
|
||||
hash_: str,
|
||||
args: dict = None,
|
||||
scheduled_in_secs: int = None,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a script job by hash and return its job id."""
|
||||
return self._run_script_async_internal(hash_=hash_, args=args, scheduled_in_secs=scheduled_in_secs)
|
||||
return self._run_script_async_internal(hash_=hash_, args=args, scheduled_in_secs=scheduled_in_secs, tag=tag)
|
||||
|
||||
def run_flow_async(
|
||||
self,
|
||||
@@ -230,10 +236,13 @@ class Windmill:
|
||||
# as otherwise the child flow and its own child will store their state in the parent job which will
|
||||
# lead to incorrectness and failures
|
||||
do_not_track_in_parent: bool = True,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a flow job and return its job id."""
|
||||
args = args or {}
|
||||
params = {"scheduled_in_secs": scheduled_in_secs} if scheduled_in_secs else {}
|
||||
if tag:
|
||||
params["tag"] = tag
|
||||
if not do_not_track_in_parent:
|
||||
if os.environ.get("WM_JOB_ID"):
|
||||
params["parent_job"] = os.environ.get("WM_JOB_ID")
|
||||
@@ -254,9 +263,10 @@ class Windmill:
|
||||
verbose: bool = False,
|
||||
cleanup: bool = True,
|
||||
assert_result_is_not_none: bool = False,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run script synchronously and return its result.
|
||||
|
||||
|
||||
.. deprecated:: Use run_script_by_path or run_script_by_hash instead.
|
||||
"""
|
||||
logging.warning(
|
||||
@@ -265,7 +275,7 @@ class Windmill:
|
||||
assert not (path and hash_), "path and hash_ are mutually exclusive"
|
||||
return self._run_script_internal(
|
||||
path=path, hash_=hash_, args=args, timeout=timeout, verbose=verbose,
|
||||
cleanup=cleanup, assert_result_is_not_none=assert_result_is_not_none
|
||||
cleanup=cleanup, assert_result_is_not_none=assert_result_is_not_none, tag=tag
|
||||
)
|
||||
|
||||
def _run_script_internal(
|
||||
@@ -277,6 +287,7 @@ class Windmill:
|
||||
verbose: bool = False,
|
||||
cleanup: bool = True,
|
||||
assert_result_is_not_none: bool = False,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Internal helper for running scripts synchronously."""
|
||||
args = args or {}
|
||||
@@ -290,7 +301,7 @@ class Windmill:
|
||||
if isinstance(timeout, dt.timedelta):
|
||||
timeout = timeout.total_seconds()
|
||||
|
||||
job_id = self._run_script_async_internal(path=path, hash_=hash_, args=args)
|
||||
job_id = self._run_script_async_internal(path=path, hash_=hash_, args=args, tag=tag)
|
||||
return self.wait_job(
|
||||
job_id, timeout, verbose, cleanup, assert_result_is_not_none
|
||||
)
|
||||
@@ -303,11 +314,12 @@ class Windmill:
|
||||
verbose: bool = False,
|
||||
cleanup: bool = True,
|
||||
assert_result_is_not_none: bool = False,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run script by path synchronously and return its result."""
|
||||
return self._run_script_internal(
|
||||
path=path, args=args, timeout=timeout, verbose=verbose,
|
||||
cleanup=cleanup, assert_result_is_not_none=assert_result_is_not_none
|
||||
cleanup=cleanup, assert_result_is_not_none=assert_result_is_not_none, tag=tag
|
||||
)
|
||||
|
||||
def run_script_by_hash(
|
||||
@@ -318,11 +330,12 @@ class Windmill:
|
||||
verbose: bool = False,
|
||||
cleanup: bool = True,
|
||||
assert_result_is_not_none: bool = False,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run script by hash synchronously and return its result."""
|
||||
return self._run_script_internal(
|
||||
hash_=hash_, args=args, timeout=timeout, verbose=verbose,
|
||||
cleanup=cleanup, assert_result_is_not_none=assert_result_is_not_none
|
||||
cleanup=cleanup, assert_result_is_not_none=assert_result_is_not_none, tag=tag
|
||||
)
|
||||
|
||||
def run_inline_script_preview(
|
||||
@@ -1453,6 +1466,7 @@ def run_script_async(
|
||||
hash_or_path: str,
|
||||
args: Dict[str, Any] = None,
|
||||
scheduled_in_secs: int = None,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a script job and return its job ID.
|
||||
|
||||
@@ -1460,6 +1474,7 @@ def run_script_async(
|
||||
hash_or_path: Script hash or path (determined by presence of '/')
|
||||
args: Script arguments
|
||||
scheduled_in_secs: Delay before execution in seconds
|
||||
tag: Override the worker tag the job runs on
|
||||
|
||||
Returns:
|
||||
Job ID string
|
||||
@@ -1472,6 +1487,7 @@ def run_script_async(
|
||||
path=path,
|
||||
args=args,
|
||||
scheduled_in_secs=scheduled_in_secs,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -1484,6 +1500,7 @@ def run_flow_async(
|
||||
# as otherwise the child flow and its own child will store their state in the parent job which will
|
||||
# lead to incorrectness and failures
|
||||
do_not_track_in_parent: bool = True,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a flow job and return its job ID.
|
||||
|
||||
@@ -1492,6 +1509,7 @@ def run_flow_async(
|
||||
args: Flow arguments
|
||||
scheduled_in_secs: Delay before execution in seconds
|
||||
do_not_track_in_parent: Whether to track in parent job (default: True)
|
||||
tag: Override the worker tag the job runs on
|
||||
|
||||
Returns:
|
||||
Job ID string
|
||||
@@ -1501,6 +1519,7 @@ def run_flow_async(
|
||||
args=args,
|
||||
scheduled_in_secs=scheduled_in_secs,
|
||||
do_not_track_in_parent=do_not_track_in_parent,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -1512,6 +1531,7 @@ def run_script_sync(
|
||||
assert_result_is_not_none: bool = True,
|
||||
cleanup: bool = True,
|
||||
timeout: dt.timedelta = None,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run a script synchronously by hash and return its result.
|
||||
|
||||
@@ -1522,6 +1542,7 @@ def run_script_sync(
|
||||
assert_result_is_not_none: Raise exception if result is None
|
||||
cleanup: Register cleanup handler to cancel job on exit
|
||||
timeout: Maximum time to wait
|
||||
tag: Override the worker tag the job runs on
|
||||
|
||||
Returns:
|
||||
Script result
|
||||
@@ -1533,6 +1554,7 @@ def run_script_sync(
|
||||
assert_result_is_not_none=assert_result_is_not_none,
|
||||
cleanup=cleanup,
|
||||
timeout=timeout,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -1541,6 +1563,7 @@ def run_script_by_path_async(
|
||||
path: str,
|
||||
args: Dict[str, Any] = None,
|
||||
scheduled_in_secs: Union[None, int] = None,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a script job by path and return its job ID.
|
||||
|
||||
@@ -1548,6 +1571,7 @@ def run_script_by_path_async(
|
||||
path: Script path
|
||||
args: Script arguments
|
||||
scheduled_in_secs: Delay before execution in seconds
|
||||
tag: Override the worker tag the job runs on
|
||||
|
||||
Returns:
|
||||
Job ID string
|
||||
@@ -1556,6 +1580,7 @@ def run_script_by_path_async(
|
||||
path=path,
|
||||
args=args,
|
||||
scheduled_in_secs=scheduled_in_secs,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -1564,6 +1589,7 @@ def run_script_by_hash_async(
|
||||
hash_: str,
|
||||
args: Dict[str, Any] = None,
|
||||
scheduled_in_secs: Union[None, int] = None,
|
||||
tag: str = None,
|
||||
) -> str:
|
||||
"""Create a script job by hash and return its job ID.
|
||||
|
||||
@@ -1571,6 +1597,7 @@ def run_script_by_hash_async(
|
||||
hash_: Script hash
|
||||
args: Script arguments
|
||||
scheduled_in_secs: Delay before execution in seconds
|
||||
tag: Override the worker tag the job runs on
|
||||
|
||||
Returns:
|
||||
Job ID string
|
||||
@@ -1579,6 +1606,7 @@ def run_script_by_hash_async(
|
||||
hash_=hash_,
|
||||
args=args,
|
||||
scheduled_in_secs=scheduled_in_secs,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -1590,6 +1618,7 @@ def run_script_by_path_sync(
|
||||
assert_result_is_not_none: bool = True,
|
||||
cleanup: bool = True,
|
||||
timeout: dt.timedelta = None,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run a script synchronously by path and return its result.
|
||||
|
||||
@@ -1600,6 +1629,7 @@ def run_script_by_path_sync(
|
||||
assert_result_is_not_none: Raise exception if result is None
|
||||
cleanup: Register cleanup handler to cancel job on exit
|
||||
timeout: Maximum time to wait
|
||||
tag: Override the worker tag the job runs on
|
||||
|
||||
Returns:
|
||||
Script result
|
||||
@@ -1611,6 +1641,7 @@ def run_script_by_path_sync(
|
||||
assert_result_is_not_none=assert_result_is_not_none,
|
||||
cleanup=cleanup,
|
||||
timeout=timeout,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -2062,9 +2093,10 @@ def run_script(
|
||||
verbose: bool = False,
|
||||
cleanup: bool = True,
|
||||
assert_result_is_not_none: bool = True,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run script synchronously and return its result.
|
||||
|
||||
|
||||
.. deprecated:: Use run_script_by_path or run_script_by_hash instead.
|
||||
"""
|
||||
return _client.run_script(
|
||||
@@ -2075,6 +2107,7 @@ def run_script(
|
||||
assert_result_is_not_none=assert_result_is_not_none,
|
||||
cleanup=cleanup,
|
||||
timeout=timeout,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -2086,6 +2119,7 @@ def run_script_by_path(
|
||||
verbose: bool = False,
|
||||
cleanup: bool = True,
|
||||
assert_result_is_not_none: bool = True,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run script by path synchronously and return its result."""
|
||||
return _client.run_script_by_path(
|
||||
@@ -2095,6 +2129,7 @@ def run_script_by_path(
|
||||
assert_result_is_not_none=assert_result_is_not_none,
|
||||
cleanup=cleanup,
|
||||
timeout=timeout,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
|
||||
@@ -2106,6 +2141,7 @@ def run_script_by_hash(
|
||||
verbose: bool = False,
|
||||
cleanup: bool = True,
|
||||
assert_result_is_not_none: bool = True,
|
||||
tag: str = None,
|
||||
) -> Any:
|
||||
"""Run script by hash synchronously and return its result."""
|
||||
return _client.run_script_by_hash(
|
||||
@@ -2115,6 +2151,7 @@ def run_script_by_hash(
|
||||
assert_result_is_not_none=assert_result_is_not_none,
|
||||
cleanup=cleanup,
|
||||
timeout=timeout,
|
||||
tag=tag,
|
||||
)
|
||||
|
||||
@init_global_client
|
||||
|
||||
Reference in New Issue
Block a user