Skip to content

Commit 5d748b4

Browse files
add step args
1 parent 5062a1e commit 5d748b4

5 files changed

Lines changed: 61 additions & 4 deletions

File tree

clarifai/cli/pipeline_step.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,30 @@ def init(pipeline_step_path):
125125
default=False,
126126
help='Keep the Docker image after the pipeline step finishes.',
127127
)
128-
def local_run(pipeline_step_path, mode, keep_image):
128+
@click.option(
129+
'--step-args',
130+
default=None,
131+
help='Arguments to pass to pipeline_step.py (e.g., "--param_a hello --param_b world").',
132+
)
133+
def local_run(pipeline_step_path, mode, keep_image, step_args):
129134
"""Run a pipeline step locally in a Docker container.
130135
136+
\b
131137
PIPELINE_STEP_PATH: Path to the pipeline step directory (containing config.yaml,
132138
requirements.txt, and 1/pipeline_step.py). Defaults to current directory.
133139
140+
\b
141+
Pass arguments to the step script via --step-args:
142+
clarifai pipelinestep local-run ./my-step --step-args "--param_a hello --param_b world"
143+
134144
This reuses the same Docker build infrastructure as ``clarifai model serve
135145
--mode container`` but executes pipeline_step.py once and exits.
136146
"""
147+
# Parse step-args string into a list
148+
if step_args:
149+
import shlex
150+
151+
step_args = shlex.split(step_args)
137152
from clarifai.runners.pipeline_steps.pipeline_run_locally import PipelineStepRunLocally
138153

139154
manager = PipelineStepRunLocally(pipeline_step_path)
@@ -157,6 +172,7 @@ def local_run(pipeline_step_path, mode, keep_image):
157172
manager.run_pipeline_step_container(
158173
image_name=image_name,
159174
container_name=container_name,
175+
step_args=list(step_args) if step_args else None,
160176
)
161177
finally:
162178
if manager.container_exists(container_name):

clarifai/runners/pipeline_steps/pipeline_run_locally.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,15 @@ def run_pipeline_step_container(
7070
image_name,
7171
container_name="clarifai-pipeline-step-container",
7272
env_vars=None,
73+
step_args=None,
7374
):
7475
"""Run pipeline_step.py inside a Docker container and wait for it to finish.
7576
7677
Unlike ``ModelRunLocally.run_docker_container`` which starts a long-running
7778
server, this method executes the pipeline step script once and exits.
79+
80+
Args:
81+
step_args: Optional list of arguments to pass to pipeline_step.py.
7882
"""
7983
try:
8084
cmd = ["docker", "run", "--name", container_name, "--rm", "--network", "host"]
@@ -101,6 +105,10 @@ def run_pipeline_step_container(
101105
cmd.append(image_name)
102106
cmd.extend(["/home/nonroot/main/1/pipeline_step.py"])
103107

108+
# Append any extra arguments for the pipeline step script
109+
if step_args:
110+
cmd.extend(step_args)
111+
104112
logger.info(f"Running pipeline step in container '{container_name}'...")
105113
logger.info(f"Docker command: {cmd}")
106114

tests/cli/test_pipeline_step.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,6 +464,7 @@ def test_local_run_command_help(self):
464464
assert '--mode' in result.output
465465
assert '--keep-image' in result.output
466466
assert 'PIPELINE_STEP_PATH' in result.output
467+
assert '--step-args' in result.output
467468

468469

469470
class TestPipelineStepLocalRunCommand:
@@ -504,3 +505,20 @@ def test_local_run_no_docker(self, mock_docker):
504505

505506
assert result.exit_code != 0
506507
assert 'Docker is not installed' in result.output
508+
509+
def test_local_run_step_args_parsing(self):
510+
"""Test that --step-args string is correctly parsed into a list."""
511+
import shlex
512+
513+
# This is the parsing logic used inside the local_run command
514+
step_args_str = "--param_a hello --param_b world"
515+
parsed = shlex.split(step_args_str)
516+
assert parsed == ['--param_a', 'hello', '--param_b', 'world']
517+
518+
# Quoted values
519+
step_args_str = '--param_a "hello world" --param_b value'
520+
parsed = shlex.split(step_args_str)
521+
assert parsed == ['--param_a', 'hello world', '--param_b', 'value']
522+
523+
# None input means no args
524+
assert shlex.split("") == []
Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1-
"""Dummy pipeline step for testing local-run."""
1+
"""Dummy pipeline step matching the default clarifai pipelinestep init template."""
22

3-
print("Pipeline step started")
4-
print("Pipeline step completed successfully")
3+
import argparse
4+
5+
6+
def main():
7+
parser = argparse.ArgumentParser(description='Dummy pipeline step.')
8+
parser.add_argument('--param_a', type=str, required=True, help='First parameter')
9+
parser.add_argument('--param_b', type=str, default='default_b', help='Second parameter')
10+
11+
args = parser.parse_args()
12+
13+
print(f"Pipeline step started: param_a={args.param_a}, param_b={args.param_b}")
14+
print("Pipeline step completed successfully")
15+
16+
17+
if __name__ == "__main__":
18+
main()

tests/runners/test_pipeline_step_run_locally_container.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ def test_pipeline_step_docker_build_and_run(pipeline_step_run_locally):
4848
pipeline_step_run_locally.run_pipeline_step_container(
4949
image_name=image_name,
5050
container_name=container_name,
51+
step_args=["--param_a", "hello", "--param_b", "world"],
5152
)
5253
except subprocess.CalledProcessError:
5354
pytest.fail("Failed to run pipeline step inside the docker container.")

0 commit comments

Comments
 (0)