Skip to content

fix: handle flags placed after positional args in all commands#88

Open
rasifr wants to merge 1 commit intomainfrom
fix/ACE-171/flags-after-positional-args
Open

fix: handle flags placed after positional args in all commands#88
rasifr wants to merge 1 commit intomainfrom
fix/ACE-171/flags-after-positional-args

Conversation

@rasifr
Copy link
Member

@rasifr rasifr commented Mar 12, 2026

Go's flag.FlagSet stops parsing at the first non-flag argument, so flags appearing after a positional arg (e.g. "table-diff public.test -q") were silently misinterpreted as cluster or table names, and -h/--help caused a nil pointer panic when config was not loaded.

Add applyInterspersedFlags() to detect and apply stranded flags via ctx.Set() before the action runs, and filteredPositionalArgs() to strip flag-like tokens from the positional arg list. All command Before hooks now call applyInterspersedFlags(), and all action closures and CLI functions use filteredPositionalArgs() for arg resolution. Help flags (-h/--help) show command help via ctx.Lineage()[1] and return early. Also add nil guards on config.Cfg in TableDiffTask.Validate() and MerkleTreeTask.Validate() to prevent panics when config is not loaded.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

📝 Walkthrough

Walkthrough

Adds interspersed-flag handling to the CLI (helpers and Before hooks) and enforces nil-configuration guards in consistency validation methods to fail early if global config is not loaded.

Changes

Cohort / File(s) Summary
CLI Flag Parsing & Argument Handling
internal/cli/cli.go
Adds helpers: findFlag, isBoolFlag, filteredPositionalArgs, applyInterspersedFlags. Replaces raw ctx.Args().Slice() usage with filteredPositionalArgs(ctx), adds Before hooks to apply interspersed flags (including short-circuit for -h/--help) across many commands.
Consistency Validation Guards
internal/consistency/diff/table_diff.go, internal/consistency/mtree/merkle.go
Adds precondition checks in Validate() to return an error "configuration not loaded" when config.Cfg is nil, preventing later access to config.Cfg.* fields.

Poem

🐇 I nibble flags that hop and hide,
Between the args they sneak inside.
A guard now watches config's door,
"Loaded?" it asks — or stop, no more.
Hop, parse, and tidy CLI lore! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.79% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: fixing flag parsing for flags placed after positional arguments across all commands.
Description check ✅ Passed The description is directly related to the changeset, explaining the problem (flag parsing issues), the solution (interspersed flag handling functions), and implementation details.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/ACE-171/flags-after-positional-args

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6f55064e-05a3-44d3-977f-f5148ea6881e

📥 Commits

Reviewing files that changed from the base of the PR and between c3af6dd and 2f40218.

📒 Files selected for processing (3)
  • internal/cli/cli.go
  • internal/consistency/diff/table_diff.go
  • internal/consistency/mtree/merkle.go

Go's flag.FlagSet stops parsing at the first non-flag argument, so
flags appearing after a positional arg (e.g. "table-diff public.test
-q") were silently misinterpreted as cluster or table names, and
-h/--help caused a nil pointer panic when config was not loaded.

Add applyInterspersedFlags() to detect and apply stranded flags via
ctx.Set() before the action runs, and filteredPositionalArgs() to
strip flag-like tokens from the positional arg list. All command
Before hooks now call applyInterspersedFlags(), and all action
closures and CLI functions use filteredPositionalArgs() for arg
resolution. Help flags (-h/--help) show command help via
ctx.Lineage()[1] and return early. Also add nil guards on config.Cfg
in TableDiffTask.Validate() and MerkleTreeTask.Validate() to prevent
panics when config is not loaded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@rasifr rasifr force-pushed the fix/ACE-171/flags-after-positional-args branch from 2f40218 to 1e14e38 Compare March 12, 2026 09:00
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
internal/consistency/mtree/merkle.go (1)

50-52: Consider adding nil guard to aceSchema() for defense-in-depth.

This function directly accesses config.Cfg.MTree.Schema and is called from multiple methods (MtreeInit, BuildMtree, etc.) that don't go through Validate(). While the CLI ensures config is loaded before these paths execute, a nil guard here would provide consistent protection:

 func aceSchema() string {
+	if config.Cfg == nil {
+		return "ace"  // fallback default
+	}
 	return config.Cfg.MTree.Schema
 }

Alternatively, the callers could check config.Cfg before invoking operations that depend on it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/consistency/mtree/merkle.go` around lines 50 - 52, aceSchema()
dereferences config.Cfg.MTree.Schema without guards; add nil checks inside
aceSchema() to defend against missing config: ensure config.Cfg != nil and
config.Cfg.MTree != nil before accessing Schema and return a safe default (e.g.,
empty string) if either is nil; keep callers (MtreeInit, BuildMtree, Validate)
unchanged so they benefit from the centralized guard and optionally add a debug
log inside aceSchema() when falling back to the default.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@internal/consistency/mtree/merkle.go`:
- Around line 50-52: aceSchema() dereferences config.Cfg.MTree.Schema without
guards; add nil checks inside aceSchema() to defend against missing config:
ensure config.Cfg != nil and config.Cfg.MTree != nil before accessing Schema and
return a safe default (e.g., empty string) if either is nil; keep callers
(MtreeInit, BuildMtree, Validate) unchanged so they benefit from the centralized
guard and optionally add a debug log inside aceSchema() when falling back to the
default.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 83cdfd26-e3a4-48fa-8e96-6ef873bca506

📥 Commits

Reviewing files that changed from the base of the PR and between 2f40218 and 1e14e38.

📒 Files selected for processing (3)
  • internal/cli/cli.go
  • internal/consistency/diff/table_diff.go
  • internal/consistency/mtree/merkle.go


func TableDiffCLI(ctx *cli.Context) error {
// findFlag returns the flag definition matching name (including aliases).
func findFlag(flags []cli.Flag, name string) cli.Flag {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of this seems unnecessary and complicates things. Standard handling for go executables I believe is to process all of the flags first before the usual positional arguments. For example, ace table-diff -q public.test is ok but table-diff public.test -q isn't.

I think the only thing I think that this PR should have is this nil checks:

--- a/internal/consistency/diff/table_diff.go
+++ b/internal/consistency/diff/table_diff.go
@@ -727,6 +727,10 @@ func (t *TableDiffTask) Validate() error {
                return fmt.Errorf("cluster_name and table_name are required arguments")
        }

+       if config.Cfg == nil {
+               return fmt.Errorf("configuration not loaded")
+       }
+
        if t.BlockSize > config.Cfg.TableDiff.MaxBlockSize && !t.OverrideBlockSize {
                return fmt.Errorf("block row size should be <= %d", config.Cfg.TableDiff.MaxBlockSize)
        }
diff --git a/internal/consistency/mtree/merkle.go b/internal/consistency/mtree/merkle.go
index ac9e84c..b8c6ce1 100644
--- a/internal/consistency/mtree/merkle.go
+++ b/internal/consistency/mtree/merkle.go
@@ -1095,6 +1095,11 @@ func (m *MerkleTreeTask) Validate() error {
        if m.Mode == "listen" {
                return nil
        }
+
+       if config.Cfg == nil {
+               return fmt.Errorf("configuration not loaded")
+       }
+
        cfg := config.Cfg.MTree.Diff

        if m.BlockSize != 0 && !m.OverrideBlockSize {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants