feat: terragrunt filter + close discover git/kubectl/glab gaps - #13
Conversation
Wrapped and non-dedicated commands were reported as "unhandled" even though rtk handles them, so the hook never rewrote them either: - Normalize before classifying: strip git global opts (-C/-c, ported from upstream rtk-ai#163), absolute binary paths (upstream rtk-ai#485), kubectl global flags before the subcommand, $(which x)/backtick wrappers, and a leading backslash line-continuation. Rewrite preserves the flags. - Classify git/kubectl passthrough subcommands (checkout, rebase, describe, config, ...) and glab (mr/ci/issue compact, rest passthrough) via a 0%-savings -> Passthrough status heuristic.
kubectl_pods/kubectl_services ignored the exit code, so a failed kubectl (bad context, RBAC denial, expired SSO token) produced empty stdout that parsed to "No pods found" with exit 0. Check status.success() first, print stderr, and propagate the real exit code, matching the behavior kubectl_get_generic already had.
…flags - New `rtk terragrunt`: strip ANSI + the terragrunt log prefix (<ts> LEVEL terraform: ...), drop init/refresh/progress noise, and keep resource action headers, in-place attribute changes, Plan/Apply/No-changes summaries, Changes to Outputs / Outputs, and error boxes. 80-92% reduction; validated against real Terragrunt 1.0.8 (fixtures captured from a null_resource project, apply/no-change/update synthesized). - main.rs: reorder 'rtk kubectl <global flags> <subcommand>' so clap routes it through the filter instead of falling back to raw (unfiltered). - Docs: ARCHITECTURE (60 modules), CLAUDE.md, README.
There was a problem hiding this comment.
Code Review
This pull request introduces a new terragrunt command and output filter to compact Terragrunt, Terraform, and OpenTofu execution logs. It also adds command normalization and passthrough tracking for git, kubectl, and glab subcommands, allowing global flags (like -C or --context) to be preserved or reordered correctly. Additionally, it improves error visibility for kubectl failures. The reviewer identified a high-severity issue in the Terragrunt filter where global deduplication would inadvertently strip identical attribute changes across different resources, and provided a code suggestion to restrict deduplication to error, warning, and box framing lines.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| let mut seen = std::collections::HashSet::new(); | ||
| kept.retain(|line| seen.insert(line.clone())); |
There was a problem hiding this comment.
Global deduplication of all kept lines will inadvertently strip identical attribute changes from different resources (e.g., if multiple resources have the exact same ~ triggers = { or ~ "foo" = "bar" -> "CHANGED" lines). This makes the plan output incomplete and misleading for resources with duplicate changes.\n\nTo fix this while still deduplicating the duplicate error/warning boxes printed by Terragrunt, we should restrict deduplication to only error, warning, and box framing lines.
let mut seen = std::collections::HashSet::new();\n kept.retain(|line| {\n let trimmed = line.trim();\n if is_box_line(trimmed) || trimmed.starts_with("Error:") || trimmed.starts_with("Warning:") {\n seen.insert(line.clone())\n } else {\n true\n }\n });There was a problem hiding this comment.
Good catch, fixed in 9470998. You are right that global dedup would drop identical in-place changes shared by different resources (common when the same attribute changes across a fleet). Restricted dedup to error/warning/box lines, which are the only content Terragrunt actually prints twice (the STDERR box + the error occurred: footer).
Added two regression tests: test_identical_changes_across_resources_preserved (two resources with the same ~ instance_type change, both survive) and test_error_box_deduplicated_to_single_copy (box still collapses to one copy).
Global deduplication dropped identical in-place change lines shared by different resources (e.g. the same instance_type bump across a fleet), making plans incomplete. Restrict dedup to error/warning/box framing - the only lines Terragrunt genuinely prints twice (STDERR + footer). Addresses Gemini review on PR #13.
Motivation
Driven by a Linux user's
rtk discoveroutput: ~3.3K commands/report were flagged as "unhandled — open an issue?" that rtk actually handles but failed to detect, plus a genuinely missingterragruntfilter that the registry already promised.What changed
feat(terragrunt)— newrtk terragruntfilterReal Terragrunt 1.0.8 output is ANSI-colored and log-prefixed (
<ts> LEVEL terraform: <content>), not the oldtime=level=msg=format. The filter strips ANSI + the log prefix, drops init/refresh/progress noise, and keeps the review essentials: resource action headers (# X will be …), in-place attribute changes (~ attr = old -> new),Plan:/Apply complete!/No changessummaries,Changes to Outputs/Outputs, and error boxes. 80–92% reduction.Fixtures were captured from a real cloud-free
null_resourceproject (tests/fixtures/terragrunt_*.txt); apply/no-change/update are synthesized becauseterragrunt apply -auto-approveis safety-gated.feat(discover)— close git/kubectl/glab detection gapsgit -C <path>/-c k=v→ ported from upstream bug: rtk git -C <path> ... is rejected (works only via separator form) rtk-ai/rtk#163/usr/bin/gitabsolute paths → ported from upstream fix: discover doesn't match /usr/bin/grep as rtk grep equivalent rtk-ai/rtk#485kubectl --context x -n y getglobal flags → net-new (missing upstream too)$(which git)/ backtick wrappers, leading\continuation → net-newcheckout,rebase,reset,config,describe, …), kubectl (config,describe,apply,delete,rollout, …), and glab (new rule:mr/ci/issuecompact, rest passthrough). Uses a0%-savings → Passthroughheuristic so no per-subcommand status tables are needed.fix(kubectl)— surface errors + route global-flags-firstrtk kubectl <global flags> <subcommand>was failing clap parsing and falling back to raw (unfiltered).normalize_kubectl_argvreorders global flags after the subcommand so it routes through the filter. Behavior-preserving (kubectl accepts flags anywhere); unknown input still falls back to raw (no regression).kubectl_pods/kubectl_servicesignored the exit code and masked real failures (bad context, RBAC, expired SSO) as "No pods found" with exit 0. Now they checkstatus.success(), print stderr, and propagate the real exit code.Upstream analysis (rtk-ai/rtk @ v0.43.0)
git -C/ abs-paths: already fixed upstream → ported rather than reinvented.$(which)literal / raw-fallback: still broken upstream → candidates to contribute back.Testing
cargo fmtclean; zero new clippy warnings in changed files;scripts/validate-docs.shpasses (60 modules).rtk rewrite) and real execution (rtk terragrunt plan,rtk kubectl --context … get pods,rtk kubectl config get-contexts,rtk git describe).Release impact
Two
feats → Release Please will cut a minor bump. Docs (README/CLAUDE/ARCHITECTURE) updated in-PR.