diff --git a/crates/tokf-cli/filters/gh/issue/list.toml b/crates/tokf-cli/filters/gh/issue/list.toml index 95caf599..45bebc64 100644 --- a/crates/tokf-cli/filters/gh/issue/list.toml +++ b/crates/tokf-cli/filters/gh/issue/list.toml @@ -1,7 +1,7 @@ command = "gh issue list" description = "Structured JSON extraction of issue number, title, state, and labels" run = "gh issue list --json number,title,state,labels {args}" -passthrough_args = ["--web", "-w"] +passthrough_args = ["--web", "-w", "--json", "-q", "--jq"] [json] diff --git a/crates/tokf-cli/filters/gh/issue/view.toml b/crates/tokf-cli/filters/gh/issue/view.toml index 40a7d0ca..8a1a6beb 100644 --- a/crates/tokf-cli/filters/gh/issue/view.toml +++ b/crates/tokf-cli/filters/gh/issue/view.toml @@ -1,7 +1,7 @@ command = "gh issue view *" description = "Structured JSON extraction of issue details with body" run = "gh issue view {args} --json number,title,state,author,labels,assignees,milestone,body" -passthrough_args = ["--web", "-w"] +passthrough_args = ["--web", "-w", "--json", "-q", "--jq"] [json] diff --git a/crates/tokf-cli/filters/gh/pr/checks.toml b/crates/tokf-cli/filters/gh/pr/checks.toml index e6debe72..53e0e891 100644 --- a/crates/tokf-cli/filters/gh/pr/checks.toml +++ b/crates/tokf-cli/filters/gh/pr/checks.toml @@ -1,7 +1,7 @@ command = "gh pr checks *" description = "Structured JSON extraction of CI check names and status" run = "gh pr checks {args} --json name,state,workflow" -passthrough_args = ["--watch", "--web", "-w"] +passthrough_args = ["--watch", "--web", "-w", "--json", "-q", "--jq"] [json] diff --git a/crates/tokf-cli/filters/gh/pr/list.toml b/crates/tokf-cli/filters/gh/pr/list.toml index 5a5995d1..66d3aa1e 100644 --- a/crates/tokf-cli/filters/gh/pr/list.toml +++ b/crates/tokf-cli/filters/gh/pr/list.toml @@ -1,7 +1,7 @@ command = "gh pr list" description = "Structured JSON extraction of PR number, title, state, and branch" run = "gh pr list --json number,title,state,headRefName {args}" -passthrough_args = ["--web", "-w"] +passthrough_args = ["--web", "-w", "--json", "-q", "--jq"] [json] diff --git a/crates/tokf-cli/filters/gh/pr/view.toml b/crates/tokf-cli/filters/gh/pr/view.toml index 689b2596..a9c71631 100644 --- a/crates/tokf-cli/filters/gh/pr/view.toml +++ b/crates/tokf-cli/filters/gh/pr/view.toml @@ -1,7 +1,7 @@ command = "gh pr view *" description = "Structured JSON extraction of PR details with review status and body" run = "gh pr view {args} --json number,title,state,author,headRefName,baseRefName,reviewDecision,labels,assignees,milestone,body" -passthrough_args = ["--web", "-w"] +passthrough_args = ["--web", "-w", "--json", "-q", "--jq"] [json] diff --git a/crates/tokf-cli/tests/cli_run.rs b/crates/tokf-cli/tests/cli_run.rs index 8d3bd591..fcc53be7 100644 --- a/crates/tokf-cli/tests/cli_run.rs +++ b/crates/tokf-cli/tests/cli_run.rs @@ -501,3 +501,73 @@ output = "CHILD_FILTERED" "expected parent filter when no args variant matches, got: {stdout}" ); } + +// Regression test for https://github.com/nicholasgasior/tokf/issues/381: +// gh filters with a `run` override that injects --json must passthrough when +// the user already supplies their own --json / -q / --jq, otherwise the +// template renders an empty stub. +#[test] +fn gh_json_flag_triggers_passthrough() { + let dir = tempfile::TempDir::new().unwrap(); + let filters_dir = dir.path().join(".tokf/filters/gh/pr"); + std::fs::create_dir_all(&filters_dir).unwrap(); + // Mimic the bundled gh/pr/view filter (command + run + json extract + template) + std::fs::write( + filters_dir.join("view.toml"), + r#"command = "gh pr view *" +run = "echo INJECTED_JSON_SCHEMA" +passthrough_args = ["--web", "-w", "--json", "-q", "--jq"] + +[on_success] +output = "FILTERED_TEMPLATE" +"#, + ) + .unwrap(); + + // Without --json: filter applies, we get the template + let output = tokf() + .args(["run", "gh", "pr", "view", "1"]) + .current_dir(dir.path()) + .output() + .unwrap(); + assert!(output.status.success()); + let stdout = String::from_utf8_lossy(&output.stdout); + assert!( + stdout.contains("FILTERED_TEMPLATE"), + "expected filter template without --json, got: {stdout}" + ); + + // With --json: passthrough — original args forwarded, no template rendered + let output = tokf() + .args([ + "run", "gh", "pr", "view", "1", "--json", "isDraft", "-q", ".isDraft", + ]) + .current_dir(dir.path()) + .output() + .unwrap(); + assert!(output.status.success()); + let stdout = String::from_utf8_lossy(&output.stdout); + assert!( + !stdout.contains("FILTERED_TEMPLATE"), + "filter template must not appear when --json is passed, got: {stdout}" + ); + assert!( + !stdout.contains("INJECTED_JSON_SCHEMA"), + "run override must not execute when --json is passed, got: {stdout}" + ); + + // With --jq: same passthrough behaviour + let output = tokf() + .args([ + "run", "gh", "pr", "view", "1", "--json", "isDraft", "--jq", ".isDraft", + ]) + .current_dir(dir.path()) + .output() + .unwrap(); + assert!(output.status.success()); + let stdout = String::from_utf8_lossy(&output.stdout); + assert!( + !stdout.contains("FILTERED_TEMPLATE"), + "filter template must not appear when --jq is passed, got: {stdout}" + ); +}