Skip to content

Fix section subcommand help when a global flag precedes the section (MIR-1309)#908

Merged
evanphx merged 1 commit into
mainfrom
mir-1309-miren-help-auth-refuses-to-show-the-subcommands
Jul 10, 2026
Merged

Fix section subcommand help when a global flag precedes the section (MIR-1309)#908
evanphx merged 1 commit into
mainfrom
mir-1309-miren-help-auth-refuses-to-show-the-subcommands

Conversation

@evanphx

@evanphx evanphx commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Problem

MIR-1309 was filed as "miren help auth refuses to show the subcommands," but
that form works. The real defect: a value-taking global flag before a section
name
breaks subcommand help.

miren -C prod auth help   → printed TOP-LEVEL help instead of auth's subcommands
miren -C prod auth        → same class of failure

auth (and env, sandbox, config, …) is a Section with an empty
flagset. The mflags interspersed-flag resolver correctly guessed -C consumed
prod, matched the auth section, then rejected the match because -C isn't
declared in the section's flagset — falling back to top-level help.

Fix

Two parts:

  1. mflags (already merged: Show section subcommand help when a global flag precedes the section mflags#15) — the resolver no longer
    rejects a matched command path just because a pre-command flag is unknown to
    it. This PR bumps the pin to that commit.
  2. runtime (here) — section flagsets now AllowUnknownFlags(true), so the
    no-help form (miren -C prod auth) parses the leftover global flag and
    renders subcommands via ErrShowHelp instead of erroring.

Tests

  • cli/commands/section_help_test.go — new regression test built via
    RegisterAll, covering miren [-C prod] auth [help|--help].
  • Verified end-to-end against a real build: every section form lists its
    subcommands; -C prod app list still receives the cluster and
    -C prod auth generate still runs the real command.

Fixes MIR-1309.

`miren -C <cluster> auth help` (and `miren -C <cluster> auth`) printed
top-level help instead of the auth section's subcommands. The mflags
interspersed-flag resolver rejected the section match because the section's
empty flagset doesn't declare -C; that fix lands in mflags. On this side,
sections now tolerate unknown flags so the no-help form parses and renders
its subcommands via ErrShowHelp instead of erroring.

- cli/commands/help.go: Section flagsets set AllowUnknownFlags(true).
- cli/commands/section_help_test.go: regression test via RegisterAll.
- go.mod: bump miren.dev/mflags to the resolver fix.

Fixes MIR-1309.
@evanphx
evanphx requested a review from a team as a code owner July 9, 2026 23:13
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Section help now uses a dedicated flag set that allows unknown flags before a section name. The mflags dependency is updated, and tests cover multiple global-flag and help argument combinations while verifying that auth sub-command help is rendered.


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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
cli/commands/section_help_test.go (1)

57-79: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Pipe read happens only after Execute returns — risk of deadlock if output exceeds pipe buffer.

os.Pipe() has a fixed OS buffer (~64KB on Linux). Since nothing reads from r until after Execute finishes and w is closed, a subcommand writing more than the buffer size would block forever on write. Fine for today's small help output, but fragile if this helper is reused for larger outputs. Reading concurrently in a goroutine (or draining incrementally) removes the risk.

♻️ Suggested fix using concurrent drain
 	d := mflags.NewDispatcher("miren")
 	RegisterAll(d)
 
 	old := os.Stdout
 	r, w, _ := os.Pipe()
 	os.Stdout = w
 
+	outCh := make(chan string, 1)
+	go func() {
+		var buf bytes.Buffer
+		io.Copy(&buf, r)
+		outCh <- buf.String()
+	}()
+
 	err := d.Execute(args)
 
 	w.Close()
 	os.Stdout = old
 
 	if err != nil {
 		t.Fatalf("Execute(%v) returned error: %v", args, err)
 	}
 
-	var buf bytes.Buffer
-	io.Copy(&buf, r)
-	return buf.String()
+	return <-outCh
 }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/commands/section_help_test.go` around lines 57 - 79, Update
captureDispatch to drain the pipe concurrently while d.Execute(args) runs,
rather than reading from r only after execution completes. Start a goroutine
that copies from r into a buffer, then execute, close w, wait for the reader,
restore os.Stdout safely, and preserve the existing error handling.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cli/commands/section_help_test.go`:
- Around line 57-79: Update captureDispatch to drain the pipe concurrently while
d.Execute(args) runs, rather than reading from r only after execution completes.
Start a goroutine that copies from r into a buffer, then execute, close w, wait
for the reader, restore os.Stdout safely, and preserve the existing error
handling.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 818598d9-6da0-4568-9e52-849046fd4e16

📥 Commits

Reviewing files that changed from the base of the PR and between eb4b8f6 and b8cb333.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (3)
  • cli/commands/help.go
  • cli/commands/section_help_test.go
  • go.mod

@evanphx
evanphx merged commit 5dfc014 into main Jul 10, 2026
18 checks passed
@evanphx
evanphx deleted the mir-1309-miren-help-auth-refuses-to-show-the-subcommands branch July 10, 2026 17:10
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