@@ -101,6 +101,48 @@ def test_task_run__extra_yaml_missing_path_raises(runtime):
101101 multi_cmd .resolve_command (ctx , ["dummy-task" , "--extra-yaml" ])
102102
103103
104+ def test_task_run__dash_o_overrides_extra_yaml (runtime ):
105+ """``-o taskname__option value`` wins over ``--extra-yaml``.
106+
107+ Extra YAML merges into the project config at load time; ``-o`` options
108+ are applied to ``task_config.config["options"]`` at invocation time
109+ (see ``task.py`` -- after ``reload_project_config``). The final task
110+ receives the ``-o`` value.
111+
112+ ``reload_project_config`` is mocked because the fixture builds a fake
113+ project in-memory; the relevant assertion is that ``-o`` wins over any
114+ option already present in ``task_config.config['options']`` regardless
115+ of whether that value came from ``cumulusci.yml`` or from extra YAML.
116+ """
117+ # Pretend the extra YAML already set tasks.dummy-task.options.color
118+ # (the runtime fixture lets us just pre-populate the config).
119+ runtime .project_config .config ["tasks" ]["dummy-task" ]["options" ] = {
120+ "color" : "red-from-extra-yaml" ,
121+ }
122+ runtime .reload_project_config = Mock ()
123+
124+ captured = {}
125+
126+ def _capture_options (self ):
127+ captured ["color" ] = self .options ["color" ]
128+
129+ DummyTask ._run_task = _capture_options
130+ multi_cmd = task .RunTaskCommand ()
131+ with click .Context (multi_cmd , obj = runtime ) as ctx :
132+ cmd = multi_cmd .get_command (ctx , "dummy-task" )
133+ cmd .callback (
134+ runtime ,
135+ "dummy-task" ,
136+ o = (("color" , "blue" ),),
137+ no_prompt = False ,
138+ debug = False ,
139+ debug_before = False ,
140+ debug_after = False ,
141+ )
142+
143+ assert captured ["color" ] == "blue"
144+
145+
104146def test_task_run__no_project (runtime ):
105147 runtime .project_config = None
106148 runtime .project_config_error = Exception ("Broken" )
0 commit comments