Skip to content

Conversation

@kooksee
Copy link
Contributor

@kooksee kooksee commented Jan 21, 2026

No description provided.

@kooksee kooksee merged commit 2db8f44 into main Jan 21, 2026
1 check passed
@gemini-code-assist
Copy link

Summary of Changes

Hello @kooksee, 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 introduces significant new functionality to the protobuild tool, including a web-based UI for configuration, interactive project setup, and environment diagnostics. It also features a major internal refactoring of configuration handling, enhancing the tool's architecture and extensibility. The accompanying documentation updates ensure users can easily adopt these new capabilities.

Highlights

  • New Commands Introduced: Three new commands have been added: 'web' for a web-based configuration UI, 'init' for interactive project initialization with templates, and 'doctor' for diagnosing the development environment and dependencies.
  • Configuration Refactoring: The internal configuration structures (Config, Plugin, Depend, Linter) have been refactored into a new 'internal/config' package, improving modularity and maintainability.
  • Enhanced Documentation: The README files (English and Chinese) have been significantly updated to include detailed usage instructions for the new commands and a new 'Roadmap' section outlining future features.
  • Version Update: The project version has been bumped from v0.0.29 to v0.1.1, indicating a new minor release with these substantial changes.
  • Protoc-gen-retag Integration: The 'protoc-gen-retag' plugin is now explicitly integrated, allowing for custom struct tags (e.g., XML, validation) to be added to generated Go code via proto options, as demonstrated in new example files.

🧠 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.

Ignored Files
  • Ignored by pattern: .github/workflows/** (2)
    • .github/workflows/lint.yml
    • .github/workflows/release.yml
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.

Copy link

@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 introduces significant new features to the protobuild tool, including init and doctor commands for project initialization and environment diagnostics, and a web command that launches a web-based UI for visual configuration editing, dependency management, plugin configuration, and proto file browsing. The changes involve adding new Go files for these commands and their web server implementation, updating README.md and README_CN.md to document these new features and a project roadmap, and refactoring internal configuration types into a new internal/config package. Additionally, the protoc-gen-retag plugin's options handling is adjusted, and the project version is updated to v0.1.1. Review comments suggest improving the escapeJSON function in the web UI by using json.Marshal for robustness, optimizing the runDoctor command to avoid redundant checks by caching results, and considering caching or asynchronous processing for handleProjectStats to enhance performance for large projects.

Comment on lines +428 to +434
func escapeJSON(s string) string {
s = strings.ReplaceAll(s, "\\", "\\\\")
s = strings.ReplaceAll(s, "\"", "\\\"")
s = strings.ReplaceAll(s, "\n", "\\n")
s = strings.ReplaceAll(s, "\r", "\\r")
s = strings.ReplaceAll(s, "\t", "\\t")
return s

Choose a reason for hiding this comment

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

high

escapeJSON 函数手动实现了对 JSON 字符串的转义,这可能无法覆盖所有边界情况,容易出错。建议使用标准库 encoding/json 中的 json.Marshal 来进行更安全、更健壮的 JSON 序列化。

Suggested change
func escapeJSON(s string) string {
s = strings.ReplaceAll(s, "\\", "\\\\")
s = strings.ReplaceAll(s, "\"", "\\\"")
s = strings.ReplaceAll(s, "\n", "\\n")
s = strings.ReplaceAll(s, "\r", "\\r")
s = strings.ReplaceAll(s, "\t", "\\t")
return s
func escapeJSON(s string) string {
b, err := json.Marshal(s)
if err != nil {
// Fallback for safety, though Marshal on a string should not fail.
return `"` + strings.ReplaceAll(s, `"`, `\"`) + `"`
}
return string(b)
}

Comment on lines +125 to +145
if len(issues) > 0 {
fmt.Printf("❌ 发现 %d 个问题需要修复:\n", len(issues))
for _, item := range issues {
result := item.Check()
fmt.Printf(" • %s: %s\n", item.Name, result.Message)
if result.Help != "" {
fmt.Printf(" 💡 %s\n", result.Help)
}
}
}

if len(warnings) > 0 {
fmt.Printf("⚠️ 发现 %d 个可选组件未安装:\n", len(warnings))
for _, item := range warnings {
result := item.Check()
fmt.Printf(" • %s: %s\n", item.Name, result.Message)
if result.Help != "" {
fmt.Printf(" 💡 %s\n", result.Help)
}
}
}

Choose a reason for hiding this comment

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

medium

runDoctor 函数中,对于检查失败的项,item.Check() 被调用了两次:一次是在主循环中确定状态,另一次是在打印修复建议时。这会导致不必要的重复检查,尤其当检查操作比较耗时(如执行外部命令)时,会影响性能。

建议将第一次检查的结果存储起来,在后续打印信息时复用。例如,可以将 issueswarnings 的类型从 []checkItem 改为 []struct { item checkItem; result checkResult },这样就可以存储并复用第一次的检查结果。

Comment on lines +494 to +554
func (s *Server) handleProjectStats(w http.ResponseWriter, r *http.Request) {
s.mu.RLock()
cfg := s.config
s.mu.RUnlock()

stats := ProjectStats{
ProtoRoots: cfg.Root,
VendorDir: cfg.Vendor,
DependencyCount: len(cfg.Depends),
PluginCount: len(cfg.Plugins),
}

baseDir := filepath.Dir(s.configPath)

// Count proto files in root directories
for _, root := range cfg.Root {
rootPath := filepath.Join(baseDir, root)
filepath.Walk(rootPath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return nil
}
if !info.IsDir() && strings.HasSuffix(path, ".proto") {
stats.ProtoFiles++

// Count lines, messages, and services
content, err := os.ReadFile(path)
if err == nil {
lines := strings.Split(string(content), "\n")
stats.TotalLines += len(lines)

for _, line := range lines {
trimmed := strings.TrimSpace(line)
if strings.HasPrefix(trimmed, "message ") {
stats.MessageCount++
} else if strings.HasPrefix(trimmed, "service ") {
stats.ServiceCount++
}
}
}
}
return nil
})
}

// Count vendor files
if cfg.Vendor != "" {
vendorPath := filepath.Join(baseDir, cfg.Vendor)
filepath.Walk(vendorPath, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return nil
}
if !info.IsDir() && strings.HasSuffix(path, ".proto") {
stats.VendorFiles++
}
return nil
})
}

w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(stats)
}

Choose a reason for hiding this comment

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

medium

handleProjectStats 函数通过遍历文件系统来实时计算项目统计信息。对于包含大量文件的大型项目,这可能会导致响应缓慢,影响 Web UI 的用户体验。为了提升性能,可以考虑引入缓存机制,或者将统计信息计算作为后台任务异步执行。

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