diff --git a/docs/EXTENSIONS.md b/docs/EXTENSIONS.md index 9ba91a6..1cb8485 100644 --- a/docs/EXTENSIONS.md +++ b/docs/EXTENSIONS.md @@ -110,6 +110,7 @@ Extensions receive pup's auth credentials via environment variables. This means | `DD_SITE` | Always | Datadog site (e.g., `datadoghq.com`) | | `DD_ORG` | Org is specified | Named org session | | `PUP_OUTPUT` | Always | Output format (`json`, `table`, `yaml`, `csv`, `tsv`) | +| `PUP_FILTER` | `--jq` flag is set | The jq expression, verbatim | | `PUP_AUTO_APPROVE` | `--yes` flag or agent mode | `true` | | `PUP_READ_ONLY` | Read-only mode | `true` | | `PUP_AGENT_MODE` | Agent mode | `true` | @@ -118,7 +119,7 @@ Pup refreshes the OAuth2 token if needed before passing it to the extension, so Variables not active in the current session are explicitly removed from the child environment to prevent stale credentials from leaking through the parent shell. -The `PUP_OUTPUT`, `PUP_AGENT_MODE`, `PUP_READ_ONLY`, and `PUP_AUTO_APPROVE` variables are read back by a child `pup` process. So if your extension shells out to `pup` (see below), those nested calls automatically inherit the format and mode the user selected on the parent command. +The `PUP_OUTPUT`, `PUP_FILTER`, `PUP_AGENT_MODE`, `PUP_READ_ONLY`, and `PUP_AUTO_APPROVE` variables are read back by a child `pup` process. So if your extension shells out to `pup` (see below), those nested calls automatically inherit the format, `--jq` filter, and mode the user selected on the parent command. An extension that prints its own JSON directly — rather than delegating to a nested `pup` call — still needs to read `PUP_FILTER` itself and apply the jq expression if it wants to honor `--jq`. ### Example: using auth in a Python extension diff --git a/src/config.rs b/src/config.rs index d82aae2..eaeb11b 100644 --- a/src/config.rs +++ b/src/config.rs @@ -199,7 +199,10 @@ impl Config { || env_bool("DD_CLI_READ_ONLY") || env_bool("PUP_READ_ONLY") || file_cfg.read_only.unwrap_or(false), - jq: None, // set by caller from --jq flag + // `PUP_FILTER` is injected into extension subprocesses (like + // `PUP_OUTPUT` above) so a child `pup` call inherits the parent's + // --jq expression; an explicit --jq flag still overrides it. + jq: env_or("PUP_FILTER", None), }; Ok(cfg) @@ -1665,6 +1668,7 @@ mod tests { "DD_AUTO_APPROVE", "DD_CLI_AUTO_APPROVE", "PUP_AUTO_APPROVE", + "PUP_FILTER", ] { std::env::remove_var(var); } @@ -1681,6 +1685,15 @@ mod tests { std::env::remove_var("DD_OUTPUT"); std::env::remove_var("PUP_OUTPUT"); + // PUP_FILTER drives cfg.jq so a nested `pup` call spawned by an extension + // (e.g. `pup api` invoked from inside a `pup-` process) inherits the + // outer --jq expression, the same way it inherits --output. + assert_eq!(Config::from_env().unwrap().jq, None); + std::env::set_var("PUP_FILTER", ".[] | .id"); + let cfg = Config::from_env().unwrap(); + assert_eq!(cfg.jq.as_deref(), Some(".[] | .id")); + std::env::remove_var("PUP_FILTER"); + // PUP_READ_ONLY / PUP_AUTO_APPROVE flip the mode flags. std::env::set_var("PUP_READ_ONLY", "true"); std::env::set_var("PUP_AUTO_APPROVE", "true");