Skip to content

chore: initial setup Go CLI with Cobra framework#2

Merged
feloy merged 9 commits intokortex-hub:mainfrom
feloy:cli2
Feb 27, 2026
Merged

chore: initial setup Go CLI with Cobra framework#2
feloy merged 9 commits intokortex-hub:mainfrom
feloy:cli2

Conversation

@feloy
Copy link
Copy Markdown
Contributor

@feloy feloy commented Feb 27, 2026

  • Bootstrap kortex-cli with Go and cobra library
  • Add .gitignore for Go build artifacts
  • Add version command
  • Add unit tests
  • Add copyright headers

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 27, 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

Initializes a Go Cobra CLI: adds module config and .gitignore, a CLI entry point, Cobra root and version commands, a version package constant, and unit tests for main and command behaviors.

Changes

Cohort / File(s) Summary
Project Configuration
\.gitignore, go.mod
Adds ignores for build artifacts and configures the Go module and dependencies (Cobra and indirect deps).
CLI Entry Point & Tests
cmd/kortex-cli/main.go, cmd/kortex-cli/main_test.go
Adds main() that calls cmd.Execute() and a test invoking main with the version subcommand to ensure it doesn't panic.
Command Framework & Tests
pkg/cmd/root.go, pkg/cmd/root_test.go, pkg/cmd/version.go, pkg/cmd/version_test.go
Introduces Cobra rootCmd with public Execute(), a version subcommand wired to rootCmd, and tests validating command initialization, help/exec flows, and presence of version command.
Version Package
pkg/version/version.go
Adds exported Version variable initialized to 0.1.0-next used by the version command.

Sequence Diagram

sequenceDiagram
    participant User as User/Shell
    participant Main as main.go
    participant Execute as cmd.Execute()
    participant RootCmd as rootCmd
    participant VersionCmd as versionCmd
    participant VersionPkg as version.Version

    User->>Main: run CLI executable
    Main->>Execute: Invoke Execute()
    Execute->>RootCmd: Execute rootCmd
    Note over RootCmd: parse args & route
    User->>RootCmd: "version" arg
    RootCmd->>VersionCmd: dispatch to version
    VersionCmd->>VersionPkg: read Version
    VersionPkg-->>VersionCmd: return "0.1.0-next"
    VersionCmd-->>User: print version output
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% 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 directly reflects the main purpose of the PR: establishing initial Go CLI infrastructure with the Cobra framework, which is confirmed by the changes including go.mod dependencies, cmd/main.go entry point, pkg/cmd/root.go and version.go command structure, and comprehensive unit tests.
Description check ✅ Passed The pull request description accurately summarizes the changeset, covering the bootstrap of kortex-cli with Go and Cobra, addition of .gitignore, version command, unit tests, and copyright headers.

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


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
Copy Markdown

@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: 3

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

Inline comments:
In `@cmd/root.go`:
- Around line 15-19: The Execute function currently prints errors manually which
duplicates Cobra's own error output; in the Execute() function remove the
explicit fmt.Fprintln(os.Stderr, err) call (leave the err check and os.Exit(1)
so the process still exits on error) and rely on rootCmd/Cobra to handle error
printing.

In `@cmd/version.go`:
- Around line 11-16: The version command currently uses fmt.Printf and accepts
any args; change the cobra command definition for versionCmd to enforce no args
by adding Args: cobra.NoArgs and switch the output call inside the Run function
from fmt.Printf(...) to cmd.Printf(...) so the command validates unexpected
arguments and uses Cobra's configured output writer (reference symbols:
versionCmd, Args: cobra.NoArgs, Run func, cmd.Printf vs fmt.Printf).

In `@go.mod`:
- Around line 3-10: The go.mod declares "go 1.25.7" but CI/workflows may use a
different Go version; update your CI to explicitly install/use Go 1.25.7 so
builds/tests match the module setting—e.g., set the setup action or Docker image
to use go-version 1.25.7 in the workflow(s) that run builds/tests and update any
matrix entries that reference other Go versions to include 1.25.7; if the repo
uses container images or Makefile toolchains, ensure those are aligned as well
so "go 1.25.7" in go.mod is enforced across all CI runs.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f3b4662 and 9915153.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (5)
  • .gitignore
  • cmd/root.go
  • cmd/version.go
  • go.mod
  • main.go

@benoitf benoitf changed the title Initial setup: Go CLI with Cobra framework chore: Initial setup Go CLI with Cobra framework Feb 27, 2026
feloy and others added 5 commits February 27, 2026 09:57
- Initialize module as github.com/kortex-hub/kortex-cli
- Add root command for launching and managing AI agents
- Add version command (0.1.0-next)
- Configure Cobra command structure
- Add .gitignore for Go build artifacts

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Signed-off-by: Philippe Martin <phmartin@redhat.com>
Update version command to reject unexpected arguments and use Cobra's
output writer for better testability and framework integration.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Signed-off-by: Philippe Martin <phmartin@redhat.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown

@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)
pkg/cmd/root.go (1)

20-22: Remove empty init() until needed.

This keeps the file tighter and avoids dead placeholder hooks.

Optional cleanup
-func init() {
-	// Global flags can be added here
-}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cmd/root.go` around lines 20 - 22, Remove the empty init() function
defined as init() — delete the entire empty init() block (the no-op global
initializer) so there are no dead placeholder hooks; confirm there are no side
effects or dependencies expecting this init() before removing, then run `go
vet`/build to ensure nothing breaks.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/cmd/root.go`:
- Around line 20-22: Remove the empty init() function defined as init() — delete
the entire empty init() block (the no-op global initializer) so there are no
dead placeholder hooks; confirm there are no side effects or dependencies
expecting this init() before removing, then run `go vet`/build to ensure nothing
breaks.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e72cf4f and d2bdff7.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • .gitignore
  • cmd/kortex-cli/main.go
  • go.mod
  • pkg/cmd/root.go
  • pkg/cmd/version.go
  • pkg/version/version.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • .gitignore
  • go.mod

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Signed-off-by: Philippe Martin <phmartin@redhat.com>
Copy link
Copy Markdown

@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)
cmd/kortex-cli/main_test.go (1)

8-18: Consider capturing stdout to verify actual output.

This smoke test correctly saves/restores os.Args and verifies no panic occurs, which is a reasonable starting point. However, the test would pass even if the version subcommand printed nothing or incorrect output.

For more robust coverage, consider capturing stdout and asserting on the expected version string:

♻️ Suggested improvement with output verification
 package main
 
 import (
+	"bytes"
+	"io"
 	"os"
+	"strings"
 	"testing"
 )
 
 func TestMain_VersionSubcommand(t *testing.T) {
 	// Save original os.Args and restore after test
 	oldArgs := os.Args
 	defer func() { os.Args = oldArgs }()
 
+	// Capture stdout
+	oldStdout := os.Stdout
+	r, w, _ := os.Pipe()
+	os.Stdout = w
+
 	// Set os.Args to call the version subcommand
 	os.Args = []string{"kortex-cli", "version"}
 
-	// Call main() - test passes if it doesn't panic
+	// Call main()
 	main()
+
+	// Restore stdout and read captured output
+	w.Close()
+	os.Stdout = oldStdout
+	var buf bytes.Buffer
+	io.Copy(&buf, r)
+
+	// Verify output contains version info
+	if !strings.Contains(buf.String(), "0.1.0") {
+		t.Errorf("expected version output to contain '0.1.0', got: %s", buf.String())
+	}
 }

Note: If any code path (e.g., error handling in Execute()) calls os.Exit(), it will terminate the test process entirely. This is a common Go testing caveat—consider verifying that successful commands don't invoke os.Exit().

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

In `@cmd/kortex-cli/main_test.go` around lines 8 - 18, Update
TestMain_VersionSubcommand to capture and assert stdout rather than only
checking no panic: create a pipe or use bytes.Buffer to redirect os.Stdout, run
the same os.Args setup and call main() (or the command entry like
Execute()/rootCmd.Execute() if available), restore os.Stdout, and assert the
captured output contains the expected version string; also ensure the test
avoids os.Exit terminating the process by invoking the command entrypoint that
returns an error instead of exiting or by mocking/stubbing any code path that
calls os.Exit().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@cmd/kortex-cli/main_test.go`:
- Around line 8-18: Update TestMain_VersionSubcommand to capture and assert
stdout rather than only checking no panic: create a pipe or use bytes.Buffer to
redirect os.Stdout, run the same os.Args setup and call main() (or the command
entry like Execute()/rootCmd.Execute() if available), restore os.Stdout, and
assert the captured output contains the expected version string; also ensure the
test avoids os.Exit terminating the process by invoking the command entrypoint
that returns an error instead of exiting or by mocking/stubbing any code path
that calls os.Exit().

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d2bdff7 and 0dc928d.

📒 Files selected for processing (1)
  • cmd/kortex-cli/main_test.go

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Signed-off-by: Philippe Martin <phmartin@redhat.com>
Copy link
Copy Markdown
Contributor

@benoitf benoitf left a comment

Choose a reason for hiding this comment

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

looks OK, only missing copyright headers

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

Signed-off-by: Philippe Martin <phmartin@redhat.com>
@feloy feloy requested a review from benoitf February 27, 2026 10:31
Copy link
Copy Markdown

@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 (2)
pkg/cmd/root_test.go (1)

35-69: These execution tests should assert output and share a helper.

Lines 50 and 68 call Execute() and only verify “no panic”; they don’t validate command behavior. Also, the arg/output setup is duplicated. Consider a small helper that executes rootCmd with SetArgs, returns output, and lets each test assert expected text (e.g., usage/help).

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

In `@pkg/cmd/root_test.go` around lines 35 - 69, Replace the duplicated os.Args
and output-redirection logic in TestExecute_WithHelp and TestExecute_NoArgs with
a small helper (e.g., runRootCmd(args []string) string) that uses
rootCmd.SetArgs(args), captures rootCmd.Out via SetOut to a bytes.Buffer, calls
Execute() (or rootCmd.Execute() if more appropriate), restores output, and
returns buf.String(); then update each test to call this helper and assert the
returned string contains the expected text (e.g., "help" or "Usage") instead of
only ensuring no panic; reference TestExecute_WithHelp, TestExecute_NoArgs,
rootCmd, Execute(), rootCmd.SetArgs and rootCmd.SetOut when making the changes.
pkg/cmd/version_test.go (1)

39-55: Strengthen this test to assert behavior and avoid os.Exit path.

Line 54 calls Execute() (the wrapper in pkg/cmd/root.go) which exits the process on error, and the test currently doesn’t assert the version output. Prefer executing rootCmd directly with test args and asserting emitted content.

✅ Suggested refactor
 import (
 	"bytes"
-	"os"
+	"strings"
 	"testing"
 )
@@
 func TestExecute_WithVersion(t *testing.T) {
-	// Save original os.Args and restore after test
-	oldArgs := os.Args
-	defer func() { os.Args = oldArgs }()
-
-	// Set os.Args to call version subcommand
-	os.Args = []string{"kortex-cli", "version"}
-
-	// Redirect output to avoid cluttering test output
+	// Redirect output and execute command directly
 	oldStdout := rootCmd.OutOrStdout()
+	oldStderr := rootCmd.ErrOrStderr()
 	buf := new(bytes.Buffer)
 	rootCmd.SetOut(buf)
+	rootCmd.SetErr(buf)
+	rootCmd.SetArgs([]string{"version"})
-	defer rootCmd.SetOut(oldStdout)
+	defer func() {
+		rootCmd.SetOut(oldStdout)
+		rootCmd.SetErr(oldStderr)
+		rootCmd.SetArgs(nil)
+	}()
 
-	// Call Execute() - test passes if it doesn't panic
-	Execute()
+	if err := rootCmd.Execute(); err != nil {
+		t.Fatalf("unexpected execute error: %v", err)
+	}
+	if !strings.Contains(buf.String(), "0.1.0-next") {
+		t.Fatalf("expected version output, got: %q", buf.String())
+	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cmd/version_test.go` around lines 39 - 55, Update TestExecute_WithVersion
to avoid calling the Execute() wrapper (which can os.Exit) and instead run the
cobra rootCmd directly: set rootCmd.SetOut(buf) and
rootCmd.SetArgs([]string{"version"}), call rootCmd.ExecuteC(), assert the call
returns no error, and assert the captured buffer (buf.String()) contains the
expected version substring; keep restoring any modified state (original os.Args,
rootCmd output) and reference TestExecute_WithVersion, Execute(), and rootCmd in
your changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/cmd/root_test.go`:
- Around line 35-69: Replace the duplicated os.Args and output-redirection logic
in TestExecute_WithHelp and TestExecute_NoArgs with a small helper (e.g.,
runRootCmd(args []string) string) that uses rootCmd.SetArgs(args), captures
rootCmd.Out via SetOut to a bytes.Buffer, calls Execute() (or rootCmd.Execute()
if more appropriate), restores output, and returns buf.String(); then update
each test to call this helper and assert the returned string contains the
expected text (e.g., "help" or "Usage") instead of only ensuring no panic;
reference TestExecute_WithHelp, TestExecute_NoArgs, rootCmd, Execute(),
rootCmd.SetArgs and rootCmd.SetOut when making the changes.

In `@pkg/cmd/version_test.go`:
- Around line 39-55: Update TestExecute_WithVersion to avoid calling the
Execute() wrapper (which can os.Exit) and instead run the cobra rootCmd
directly: set rootCmd.SetOut(buf) and rootCmd.SetArgs([]string{"version"}), call
rootCmd.ExecuteC(), assert the call returns no error, and assert the captured
buffer (buf.String()) contains the expected version substring; keep restoring
any modified state (original os.Args, rootCmd output) and reference
TestExecute_WithVersion, Execute(), and rootCmd in your changes.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0dc928d and fc785ee.

📒 Files selected for processing (7)
  • cmd/kortex-cli/main.go
  • cmd/kortex-cli/main_test.go
  • pkg/cmd/root.go
  • pkg/cmd/root_test.go
  • pkg/cmd/version.go
  • pkg/cmd/version_test.go
  • pkg/version/version.go
🚧 Files skipped from review as they are similar to previous changes (4)
  • pkg/cmd/version.go
  • pkg/cmd/root.go
  • cmd/kortex-cli/main_test.go
  • cmd/kortex-cli/main.go

@feloy feloy changed the title chore: Initial setup Go CLI with Cobra framework chore: initial setup Go CLI with Cobra framework Feb 27, 2026
Copy link
Copy Markdown
Contributor

@jeffmaury jeffmaury left a comment

Choose a reason for hiding this comment

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

LGTM

Co-authored-by: Jeff MAURY <jmaury@redhat.com>
Signed-off-by: Philippe Martin <phmartin@redhat.com>
@feloy feloy merged commit 7c01aba into kortex-hub:main Feb 27, 2026
3 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.

3 participants