Skip to content

feat(cmd): add Example fields with validation utilities#61

Merged
feloy merged 7 commits intokortex-hub:mainfrom
feloy:tested-examples
Mar 12, 2026
Merged

feat(cmd): add Example fields with validation utilities#61
feloy merged 7 commits intokortex-hub:mainfrom
feloy:tested-examples

Conversation

@feloy
Copy link
Contributor

@feloy feloy commented Mar 11, 2026

Adds Example fields to init, workspace list, and workspace remove commands to improve help documentation. Includes a validation utility in pkg/cmd/testutil that parses and validates examples against the actual command structure, ensuring examples stay accurate as the
codebase evolves.

The validator catches invalid flags, wrong binary names, invalid subcommands, while correctly allowing valid positional arguments.

Updated AGENTS.md to require examples and validation tests for all new commands.

Adds AdaptExampleForAlias utility function that allows alias commands to inherit examples from their original commands while adapting them to show the alias syntax. The function replaces the original command with the alias only in command lines, preserving comments unchanged.

Applied to list and remove alias commands. Updated AGENTS.md with documentation and usage examples for creating aliases with examples.

Closes #53

@codecov-commenter
Copy link

codecov-commenter commented Mar 11, 2026

Codecov Report

❌ Patch coverage is 86.79245% with 21 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pkg/cmd/testutil/example_validator.go 83.33% 14 Missing and 7 partials ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds Example help text to several Cobra commands, implements parsing and validation utilities for example blocks, adds an alias-adaptation helper, and introduces unit tests to validate examples and alias transformations against the CLI command tree.

Changes

Cohort / File(s) Summary
Docs
AGENTS.md
Adds mandatory Example guidance, format/guidelines, validator flow, alias handling notes, and testing recommendations.
Command Example Fields
pkg/cmd/init.go, pkg/cmd/workspace_list.go, pkg/cmd/workspace_remove.go
Populate Cobra Example fields with usage examples; no runtime behavior changes.
Alias Commands
pkg/cmd/list.go, pkg/cmd/remove.go
Assign alias command Example by adapting original command examples using AdaptExampleForAlias.
Alias Helper
pkg/cmd/helpers.go
New AdaptExampleForAlias(example, originalCmd, aliasCmd string) string to transform example lines for aliases while preserving comments/formatting.
Example Validation Utilities
pkg/cmd/testutil/example_validator.go
New parsing/validation utilities and ExampleCommand type: ParseExampleCommands, ValidateExampleCommand, ValidateCommandExamples to parse example blocks and verify commands/flags against the Cobra tree.
Validation Tests
pkg/cmd/testutil/example_validator_test.go
Unit tests covering parsing, flag forms, positional args, comments, multi-command blocks, and validation error cases.
Command Example Tests
pkg/cmd/init_test.go, pkg/cmd/workspace_list_test.go, pkg/cmd/workspace_remove_test.go
New Test...Cmd_Examples tests asserting Example presence, parsing, expected example counts, and validation against root command.
Alias Helper Tests
pkg/cmd/helpers_test.go
Tests for AdaptExampleForAlias covering replacements, comment preservation, indentation, multiple occurrences, and empty input.

Sequence Diagram(s)

sequenceDiagram
    participant Examples as Example Block
    participant Parser as Example Parser
    participant Validator as Example Validator
    participant Cobra as Cobra Command Tree

    Examples->>Parser: provide multi-line example text
    Parser->>Parser: parse lines into ExampleCommand structs
    Parser->>Validator: deliver parsed ExampleCommand(s)
    Validator->>Cobra: lookup commands/subcommands and flags
    Cobra-->>Validator: return command/flag metadata
    Validator-->>Parser: return validation results (ok / errors)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • feat: init command #23: Adds the init command and its initial tests — closely related because this PR adds Example text and example-validation tests for the same command.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding Example fields and validation utilities for Cobra commands.
Description check ✅ Passed The description explains the addition of Example fields to commands, introduces validation utilities, and describes the AdaptExampleForAlias helper for aliases.
Linked Issues check ✅ Passed All coding requirements from issue #53 are implemented: Example fields added to init/list/remove commands [#53], validation utilities created to parse and validate examples [#53], and alias handling via AdaptExampleForAlias [#53].
Out of Scope Changes check ✅ Passed All changes are directly related to issue #53 requirements: Example fields in commands, validation utilities, alias adaptation logic, and AGENTS.md documentation updates align with stated objectives.

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

📝 Coding Plan for PR comments
  • Generate coding plan

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: 4

🧹 Nitpick comments (1)
pkg/cmd/list.go (1)

21-35: Avoid importing pkg/cmd/testutil into runtime command construction.

NewListCmd() now depends on a package named testutil just to rewrite help text. I'd move AdaptExampleForAlias into pkg/cmd or a neutral helper package and keep the parser/validator helpers in testutil.

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

In `@pkg/cmd/list.go` around lines 21 - 35, NewListCmd imports testutil solely for
AdaptExampleForAlias which couples runtime command construction to test helpers;
move AdaptExampleForAlias into a neutral runtime helper in pkg/cmd (or a new
pkg/cmd/internal/helpers) and update NewListCmd to call that helper instead of
pkg/cmd/testutil. Modify the code that defines AdaptExampleForAlias (currently
in pkg/cmd/testutil) so it is exported from the new location, update references
in NewListCmd to use the new package/function name, and remove the testutil
import from pkg/cmd/list.go so runtime code no longer depends on test-only
utilities.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cmd/testutil/example_validator_test.go`:
- Around line 23-190: Add regression cases to TestParseExampleCommands to assert
ParseExampleCommands returns an error for malformed examples: include tests
named like "extra positional to leaf command" with example `kortex-cli workspace
list extra`, "string flag missing value" with example `kortex-cli init --name`,
and "unmatched quotes" with an example containing a missing closing quote (e.g.,
`kortex-cli init --name "proj`). Place these new entries in the tests slice
inside TestParseExampleCommands and set wantErr: true so the parser
(ParseExampleCommands) is validated to reject extra positional args for leaf
commands, flags that require values but have none, and unbalanced quotation
marks.

In `@pkg/cmd/testutil/example_validator.go`:
- Around line 66-68: splitCommandLine currently accepts lines with unterminated
quotes and must be changed to fail instead; update splitCommandLine to return an
error when it reaches EOF while inQuote (e.g., change signature to return
([]string, error) or otherwise propagate an error) and propagate that error up
in parseCommandLine so parseCommandLine returns an error for inputs like
`kortex-cli init "/tmp/project`. Adjust callers (parseCommandLine and any other
uses) to handle the new error return and ensure ExampleCommand parsing fails on
unterminated quoted arguments.
- Around line 26-31: The ExampleCommand flag handling currently stores every
flag value as a string, losing whether a value was actually provided; update
ExampleCommand to store per-flag metadata (e.g., change Flags from
map[string]string to a map[string]FlagMeta or add a separate map like
FlagPresent map[string]bool and FlagValues map[string]string) so you can
distinguish "no value supplied" vs "empty value supplied"; then update the
validator code that inspects flags (references: ExampleCommand, Flags, the
validation function that checks flag values, and use pflag.Flag.NoOptDefVal) to
treat non-boolean StringVar/StringVarP flags as invalid when the flag was
present but no value was supplied (FlagPresent true && FlagValues[key] == "" &&
pflag.Flag.NoOptDefVal == "") and allow empty values only when
pflag.Flag.NoOptDefVal indicates the flag accepts an explicit empty value;
ensure boolean flags continue to be valid when no value is provided.
- Around line 176-190: In ValidateExampleCommand, after finding the resolved
command (cmd) and remainingArgs, invoke the command's Args validator by calling
cmd.Args(cmd, remainingArgs) and return any error it produces (e.g., handle
cobra.NoArgs, ExactArgs, etc.); replace the current heuristic that only checks
cmd.HasSubCommands() for rejecting unknown args with this Args-based validation
(you may still keep the existing unknown-subcommand error for clearer messages,
but do not accept examples simply because HasSubCommands() is false—use cmd.Args
to decide validity).

---

Nitpick comments:
In `@pkg/cmd/list.go`:
- Around line 21-35: NewListCmd imports testutil solely for AdaptExampleForAlias
which couples runtime command construction to test helpers; move
AdaptExampleForAlias into a neutral runtime helper in pkg/cmd (or a new
pkg/cmd/internal/helpers) and update NewListCmd to call that helper instead of
pkg/cmd/testutil. Modify the code that defines AdaptExampleForAlias (currently
in pkg/cmd/testutil) so it is exported from the new location, update references
in NewListCmd to use the new package/function name, and remove the testutil
import from pkg/cmd/list.go so runtime code no longer depends on test-only
utilities.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d20da726-7278-4e6e-96a9-8c0f6d553b07

📥 Commits

Reviewing files that changed from the base of the PR and between 6ac3c35 and 22390a2.

📒 Files selected for processing (11)
  • AGENTS.md
  • pkg/cmd/init.go
  • pkg/cmd/init_test.go
  • pkg/cmd/list.go
  • pkg/cmd/remove.go
  • pkg/cmd/testutil/example_validator.go
  • pkg/cmd/testutil/example_validator_test.go
  • pkg/cmd/workspace_list.go
  • pkg/cmd/workspace_list_test.go
  • pkg/cmd/workspace_remove.go
  • pkg/cmd/workspace_remove_test.go

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

♻️ Duplicate comments (1)
pkg/cmd/testutil/example_validator_test.go (1)

26-160: ⚠️ Potential issue | 🟡 Minor

Cover malformed parse inputs, not just the wrong-binary path.

TestParseExampleCommands still only asserts one failing case. It should also lock down tokenizer failures like a missing flag value and unbalanced quotes; otherwise those branches in ParseExampleCommands can regress unnoticed.

Suggested table entries
 		{
 			name:    "invalid command - wrong binary",
 			example: `other-cli init`,
 			wantErr: true,
 		},
+		{
+			name:    "string flag missing value",
+			example: `kortex-cli init --name`,
+			wantErr: true,
+		},
+		{
+			name:    "unmatched quotes",
+			example: `kortex-cli init --name "my-project`,
+			wantErr: true,
+		},
 		{
 			name:      "command with multiple flags",
 			example:   `kortex-cli init --name my-project --verbose`,
 			wantCount: 1,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cmd/testutil/example_validator_test.go` around lines 26 - 160, The test
suite TestParseExampleCommands only asserts the wrong-binary error path; add
additional negative test cases to exercise ParseExampleCommands tokenizer
failures (e.g., a command with a long flag missing its value like "kortex-cli
cmd --output", an unbalanced quoted argument like `kortex-cli cmd
"unterminated`, and a short-flag missing value like `kortex-cli cmd -o`) so
those branches return wantErr=true; locate the tests slice in
TestParseExampleCommands and add entries that set example to the malformed
strings and wantErr: true (using the existing
ExampleCommand/ParseExampleCommands flow) to ensure tokenizer and parse errors
are covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cmd/testutil/example_validator_test.go`:
- Around line 432-518: Add a table test case in the tests slice that verifies
only the command prefix is rewritten and not occurrences inside argument values:
create a test entry (use the same fields name, example, originalCmd="workspace
list", aliasCmd="list", want) where example contains a line with the command
prefix "kortex-cli workspace list" and another line with a flag whose value
contains the literal "workspace list" (e.g. kortex-cli workspace list --label
"workspace list"); set want so the command prefix is replaced to "kortex-cli
list" but the quoted flag value remains "workspace list". Ensure the new case is
included alongside the other tests in the tests slice.

---

Duplicate comments:
In `@pkg/cmd/testutil/example_validator_test.go`:
- Around line 26-160: The test suite TestParseExampleCommands only asserts the
wrong-binary error path; add additional negative test cases to exercise
ParseExampleCommands tokenizer failures (e.g., a command with a long flag
missing its value like "kortex-cli cmd --output", an unbalanced quoted argument
like `kortex-cli cmd "unterminated`, and a short-flag missing value like
`kortex-cli cmd -o`) so those branches return wantErr=true; locate the tests
slice in TestParseExampleCommands and add entries that set example to the
malformed strings and wantErr: true (using the existing
ExampleCommand/ParseExampleCommands flow) to ensure tokenizer and parse errors
are covered.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a472f180-846c-47fb-a5cf-f656d4f500e0

📥 Commits

Reviewing files that changed from the base of the PR and between 22390a2 and ba16f8b.

📒 Files selected for processing (1)
  • pkg/cmd/testutil/example_validator_test.go

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

♻️ Duplicate comments (3)
pkg/cmd/testutil/example_validator.go (2)

95-108: ⚠️ Potential issue | 🟠 Major

Keep “value supplied” separate from the parsed value.

hasValue is computed and discarded, so --name, --name=, and --name "" all collapse to "". The check on Line 258 then rejects explicitly-empty values as if the flag were missing a value. Please store that metadata per flag and validate against it instead of flagValue == "".

Suggested direction
 type ExampleCommand struct {
 	Raw         string
 	Binary      string
 	Args        []string
 	FlagPresent map[string]bool
+	FlagHasValue map[string]bool
 	FlagValues  map[string]string
 	Flags       map[string]string
 }
@@
 	cmd := ExampleCommand{
 		Raw:         line,
 		Binary:      parts[0],
 		Args:        []string{},
 		FlagPresent: make(map[string]bool),
+		FlagHasValue: make(map[string]bool),
 		FlagValues:  make(map[string]string),
 		Flags:       make(map[string]string),
 	}
@@
 			flagName, flagValue, hasValue := parseLongFlag(part, parts, &i)
 			cmd.FlagPresent[flagName] = true
+			cmd.FlagHasValue[flagName] = hasValue
 			cmd.FlagValues[flagName] = flagValue
@@
 			flagName, flagValue, hasValue := parseShortFlag(part, parts, &i)
 			cmd.FlagPresent[flagName] = true
+			cmd.FlagHasValue[flagName] = hasValue
 			cmd.FlagValues[flagName] = flagValue
@@
-		flagValue := exampleCmd.FlagValues[flagName]
-		if flagValue == "" && flag.NoOptDefVal == "" && flag.Value.Type() != "bool" {
+		if !exampleCmd.FlagHasValue[flagName] && flag.NoOptDefVal == "" && flag.Value.Type() != "bool" {
 			cmdPath := cmd.CommandPath()
For spf13/pflag / Cobra, how are `--flag`, `--flag=`, and `--flag ""` distinguished for string flags, and what does `pflag.Flag.NoOptDefVal` mean for flags that may omit a value?

Also applies to: 251-265

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

In `@pkg/cmd/testutil/example_validator.go` around lines 95 - 108, The parsing
currently discards the hasValue boolean from parseLongFlag/parseShortFlag
causing `--name`, `--name=`, and `--name ""` to be indistinguishable; add
per-flag metadata (e.g., a new map on the cmd struct like FlagHasValue
map[string]bool) and set FlagHasValue[flagName] = hasValue inside both
parseLongFlag and parseShortFlag handling (alongside existing
FlagPresent/FlagValues/Flags assignments), then update the validation logic that
currently checks flagValue == "" to instead consult FlagHasValue (and
FlagPresent) so you treat explicitly-supplied empty values differently from
omitted values.

68-70: ⚠️ Potential issue | 🟡 Minor

Reject unterminated quoted arguments.

splitCommandLine() still succeeds when EOF is reached with inQuote == true, so malformed examples like kortex-cli init --name "proj are accepted and then validated as if they were real commands.

Suggested fix
-func parseCommandLine(line string) (ExampleCommand, error) {
-	// Split by whitespace, respecting quotes (simple parsing)
-	parts := splitCommandLine(line)
+func parseCommandLine(line string) (ExampleCommand, error) {
+	parts, err := splitCommandLine(line)
+	if err != nil {
+		return ExampleCommand{}, err
+	}
 	if len(parts) == 0 {
 		return ExampleCommand{}, fmt.Errorf("empty command line")
 	}
@@
-func splitCommandLine(line string) []string {
+func splitCommandLine(line string) ([]string, error) {
 	var parts []string
 	var current strings.Builder
 	inQuote := false
 	quoteChar := rune(0)
@@
 	if current.Len() > 0 {
 		parts = append(parts, current.String())
 	}
 
-	return parts
+	if inQuote {
+		return nil, fmt.Errorf("unterminated quoted string")
+	}
+
+	return parts, nil
 }

Also applies to: 155-185

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

In `@pkg/cmd/testutil/example_validator.go` around lines 68 - 70, splitCommandLine
currently accepts input that ends with an open quote (inQuote==true) and returns
a successful parts slice; change splitCommandLine so it detects unterminated
quotes and returns an error (e.g., "unterminated quoted argument") instead of
silently succeeding, and update parseCommandLine to propagate and return that
error from splitCommandLine (so parseCommandLine returns the error for inputs
like `kortex-cli init --name "proj`). Also audit the other parsing usage block
around the second parser logic (the code referenced at the alternative location)
and make the same change there so both call sites validate and reject
unterminated quoted arguments.
pkg/cmd/helpers.go (1)

45-47: ⚠️ Potential issue | 🟡 Minor

Rewrite only the command path.

strings.Replace(..., 1) rewrites the first matching substring anywhere on the line. If originalCmd appears in a flag value before the real command tokens, this mutates the argument instead of the command and produces a broken alias example. Please match and replace the kortex-cli <originalCmd> segment explicitly.

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

In `@pkg/cmd/helpers.go` around lines 45 - 47, The current replacement uses
strings.Replace(line, originalCmd, aliasCmd, 1) which can modify occurrences of
originalCmd in flag values; instead locate the exact "kortex-cli "+originalCmd
segment and replace only that token; e.g., after confirming
strings.HasPrefix(trimmed, "kortex-cli "), compute the prefix segment
("kortex-cli "+originalCmd) and replace that exact substring with "kortex-cli
"+aliasCmd (or use TrimPrefix/strings.HasPrefix on the rest) so only the command
path (variables line, trimmed, originalCmd, aliasCmd) is mutated, leaving flag
values intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cmd/testutil/example_validator.go`:
- Around line 25-33: Replace the exported concrete struct ExampleCommand with an
unexported implementation type (e.g., exampleCommand) and expose a small
exported interface (e.g., ExampleCommandResult) that provides accessors Raw(),
Binary(), Args(), FlagPresent(), FlagValues() and any needed behavior; add a
factory function NewExampleCommand(...) that returns the interface, keep Flags
as internal/deprecated on the unexported struct, and add a compile-time
assurance var _ ExampleCommandResult = (*exampleCommand)(nil) to satisfy the
repo's interface-based design requirements.

---

Duplicate comments:
In `@pkg/cmd/helpers.go`:
- Around line 45-47: The current replacement uses strings.Replace(line,
originalCmd, aliasCmd, 1) which can modify occurrences of originalCmd in flag
values; instead locate the exact "kortex-cli "+originalCmd segment and replace
only that token; e.g., after confirming strings.HasPrefix(trimmed, "kortex-cli
"), compute the prefix segment ("kortex-cli "+originalCmd) and replace that
exact substring with "kortex-cli "+aliasCmd (or use TrimPrefix/strings.HasPrefix
on the rest) so only the command path (variables line, trimmed, originalCmd,
aliasCmd) is mutated, leaving flag values intact.

In `@pkg/cmd/testutil/example_validator.go`:
- Around line 95-108: The parsing currently discards the hasValue boolean from
parseLongFlag/parseShortFlag causing `--name`, `--name=`, and `--name ""` to be
indistinguishable; add per-flag metadata (e.g., a new map on the cmd struct like
FlagHasValue map[string]bool) and set FlagHasValue[flagName] = hasValue inside
both parseLongFlag and parseShortFlag handling (alongside existing
FlagPresent/FlagValues/Flags assignments), then update the validation logic that
currently checks flagValue == "" to instead consult FlagHasValue (and
FlagPresent) so you treat explicitly-supplied empty values differently from
omitted values.
- Around line 68-70: splitCommandLine currently accepts input that ends with an
open quote (inQuote==true) and returns a successful parts slice; change
splitCommandLine so it detects unterminated quotes and returns an error (e.g.,
"unterminated quoted argument") instead of silently succeeding, and update
parseCommandLine to propagate and return that error from splitCommandLine (so
parseCommandLine returns the error for inputs like `kortex-cli init --name
"proj`). Also audit the other parsing usage block around the second parser logic
(the code referenced at the alternative location) and make the same change there
so both call sites validate and reject unterminated quoted arguments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5c71a821-f079-453f-8050-6aaead03d65c

📥 Commits

Reviewing files that changed from the base of the PR and between ba16f8b and c0e806d.

📒 Files selected for processing (7)
  • AGENTS.md
  • pkg/cmd/helpers.go
  • pkg/cmd/helpers_test.go
  • pkg/cmd/list.go
  • pkg/cmd/remove.go
  • pkg/cmd/testutil/example_validator.go
  • pkg/cmd/testutil/example_validator_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/cmd/list.go

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: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cmd/testutil/example_validator_test.go`:
- Around line 209-210: The test fixture incorrectly registers a non-existent
"-f" alias for the production workspace list command; remove the
Flags().StringP("format","f","text",...) call (or replace it with the real
"-o"/"--output" alias) so listCmd only defines the actual output flag via
Flags().String("output",...) and then update any table rows or test cases (the
ones around the second occurrence noted) to use "-o" or "--output" instead of
"-f"/"format" so the tests match the real command behavior.
- Around line 216-230: The test CLI tree (rootCmd, workspaceCmd, initCmd in
example_validator_test.go) has drifted from the real CLI: update the fixture to
mirror the production root (or import/instantiate the real root command) so it
includes the init command's single positional argument and the
--workspace-configuration flag defined in pkg/cmd/init.go, and ensure the
top-level list/remove aliases registered in pkg/cmd/root.go are present (also
apply the same fix for the duplicated fixture at lines 387-401); either replace
the fake rootCmd with the real root constructor or reproduce those exact
flags/positional args and aliases on initCmd and rootCmd so examples validate
against the real CLI surface.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 703289b2-e009-45e3-9c42-c10c6c322d9d

📥 Commits

Reviewing files that changed from the base of the PR and between c0e806d and 539de93.

📒 Files selected for processing (1)
  • pkg/cmd/testutil/example_validator_test.go

@feloy feloy requested review from benoitf and jeffmaury March 12, 2026 08:23
feloy and others added 7 commits March 12, 2026 15:18
Adds Example fields to init, workspace list, and workspace remove
commands to improve help documentation. Includes a validation utility
in pkg/cmd/testutil that parses and validates examples against the
actual command structure, ensuring examples stay accurate as the
codebase evolves.

The validator catches invalid flags, wrong binary names, invalid
subcommands, while correctly allowing valid positional arguments.
Updated AGENTS.md to require examples and validation tests for all
new commands.

Closes kortex-hub#53

Co-Authored-By: Claude Code (Claude Sonnet 4.5) <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
Adds AdaptExampleForAlias utility function that allows alias commands
to inherit examples from their original commands while adapting them
to show the alias syntax. The function replaces the original command
with the alias only in command lines, preserving comments unchanged.

Applied to list and remove alias commands. Updated AGENTS.md with
documentation and usage examples for creating aliases with examples.

Co-Authored-By: Claude Code (Claude Sonnet 4.5) <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
Runtime command code (list.go, remove.go) was importing testutil
solely for AdaptExampleForAlias, which coupled runtime code to
test-only utilities. Moved the function to pkg/cmd/helpers.go
as a neutral runtime helper, along with its tests.

Co-Authored-By: Claude Code (Claude Sonnet 4.5) <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
The ExampleCommand structure now tracks flag presence and values
separately using FlagPresent and FlagValues maps, allowing the
validator to distinguish between flags with no value vs empty
values. This enables validation that string flags requiring values
(NoOptDefVal == "") actually have values provided, while still
allowing boolean flags to be used without values.

Co-Authored-By: Claude Code (Claude Sonnet 4.5) <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
ValidateExampleCommand now invokes cmd.Args(cmd, remainingArgs) to
validate remaining arguments, respecting each command's Args validator
(cobra.NoArgs, cobra.ExactArgs, etc.) instead of only checking
HasSubCommands(). This provides more accurate validation that matches
runtime command behavior.

Co-Authored-By: Claude Code (Claude Sonnet 4.5) <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
@feloy feloy force-pushed the tested-examples branch from 539de93 to 9350940 Compare March 12, 2026 14:18
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.

♻️ Duplicate comments (2)
pkg/cmd/testutil/example_validator_test.go (1)

196-230: ⚠️ Potential issue | 🟠 Major

Build these validator tests from the real command constructors.

These fixtures have already drifted from production: Lines 209-210 invent -f/--format for workspace list, and the init stubs omit production contracts like cobra.MaximumNArgs(1) and --workspace-configuration. That means this suite can certify examples the real NewRootCmd() would reject, or miss valid examples the real CLI accepts. Prefer NewRootCmd() or a single shared fixture kept in lockstep with the production commands.

Also applies to: 387-401

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

In `@pkg/cmd/testutil/example_validator_test.go` around lines 196 - 230, The test
fixture function createTestCommandTree diverges from production command
definitions (it invents flags like -f/--format for workspace list and omits real
contracts such as cobra.MaximumNArgs(1) and --workspace-configuration on init),
so replace the hand-rolled tree with the actual production constructor (call
NewRootCmd() or use the shared fixture used by production) inside the tests;
ensure tests reference the real command tree instead of createTestCommandTree
(or update createTestCommandTree to delegate to NewRootCmd()), preserving real
flags, Args validators and persistent flags for workspace, list, init and root
commands so examples validated by tests match the real CLI behavior.
pkg/cmd/testutil/example_validator.go (1)

69-71: ⚠️ Potential issue | 🟠 Major

Don’t collapse distinct flag syntaxes into the same parsed state.

The parser currently loses too much information: splitCommandLine() drops empty quoted tokens and never errors on EOF inside a quote, while parseCommandLine() throws away hasValue. As a result, --name, --name=, and --name "" collapse into the same state, and malformed input like kortex-cli init --name "proj can still parse as valid. Please preserve empty quoted values, retain an explicit hasValue bit, and fail on unterminated quotes.

Also applies to: 93-108, 155-185, 257-264

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

In `@pkg/cmd/testutil/example_validator.go` around lines 69 - 71, splitCommandLine
currently drops empty quoted tokens and ignores unterminated quotes, and
parseCommandLine discards whether a flag had an explicit value; update
splitCommandLine to preserve empty quoted tokens (return "" for ""), return an
error on EOF inside an open quote, and change its signature to propagate that
error; update parseCommandLine to track an explicit hasValue boolean on parsed
flags/options (distinct from the value string) so --name, --name=, and --name ""
are distinguishable, and ensure parsing logic treats "=" (even with empty RHS)
as hasValue=true while absence of "=" is hasValue=false; update callers to
handle the new error and hasValue flag accordingly (references: splitCommandLine
and parseCommandLine).
🧹 Nitpick comments (1)
pkg/cmd/list.go (1)

34-34: Validate the alias Example once.

Line 34 publishes a different help string than NewWorkspaceListCmd(), so the original command’s example test does not prove the alias help stays executable. A small ValidateCommandExamples(NewRootCmd(), NewListCmd().Example) regression test would catch alias-only breakage in AdaptExampleForAlias().

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

In `@pkg/cmd/list.go` at line 34, The alias help example isn’t being validated:
add a regression test that calls ValidateCommandExamples(NewRootCmd(),
NewListCmd().Example) (or ValidateCommandExamples(NewRootCmd(),
workspaceListCmd.Example) depending on which Example is the alias) to ensure
AdaptExampleForAlias() keeps the alias Example executable; locate
AdaptExampleForAlias, NewWorkspaceListCmd/NewListCmd and
workspaceListCmd.Example in the code and add a unit test that constructs the
root command and validates the alias Example once to catch alias-only breakage.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@pkg/cmd/testutil/example_validator_test.go`:
- Around line 196-230: The test fixture function createTestCommandTree diverges
from production command definitions (it invents flags like -f/--format for
workspace list and omits real contracts such as cobra.MaximumNArgs(1) and
--workspace-configuration on init), so replace the hand-rolled tree with the
actual production constructor (call NewRootCmd() or use the shared fixture used
by production) inside the tests; ensure tests reference the real command tree
instead of createTestCommandTree (or update createTestCommandTree to delegate to
NewRootCmd()), preserving real flags, Args validators and persistent flags for
workspace, list, init and root commands so examples validated by tests match the
real CLI behavior.

In `@pkg/cmd/testutil/example_validator.go`:
- Around line 69-71: splitCommandLine currently drops empty quoted tokens and
ignores unterminated quotes, and parseCommandLine discards whether a flag had an
explicit value; update splitCommandLine to preserve empty quoted tokens (return
"" for ""), return an error on EOF inside an open quote, and change its
signature to propagate that error; update parseCommandLine to track an explicit
hasValue boolean on parsed flags/options (distinct from the value string) so
--name, --name=, and --name "" are distinguishable, and ensure parsing logic
treats "=" (even with empty RHS) as hasValue=true while absence of "=" is
hasValue=false; update callers to handle the new error and hasValue flag
accordingly (references: splitCommandLine and parseCommandLine).

---

Nitpick comments:
In `@pkg/cmd/list.go`:
- Line 34: The alias help example isn’t being validated: add a regression test
that calls ValidateCommandExamples(NewRootCmd(), NewListCmd().Example) (or
ValidateCommandExamples(NewRootCmd(), workspaceListCmd.Example) depending on
which Example is the alias) to ensure AdaptExampleForAlias() keeps the alias
Example executable; locate AdaptExampleForAlias, NewWorkspaceListCmd/NewListCmd
and workspaceListCmd.Example in the code and add a unit test that constructs the
root command and validates the alias Example once to catch alias-only breakage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 150e3af1-0688-40a9-a49b-b7be36e156a2

📥 Commits

Reviewing files that changed from the base of the PR and between 539de93 and 9350940.

📒 Files selected for processing (13)
  • AGENTS.md
  • pkg/cmd/helpers.go
  • pkg/cmd/helpers_test.go
  • pkg/cmd/init.go
  • pkg/cmd/init_test.go
  • pkg/cmd/list.go
  • pkg/cmd/remove.go
  • pkg/cmd/testutil/example_validator.go
  • pkg/cmd/testutil/example_validator_test.go
  • pkg/cmd/workspace_list.go
  • pkg/cmd/workspace_list_test.go
  • pkg/cmd/workspace_remove.go
  • pkg/cmd/workspace_remove_test.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • pkg/cmd/init.go
  • pkg/cmd/helpers.go
  • pkg/cmd/remove.go
  • pkg/cmd/workspace_remove.go
  • pkg/cmd/workspace_remove_test.go
  • pkg/cmd/init_test.go
  • pkg/cmd/workspace_list.go

@feloy feloy merged commit b54bbe0 into kortex-hub:main Mar 12, 2026
6 checks passed
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.

add Example in cobra commands definitions

3 participants