Skip to content

Add --extra-yaml flag to cci flow run/info and task run/info#3969

Open
jstvz wants to merge 13 commits intomainfrom
extra-yaml-cli-flag
Open

Add --extra-yaml flag to cci flow run/info and task run/info#3969
jstvz wants to merge 13 commits intomainfrom
extra-yaml-cli-flag

Conversation

@jstvz
Copy link
Copy Markdown
Contributor

@jstvz jstvz commented Apr 23, 2026

Summary

Adds --extra-yaml PATH (repeatable) to cci flow run, cci flow info,
cci task run, and cci task info. It merges extra YAML into the
project config for one command. Also reads CUMULUSCI_EXTRA_YAML (a
comma-separated env var) as a fallback. The flag and env var are
opt-in; nothing changes for users who do not set them.

Supersedes #3725. Closes #3429.

Precedence (highest to lowest)

  1. -o taskname__option value
  2. --extra-yaml files (last wins)
  3. CUMULUSCI_EXTRA_YAML env var
  4. Local project cumulusci.yml
  5. Project cumulusci.yml
  6. Global cumulusci.yml
  7. Universal (bundled) cumulusci.yml

Security

Extra YAML can redefine any class_path, which runs arbitrary Python
when the task starts. This is the same risk as cumulusci.yml, but
the flag makes it easier to pass untrusted input. A stderr warning
prints on every use.

Incidental change

The first commit pins pyright in .pre-commit-config.yaml and fixes
two pre-existing reportPrivateImportUsage errors from
simple_salesforce tightening its re-exports. Without this, the
pyright hook fails on main. 4 lines across 3 files. Happy to split
into a separate PR.

Test plan

  • Helper: single file, multi-file deep merge, env var fallback,
    flag overrides env, missing file, empty env segments
  • CliRuntime.reload_project_config: applies, rebinds keychain,
    no-ops on None, wraps ConfigError
  • All four commands accept --extra-yaml, including =PATH form
  • End-to-end: option override preserves siblings, multi-file last
    wins, new task is resolvable, class_path override imports new
    class
  • -o wins over --extra-yaml for the same option
  • Smoke tested against this repo
  • All pre-commit hooks clean on touched files
  • Full pytest suite green

Docs

  • docs/cli.md: new "The --extra-yaml Flag" subsection
  • docs/config.md: new per-invocation scope section, updated
    precedence list
  • docs/env-var-reference.md: CUMULUSCI_EXTRA_YAML entry

Follow-up after merge

  • Update the Cascading-Configuration-Files wiki page to include
    --extra-yaml in the cascade diagram.

jstvz added 12 commits April 22, 2026 17:35
simple_salesforce has tightened its __all__ exports, so reading
Salesforce/OrderedDict via the top-level namespace now trips pyright's
reportPrivateImportUsage. Switch to the canonical submodule imports
(simple_salesforce.api) and a setattr() monkey-patch that pyright
doesn't flag.

Also pin the pyright version in the pre-commit hook so node-side
version drift can't silently reintroduce the same class of failure.
Introduces a pure function that reads one or more paths (from the
--extra-yaml flag or CUMULUSCI_EXTRA_YAML env var) and returns the
concatenated YAML content as a single string, suitable for passing as
BaseProjectConfig's additional_yaml kwarg.

Implements the motivating use case from #3725 (thanks @jlantz) with a
different API: flag name, multi-file support, env var fallback, and
proper Click wiring are all different.
Adds a method that rebuilds project_config with an additional_yaml kwarg
and re-binds the keychain. Needed because CliRuntime is constructed in
cci.main() before Click has parsed subcommand options, so flags like
--extra-yaml cannot be applied at construction time.
Click option accepts multiple paths and honors CUMULUSCI_EXTRA_YAML
as a fallback. The resolved YAML string is passed to
CliRuntime.reload_project_config before flow resolution.
cci task run uses a custom RunTaskCommand MultiCommand. It must
resolve --extra-yaml before get_task() runs. If it does not, any task
defined only in the extra YAML is invisible to the runtime.

RunTaskCommand.resolve_command reads --extra-yaml from the raw args
list and calls CliRuntime.reload_project_config with the merged YAML.
Both --extra-yaml PATH and --extra-yaml=PATH are accepted.

The peek happens in resolve_command, not in get_command. Click's
MultiCommand protocol calls resolve_command(ctx, args), which then
calls get_command(ctx, cmd_name). By the time get_command runs,
ctx.args is empty. The remaining args stay in the args parameter
passed to resolve_command. We override resolve_command so that we can
see --extra-yaml while the project config is still mutable.

Adds "extra_yaml" to the specials list in core/tasks.py, alongside
debug_before, debug_after, and no_prompt. Click passes extra_yaml as
a kwarg on the task subcommand, which merges into
task_config.config["options"]. Tasks that use the Pydantic Options
form with extra='forbid' would reject it. The specials list already
exists to handle exactly this case.
Exercises the full path from resolve_extra_yaml through
CliRuntime.reload_project_config into BaseProjectConfig.get_task:

- Option override preserves sibling keys (deep merge)
- Multi-file last-wins ordering
- New task definition via --extra-yaml is resolvable
- class_path override imports the replacement class (documents the
  trust posture rather than preventing it)
Intentionally skipping docs/history.md — release notes there are
auto-generated from PR titles between latest-start/latest-stop markers.
@jstvz jstvz requested a review from a team as a code owner April 23, 2026 03:21
Splitting the env var on ":" broke on Windows where drive letters
contain colons (e.g. C:\tmp\a.yml). Switch to comma, the convention
used everywhere else in CCI for list-valued strings, via
process_list_arg. Replace os.path.isfile/open with pathlib.Path.
Update all CLI help strings, docstring, and docs.
@jstvz jstvz added feature needs review internal Pull requests from IPDE team labels Apr 24, 2026
@jstvz jstvz requested a review from abikkavilli-sf April 24, 2026 22:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature internal Pull requests from IPDE team needs review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support overriding cumulusci.yml to be used for configuration

1 participant