Skip to content

Conversation

@alpe
Copy link
Contributor

@alpe alpe commented Jan 28, 2026

Resolves #3024

  • --evnode.rpc.address was existing already to point to a remote server
  • added -o for structured json output. default is text as before

@github-actions
Copy link
Contributor

github-actions bot commented Jan 28, 2026

The latest Buf updates on your PR. Results from workflow CI / buf-check (pull_request).

BuildFormatLintBreakingUpdated (UTC)
✅ passed⏩ skipped✅ passed✅ passedJan 28, 2026, 3:39 PM

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @alpe, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the net-info command by providing a new option for structured JSON output, which is crucial for programmatic consumption and integration with other tools. It also refines the handling of RPC addresses to be more robust and user-friendly, ensuring that connections are established correctly even when the protocol prefix is omitted. These changes improve the utility and reliability of the network information command.

Highlights

  • Structured JSON Output: Introduced a new --output (or -o) flag for the net-info command, allowing users to specify 'json' as an output format. The default remains 'text'.
  • Improved RPC Address Handling: The RPC address parsing now automatically prepends 'http://' to the base URL if no protocol (http:// or https://) is explicitly provided, making the configuration more flexible.
  • Refactored RPC Calls: The GetPeerInfo RPC call has been moved and is now executed once, with its result being used for both the text and the newly added JSON output formats, improving code efficiency.
  • New formatJson Function: A dedicated formatJson helper function was added to handle the serialization of network information (NetInfo and PeerInfo) into a well-structured, indented JSON format.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@claude
Copy link
Contributor

claude bot commented Jan 28, 2026

Claude finished @alpe's task in 1m 52s —— View job


Code Review Complete

I've completed a comprehensive review of PR #3029. The implementation successfully adds JSON output support and improves RPC address handling. Below are my findings organized by priority.


Critical Issues

1. Missing Output Format Validation (pkg/cmd/p2p.go:83-85)

Priority: High | Category: Error Handling

The current implementation silently falls back to text output for any unsupported format value. This creates a poor user experience and makes typos hard to detect.

if outputFormat == "json" {
    return formatJson(cmd.OutOrStdout(), netInfo, peerResp)
}
// Falls through to text output for ANY other value

Recommendation:

switch outputFormat {
case "json":
    return formatJson(cmd.OutOrStdout(), netInfo, peerResp)
case "text":
    // proceed with text output
default:
    return fmt.Errorf("unsupported output format: %q, expected 'text' or 'json'", outputFormat)
}

Fix this →


Major Issues

2. Missing Test Coverage for New JSON Feature (30% patch coverage)

Priority: High | Category: Testing

The PR adds 40 lines of new code (JSON formatting logic and flag handling), but the existing tests in pkg/cmd/p2p_test.go only test the text output format. This explains the low 30% patch coverage reported by Codecov.

Missing test cases:

  • JSON output format (-o json)
  • Invalid output format validation (e.g., -o yaml)
  • RPC address with explicit http:// prefix
  • RPC address with https:// prefix
  • Empty peer list in JSON format

Recommendation: Add tests following the existing pattern:

func TestNetInfoCmd_JSONOutput(t *testing.T) {
    // Test JSON output with peers
}

func TestNetInfoCmd_JSONOutput_NoPeers(t *testing.T) {
    // Test JSON output without peers
}

func TestNetInfoCmd_InvalidOutputFormat(t *testing.T) {
    // Test error handling for invalid format
}

func TestNetInfoCmd_HTTPSAddress(t *testing.T) {
    // Test RPC address with https:// prefix
}

Add tests →%20JSON%20output%20with%20peers%2C%202)%20JSON%20output%20without%20peers%2C%203)%20invalid%20output%20format%20validation%2C%204)%20RPC%20address%20handling%20with%20http%3A%2F%2F%20and%20https%3A%2F%2F%20prefixes.%20Follow%20the%20existing%20test%20patterns%20in%20the%20file.&repo=evstack%2Fev-node&branch=alex%2Fremote_netinfo)


3. Function Coupling to Connect Library (pkg/cmd/p2p.go:134)

Priority: Medium | Category: Architecture

The formatJson function accepts *connect.Response[pb.GetPeerInfoResponse] instead of just the peer slice []*pb.PeerInfo. This couples the formatting logic unnecessarily to the Connect RPC library.

Current signature:

func formatJson(w io.Writer, netInfo *pb.NetInfo, peerResp *connect.Response[pb.GetPeerInfoResponse]) error

Recommended signature:

func formatJson(w io.Writer, netInfo *pb.NetInfo, peers []*pb.PeerInfo) error

Benefits:

  • Clearer function purpose (formats data, doesn't know about RPC)
  • Easier to test (no need to construct Connect response objects)
  • Better separation of concerns

Call site update:

if outputFormat == "json" {
    return formatJson(cmd.OutOrStdout(), netInfo, peerResp.Msg.Peers)
}

Fix this →%20Change%20formatJson%20function%20signature%20from%20%60connect.Response%5Bpb.GetPeerInfoResponse%5D%60%20to%20%60%5B%5Dpb.PeerInfo%60%20at%20line%20134%2C%202)%20Update%20the%20call%20site%20at%20line%2084%20to%20pass%20%60peerResp.Msg.Peers%60%20directly%2C%203)%20Update%20function%20body%20at%20line%20145%20to%20use%20the%20peers%20parameter%20directly&repo=evstack%2Fev-node&branch=alex%2Fremote_netinfo)


Minor Issues

4. Inconsistent Error Message Format (pkg/cmd/p2p.go:65, 75)

Priority: Low | Category: Code Quality

Error messages changed from verbose "error calling GetNetInfo RPC: %w" to terse "GetNetInfo RPC: %w". While shorter is sometimes better, the new format loses clarity about what operation failed.

Before:

return fmt.Errorf("error calling GetNetInfo RPC: %w", err)

After:

return fmt.Errorf("GetNetInfo RPC: %w", err)

Recommendation: Consider consistency with other commands in the codebase. If brevity is preferred project-wide, this is acceptable. Otherwise, consider:

return fmt.Errorf("failed to call GetNetInfo RPC: %w", err)

5. Context Usage Improvement (pkg/cmd/p2p.go:61, 71)

Priority: Low | Category: Code Quality

Good improvement replacing context.Background() with cmd.Context(). This enables proper cancellation when users interrupt the command (Ctrl+C).

Well done - This change properly respects command lifecycle and user interrupts.


6. Potential Nil Dereference (pkg/cmd/p2p.go:145-146)

Priority: Low | Category: Defensive Programming

While the RPC layer likely ensures peerResp.Msg is not nil, defensive nil checking would make the code more robust:

func formatJson(w io.Writer, netInfo *pb.NetInfo, peerResp *connect.Response[pb.GetPeerInfoResponse]) error {
    if peerResp == nil || peerResp.Msg == nil {
        return fmt.Errorf("invalid peer response")
    }
    // ... rest of function
}

However, if the RPC contract guarantees non-nil responses on success, this may be unnecessary. Check the Connect library's guarantees.


Positive Observations

  1. Clean RPC Address Handling (lines 48-51): The auto-prepending of http:// is user-friendly and handles the common case where users omit the protocol.

  2. Efficient Allocation (line 145): Pre-allocating the peers slice with the correct capacity (make([]peerJSON, 0, len(peerResp.Msg.Peers))) is good practice.

  3. Readable JSON Output (lines 158-160): Using SetIndent for pretty-printing makes the JSON output human-readable, which is excellent for CLI tools.

  4. Proper Error Wrapping: All errors use %w for proper error chain support.


Architecture & Design

The overall design is clean and follows Go idioms well:

  • ✅ Clear separation between output formatting and business logic
  • ✅ Proper use of io.Writer for testability
  • ✅ Intermediate JSON types avoid exposing protobuf details
  • ✅ Flag handling follows Cobra conventions

Security Considerations

No significant security issues identified:

  • ✅ No sensitive data logged
  • ✅ RPC address handling doesn't introduce injection risks
  • ✅ JSON encoding is safe (using standard library)
  • ⚠️ Consider: RPC calls to arbitrary addresses could be a concern if this command runs with elevated privileges, but this seems like expected behavior for a network info tool

Performance Considerations

No performance concerns:

  • ✅ Efficient memory usage (pre-allocated slices)
  • ✅ Single pass over peers data
  • ✅ No unnecessary allocations in hot paths

Summary

This is a solid feature addition that improves the tool's automation capabilities. The implementation is clean and follows Go best practices. The main areas for improvement are:

  1. Critical: Add output format validation (switch statement)
  2. Major: Add comprehensive test coverage for JSON output
  3. Medium: Decouple formatJson from Connect library types

The 30% patch coverage is the most significant concern - the new JSON functionality should have dedicated test cases to ensure reliability.


Todo List

  • Read the changed file (pkg/cmd/p2p.go)
  • Analyze the implementation against Go best practices
  • Review error handling and resilience
  • Check security considerations
  • Assess test coverage and reliability
  • Provide comprehensive review feedback

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request successfully introduces structured JSON output for the net-info command, which is a valuable enhancement. The implementation is clean, adding a new -o flag and separating the JSON formatting logic. The refactoring to handle RPC addresses more flexibly and to fetch data before formatting is also well done. I have a couple of suggestions to improve the robustness of the output format handling and to refine the new JSON formatting function for better decoupling and testability.

Comment on lines +83 to +85
if outputFormat == "json" {
return formatJson(cmd.OutOrStdout(), netInfo, peerResp)
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The current implementation falls back to text output for any unsupported output format. It would be more user-friendly to validate the output flag and return an error for unsupported values. A switch statement can make this logic cleaner and more robust.

Additionally, to improve the formatJson function's signature and reduce its coupling to connect types, you can pass peerResp.Msg.Peers directly instead of the whole peerResp object.

Suggested change
if outputFormat == "json" {
return formatJson(cmd.OutOrStdout(), netInfo, peerResp)
}
switch outputFormat {
case "json":
return formatJson(cmd.OutOrStdout(), netInfo, peerResp.Msg.Peers)
case "text":
// valid format, proceed to text output
default:
return fmt.Errorf("unsupported output format: %q, please use 'text' or 'json'", outputFormat)
}

Comment on lines +134 to +151
func formatJson(w io.Writer, netInfo *pb.NetInfo, peerResp *connect.Response[pb.GetPeerInfoResponse]) error {
type peerJSON struct {
ID string `json:"id"`
Address string `json:"address"`
}
type netInfoJSON struct {
NodeID string `json:"node_id"`
ListenAddresses []string `json:"listen_addresses"`
Peers []peerJSON `json:"peers"`
}

peers := make([]peerJSON, 0, len(peerResp.Msg.Peers))
for _, peer := range peerResp.Msg.Peers {
peers = append(peers, peerJSON{
ID: peer.Id,
Address: peer.Address,
})
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

To align with the suggested change at the call site, the function signature should be updated to accept []*pb.PeerInfo directly, rather than the *connect.Response wrapper. This makes the function's purpose clearer, decouples it from the connect library, and simplifies testing.

Suggested change
func formatJson(w io.Writer, netInfo *pb.NetInfo, peerResp *connect.Response[pb.GetPeerInfoResponse]) error {
type peerJSON struct {
ID string `json:"id"`
Address string `json:"address"`
}
type netInfoJSON struct {
NodeID string `json:"node_id"`
ListenAddresses []string `json:"listen_addresses"`
Peers []peerJSON `json:"peers"`
}
peers := make([]peerJSON, 0, len(peerResp.Msg.Peers))
for _, peer := range peerResp.Msg.Peers {
peers = append(peers, peerJSON{
ID: peer.Id,
Address: peer.Address,
})
}
func formatJson(w io.Writer, netInfo *pb.NetInfo, peerInfos []*pb.PeerInfo) error {
type peerJSON struct {
ID string `json:"id"`
Address string `json:"address"`
}
type netInfoJSON struct {
NodeID string `json:"node_id"`
ListenAddresses []string `json:"listen_addresses"`
Peers []peerJSON `json:"peers"`
}
peers := make([]peerJSON, 0, len(peerInfos))
for _, peer := range peerInfos {
peers = append(peers, peerJSON{
ID: peer.Id,
Address: peer.Address,
})
}

@codecov
Copy link

codecov bot commented Jan 28, 2026

Codecov Report

❌ Patch coverage is 30.00000% with 28 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.45%. Comparing base (4252154) to head (121e16f).

Files with missing lines Patch % Lines
pkg/cmd/p2p.go 30.00% 25 Missing and 3 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3029      +/-   ##
==========================================
- Coverage   55.55%   55.45%   -0.11%     
==========================================
  Files         116      116              
  Lines       11477    11507      +30     
==========================================
+ Hits         6376     6381       +5     
- Misses       4401     4424      +23     
- Partials      700      702       +2     
Flag Coverage Δ
combined 55.45% <30.00%> (-0.11%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@alpe alpe changed the title Add structured output for net-info feat: Add structured output for net-info Jan 28, 2026
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.

[FEATURE] better net-info command

3 participants