Skip to content

Conversation

weibaohui
Copy link
Owner

helm 从SDK 升级为二进制命令方式

- 新增 HelmCmd 实现,通过调用 helm 二进制命令完成 Helm 接口功能
- 修改控制器逻辑,默认使用 HelmCmd 替代原有 SDK 实现
- 移除不必要的 pq 依赖并添加 yaml.v2 依赖
- 添加 Helm 接口文档说明支持多实现方式
feat(models): 添加 HelmChart 的 BatchSave 方法以支持批量保存
- 将 Helm 相关接口和实现从使用 helm.sh/Release 改为自定义的 models.Release
- 修改 runAndLog 方法支持标准输入参数
- 优化安装和升级逻辑,统一处理标准输入
- 修复 helm 命令执行时的错误处理
删除不再使用的图表图标和应用信息链接,统一使用更简洁的字段名显示状态信息
Copy link
Contributor

coderabbitai bot commented Jun 29, 2025

Warning

Rate limit exceeded

@weibaohui has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 13 minutes and 0 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 727ed57 and 9e79ca3.

📒 Files selected for processing (7)
  • main.go (1 hunks)
  • pkg/helm/helm.go (1 hunks)
  • pkg/helm/helm_cmd.go (1 hunks)
  • ui/public/pages/helm/release.json (12 hunks)
  • ui/src/components/Amis/custom/Helm/HelmUpdateRealease.tsx (2 hunks)
  • ui/src/components/Amis/custom/Helm/HelmViewRelease.tsx (1 hunks)
  • ui/src/components/Amis/index.tsx (3 hunks)
📝 Walkthrough

Summary by CodeRabbit

  • 新功能

    • 支持通过命名空间、发布名和修订号获取 Helm Release 的参数值和安装说明。
    • 新增 Helm Release 详情和参数查看组件,提升 Helm Release 详情展示能力。
    • 后端支持 Helm Release 元数据的持久化存储与查询。
  • 功能优化

    • Release 列表和详情页面字段结构简化,移除图标和部分链接,提升信息聚合度。
    • Release 参数和历史对比视图优化为单一参数展示,提升易用性。
    • Helm Release 升级操作简化,仅支持参数编辑,无需选择版本。
  • Bug 修复

    • 修复 Helm Release 操作的同步与错误提示,提升用户反馈及时性。
  • 技术重构

    • 后端 Helm 客户端由 SDK 切换为直接调用 Helm CLI,增强兼容性和日志能力。
    • Helm Release 相关接口和数据结构重构,提升维护性和扩展性。
  • 构建与部署

    • Docker 镜像新增 Helm 3 安装,确保运行环境兼容 Helm CLI。
    • 镜像依赖包和权限处理优化,提升镜像安全性与可用性。

Summary by CodeRabbit

  • 新功能

    • 新增基于 Helm CLI 的 Helm 客户端实现,支持仓库管理、Release 安装/升级/卸载、历史查询、Chart 版本和默认值获取等操作。
    • 支持 Helm Chart 的批量保存和自定义 Release 数据结构。
    • 新增支持获取 Helm Release 的备注和配置信息(可按修订版本)。
    • Helm Release 列表和历史支持自定义模型展示,字段更清晰。
    • 新增接口支持根据命名空间、发布名称和修订号获取指定 Helm Release 的参数值。
    • 新增 Release 详情页支持查看 Release Notes 和参数值。
    • 后台新增 HelmRelease 数据库模型及其增删改查方法,实现 Release 元数据持久化。
    • 新增 Helm Release 详情与参数查看组件,支持 YAML 格式展示。
    • 新增 Helm Release 获取指定修订版本参数和备注的 POST 路由。
  • 功能优化

    • Release 列表排序方式调整为按更新时间升序。
    • Release 安装操作由异步改为同步,出错时立即返回错误信息。
    • Helm 相关操作切换为通过 Helm CLI 执行,提升兼容性和日志可追溯性。
    • Release 升级流程简化,仅支持直接编辑当前参数值,无需版本选择。
    • Release 相关 API 参数简化,统一命名空间和名称传递方式。
    • Release 详情抽屉字段简化,移除 Chart 图标及应用主页/源码链接,字段展示更加简洁。
    • 安装时间字段移除,更新时间字段优化。
    • Release 参数视图由对比编辑器调整为单一 YAML 视图,提升易用性。
    • 统一 Release 相关接口参数,提升一致性和易用性。
  • 依赖变更

    • 新增 YAML 解析库依赖,调整部分依赖声明方式。
  • 修复与调整

    • Release 安装、卸载、升级等操作流程优化,错误即时反馈。
    • Release 数据结构与接口字段统一,提升兼容性和稳定性。
    • 依赖声明中移除 github.com/lib/pq 直接依赖,作为间接依赖保留。
  • 构建与部署

    • Docker 镜像新增 Helm 3 安装,支持 Helm 相关操作。
    • 镜像基础包依赖优化,提升运行环境兼容性。
  • 数据库

    • 新增 Helm Release 元数据表,支持 Release 信息持久化和批量操作。
  • 其他

    • 依赖包和代码结构调整,提升系统维护性和扩展性。

Walkthrough

本次变更重构 Helm 功能,移除原 Helm SDK 实现,新增基于 Helm CLI 的 HelmCmd 实现,支持仓库管理、Release 操作及历史查询。新增 HelmRelease 数据模型及数据库操作。前端新增 Release 参数查看组件,UI 字段简化,新增获取指定修订版本参数和备注的接口及路由。依赖声明调整,新增 YAML 解析库。

Changes

文件/路径分组 变更简述
go.mod 移除 github.com/lib/pq 直接依赖,新增 gopkg.in/yaml.v2 直接依赖。
pkg/controller/helm/helm.go getHelm 改为返回 Helm CLI 包装实例,移除集群 REST 配置相关逻辑。
pkg/controller/helm/helm_release.go Release 排序改为自定义模型按更新时间升序,安装改同步执行,新增获取 Release 备注和值接口,升级接口简化。
pkg/helm/helm.go 移除原 Helm 客户端实现,仅保留接口定义,接口方法签名调整,新增获取备注和值方法。
pkg/helm/helm_cmd.go 新增 HelmCmd 实现,基于 Helm CLI 执行仓库、Release、Chart 操作,集成数据库同步和日志。
pkg/models/helm_chart.go 新增 HelmChart 批量保存方法,新增 Release 和 ReleaseHistory 结构体。
pkg/models/helm_release.go 新增 HelmRelease 结构体及其数据库操作方法,实现 Release 元数据持久化。
pkg/models/migrate.go 新增 HelmRelease 模型自动迁移支持。
pkg/models/helm_repository.go 移除 HelmRepository 结构体中 Content 字段。
ui/public/pages/helm/release.json Release 详情 UI 字段简化,移除图标及链接,字段引用平坦化,时间字段调整。
main.go 新增 Helm Release 获取指定修订版本参数和值的 POST 路由。
ui/src/components/Amis/custom/Helm/HelmUpdateRealease.tsx 移除版本选择及多参数加载逻辑,改为直接获取并编辑当前 Release 的值,提交升级请求简化。
ui/src/components/Amis/custom/Helm/HelmViewRelease.tsx 新增组件用于展示 Helm Release 详情及安装参数,支持按命名空间、发布名、修订号异步加载参数值。
ui/src/components/Amis/index.tsx 新增 HelmViewRelease 组件注册,支持在 AMIS 中使用 helmViewRelease 渲染器。
Dockerfile / Dockerfile.action 优化镜像构建流程,新增 Helm 3 安装及版本验证步骤。

Sequence Diagram(s)

sequenceDiagram
    participant 用户
    participant Controller
    participant Helm接口
    participant HelmCmd
    participant 数据库

    用户->>Controller: 请求 Release 列表/安装/卸载/升级/获取备注/获取参数
    Controller->>Helm接口: 调用 Release/Repo/Chart 方法
    Helm接口->>HelmCmd: 通过 CLI 执行命令
    HelmCmd->>数据库: 同步仓库/Chart 元数据(如需)
    HelmCmd->>HelmCmd: 解析 CLI 输出(JSON/YAML)
    HelmCmd-->>Helm接口: 返回 Release/Chart 数据或操作结果
    Helm接口-->>Controller: 返回处理结果
    Controller-->>用户: 返回响应
Loading

Poem

🐇
Helm 命令舞轻盈,
CLI 助我展宏图。
Release 模型新颜貌,
参数视图更清晰。
批量存储 Chart 信息,
依赖整理更明晰。
代码跃进,兔子欢欣!

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate Unit Tests
  • Create PR with Unit Tests
  • Post Copyable Unit Tests in Comment
  • Commit Unit Tests in branch helm

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai auto-generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

修改UninstallRelease方法签名,增加namespace参数
更新所有调用处传递namespace参数
修复helm client实现中的参数顺序错误
Copy link
Contributor

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

🔭 Outside diff range comments (1)
ui/public/pages/helm/release.json (1)

352-371: 历史视图中的字段引用不一致。

历史视图仍在使用旧的嵌套字段引用如 chart.metadata.versioninfo.status,这些可能与新的简化 Release 模型不兼容,可能导致显示问题。

需要将这些字段更新为与新模型一致:

                      {
-                        "name": "chart.metadata.version",
+                        "name": "chart",
                        "label": "应用版本",
                        "type": "text"
                      },
                      {
-                        "name": "info.status",
+                        "name": "status",
                        "label": "状态",
🧹 Nitpick comments (3)
pkg/models/helm_chart.go (1)

33-33: 修正注释中的错误实体类型。

注释中提到的 "InspectionCheckEvent" 应该是 "HelmChart"。

-// BatchSave 批量保存 InspectionCheckEvent 实例
+// BatchSave 批量保存 HelmChart 实例
pkg/controller/helm/helm.go (1)

19-28: 清理注释代码并确认架构变更。

从基于集群 REST 配置的方法切换到直接的 CLI 命令包装器是一个重大的架构变更。建议删除注释的代码而不是保留,以保持代码库的整洁。

-	// if namespace == "" {
-	// 	namespace = "default"
-	// }
-	// selectedCluster, err := amis.GetSelectedCluster(c)
-	// if err != nil {
-	// 	amis.WriteJsonError(c, err)
-	// 	return nil, err
-	// }
-	// restConfig := service.ClusterService().GetClusterByID(selectedCluster).GetRestConfig()
-	// h, err := helm.New(restConfig, namespace)
-	// return h, err
	cmd := helm.NewHelmCmd("helm")
	return cmd, nil

新的 CLI 方法简化了 Helm 客户端的创建过程。

pkg/helm/helm_cmd.go (1)

43-43: 使用结构化日志而非 fmt.Printf

建议使用 klog 进行日志记录,以保持与项目其他部分的一致性。

-	fmt.Printf("[helm-cmd] exec: %s\n", cmdStr)
+	klog.V(6).Infof("[helm-cmd] exec: %s", cmdStr)

-	fmt.Printf("[helm-cmd] stdout: %s\n", stdout.String())
+	klog.V(6).Infof("[helm-cmd] stdout: %s", stdout.String())

-	fmt.Printf("[helm-cmd] stderr: %s\n", stderr.String())
+	klog.V(6).Infof("[helm-cmd] stderr: %s", stderr.String())

Also applies to: 53-58

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2cce697 and f09edf3.

📒 Files selected for processing (7)
  • go.mod (2 hunks)
  • pkg/controller/helm/helm.go (1 hunks)
  • pkg/controller/helm/helm_release.go (3 hunks)
  • pkg/helm/helm.go (3 hunks)
  • pkg/helm/helm_cmd.go (1 hunks)
  • pkg/models/helm_chart.go (2 hunks)
  • ui/public/pages/helm/release.json (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
pkg/controller/helm/helm_release.go (1)
pkg/models/helm_chart.go (1)
  • Release (49-57)
pkg/controller/helm/helm.go (1)
pkg/helm/helm_cmd.go (1)
  • NewHelmCmd (30-38)
pkg/helm/helm.go (1)
pkg/models/helm_chart.go (1)
  • Release (49-57)
pkg/helm/helm_cmd.go (5)
pkg/controller/helm/helm_repo.go (2)
  • AddOrUpdateRepo (28-55)
  • UpdateReposIndex (100-125)
pkg/models/helm_repository.go (1)
  • HelmRepository (11-31)
internal/dao/conn.go (1)
  • DB (176-182)
pkg/models/helm_chart.go (2)
  • HelmChart (11-27)
  • Release (49-57)
pkg/controller/helm/helm_release.go (3)
  • InstallRelease (62-103)
  • UninstallRelease (106-127)
  • UpgradeRelease (164-198)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (7)
go.mod (1)

35-35: 依赖变更支持新的 Helm CLI 实现。

添加 gopkg.in/yaml.v2 作为直接依赖合理,用于解析 Helm CLI 的 YAML 输出。将 github.com/lib/pq 移至间接依赖表明新的 CLI 方法不再直接使用它。这些变更与从 SDK 到 CLI 的架构转换一致。

Also applies to: 130-130

pkg/models/helm_chart.go (1)

49-57: 新的 Release 数据模型简化了 Helm 发布表示。

引入自定义 Release 结构体将复杂的 Helm SDK 类型简化为基本字符串字段,这与新的 CLI 方法很好地对齐。Chart 字段改为字符串类型的设计合理,便于处理 CLI 输出。

ui/public/pages/helm/release.json (1)

139-139: UI 字段引用已更新以匹配新的 Release 模型。

主要的 release 列表视图正确更新为使用简化的字段(statuschartapp_versionupdated),与新的数据模型保持一致。

Also applies to: 148-148, 276-276, 281-281, 435-435, 452-452

pkg/controller/helm/helm_release.go (2)

43-54: 验证排序方向的变更是否有意为之。

排序逻辑从降序改为升序(it.Before(jt)),这会影响用户看到的 release 顺序。请确认这个变更是有意的,因为用户通常期望看到最新的 release 在前面。

另外,时间解析格式非常具体且脆弱。建议增加错误处理的健壮性:

	slice.SortBy(list, func(i, j *models.Release) bool {
-		it, err := time.Parse("2006-01-02 15:04:05.000000 -0700 MST", i.Updated)
+		it, err := time.Parse(time.RFC3339, i.Updated)
		if err != nil {
+			klog.Warningf("Failed to parse time %s: %v", i.Updated, err)
			return false
		}
-		jt, err := time.Parse("2006-01-02 15:04:05.000000 -0700 MST", j.Updated)
+		jt, err := time.Parse(time.RFC3339, j.Updated)
		if err != nil {
+			klog.Warningf("Failed to parse time %s: %v", j.Updated, err)
			return false
		}
-		return it.Before(jt)
+		return it.After(jt)  // 如果需要保持降序
	})

95-100: 同步安装提供了更好的错误处理。

从异步 goroutine 改为同步调用可以立即处理和返回错误,提供更好的用户反馈。这是一个积极的改进,尽管可能会稍微影响响应时间。

pkg/helm/helm.go (2)

28-31: 文档注释清晰明了

注释清楚地说明了 Helm 接口支持多种实现方式,有助于代码维护者理解设计意图。


41-41: 验证通过:GetReleaseList 调用已全部更新

已检查所有 GetReleaseList() 的调用点(pkg/helm/helm_cmd.go、pkg/helm/helm.go、pkg/controller/helm/helm_release.go),均已使用 []*models.Release,未发现仍在引用 release.Release。接口变更已正确适配,无需进一步修改。

扩展Release结构体字段,新增ReleaseHistory类型
添加获取release notes和values的接口
优化helm release历史记录展示字段
将HELM_CACHE_HOME环境变量的设置从全局os.Setenv改为在命令执行时设置,避免影响其他命令的执行环境
Copy link
Contributor

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

♻️ Duplicate comments (8)
pkg/helm/helm_cmd.go (8)

39-60: 改进命令执行的安全性

当前实现使用 sh -c 执行命令,这可能导致命令注入漏洞。建议直接使用 exec.Command 而不是通过 shell。

此外,错误处理逻辑有问题:即使命令成功,如果有 stderr 输出也会返回错误。

 func (h *HelmCmd) runAndLog(args []string, stdin string) ([]byte, error) {
 	cmdStr := h.HelmBin + " " + strings.Join(args, " ")
 	fmt.Printf("[helm-cmd] exec: %s\n", cmdStr)
-	// cmd := exec.Command(h.HelmBin, args...)
-	cmd := exec.Command("sh", "-c", cmdStr)
+	cmd := exec.Command(h.HelmBin, args...)
 	if stdin != "" {
 		cmd.Stdin = strings.NewReader(stdin)
 	}
 	var stdout, stderr bytes.Buffer
 	cmd.Stdout = &stdout
 	cmd.Stderr = &stderr
 	err := cmd.Run()
 	if stdout.Len() > 0 {
 		fmt.Printf("[helm-cmd] stdout: %s\n", stdout.String())
 	}
 	if stderr.Len() > 0 {
 		fmt.Printf("[helm-cmd] stderr: %s\n", stderr.String())
-		err = fmt.Errorf(stderr.String())
+		// 只有在命令执行失败时才将 stderr 作为错误
+		if err != nil {
+			err = fmt.Errorf("command failed: %v, stderr: %s", err, stderr.String())
+		}
 	}
 	return stdout.Bytes(), err
 }

42-42: 避免记录敏感信息

当前代码会将包含密码的完整命令记录到日志中,这是一个安全风险。

 func (h *HelmCmd) runAndLog(args []string, stdin string) ([]byte, error) {
-	cmdStr := h.HelmBin + " " + strings.Join(args, " ")
-	fmt.Printf("[helm-cmd] exec: %s\n", cmdStr)
+	// 构建安全的日志字符串,隐藏敏感参数
+	safeArgs := make([]string, len(args))
+	copy(safeArgs, args)
+	for i := 0; i < len(safeArgs)-1; i++ {
+		if safeArgs[i] == "--password" {
+			safeArgs[i+1] = "***"
+		}
+	}
+	cmdStr := h.HelmBin + " " + strings.Join(safeArgs, " ")
+	fmt.Printf("[helm-cmd] exec: %s\n", cmdStr)

87-87: 避免直接使用 os.Setenv

在并发环境中,os.Setenv 会影响整个进程的环境变量,可能导致竞态条件。建议为每个命令设置独立的环境变量。

建议修改 runAndLog 方法以支持环境变量:

func (h *HelmCmd) runAndLogWithEnv(args []string, stdin string, env map[string]string) ([]byte, error) {
    cmd := exec.Command(h.HelmBin, args...)
    cmd.Env = os.Environ()
    for k, v := range env {
        cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", k, v))
    }
    // ... 其余代码
}

106-111: 返回值顺序不符合 Go 惯例

Go 的惯例是将 error 作为最后一个返回值。当前实现返回 (error, bool),应该改为 (bool, error)

-func (h *HelmCmd) updateRepoByName(repoEntry *repo.Entry, helmRepo *models.HelmRepository) (error, bool) {
+func (h *HelmCmd) updateRepoByName(repoEntry *repo.Entry, helmRepo *models.HelmRepository) (bool, error) {
 	// 4. helm repo update
 	out, err := h.runAndLog([]string{"repo", "update", repoEntry.Name}, "")
 	if err != nil {
-		return fmt.Errorf("helm repo update failed: %v, output: %s", err, string(out)), true
+		return true, fmt.Errorf("helm repo update failed: %v, output: %s", err, string(out))
 	}

相应地更新调用处:

-	err2, done := h.updateRepoByName(repoEntry, helmRepo)
+	done, err2 := h.updateRepoByName(repoEntry, helmRepo)

127-127: 使用 repository_id 而非 repository_name 删除记录

当前使用 repository_name 删除记录可能不够精确,特别是当存在同名但不同 URL 的仓库时。建议使用 repository_id 以确保准确性。

-	dao.DB().Where("repository_name = ?", repoEntry.Name).Delete(models.HelmChart{})
+	dao.DB().Where("repository_id = ?", helmRepo.ID).Delete(&models.HelmChart{})

217-217: UpgradeRelease 方法中的 chartRef 构造错误

使用 releaseName 作为 chart 名称是错误的。应该先获取 release 的历史记录,从中提取正确的 chart 名称。

 func (h *HelmCmd) UpgradeRelease(releaseName, repoName, targetVersion string, values ...string) error {
-	chartRef := fmt.Sprintf("%s/%s", repoName, releaseName)
+	// 需要先获取 release 信息以确定 chart 名称
+	// 注意:当前方法签名缺少 namespace 参数
+	// 建议修改方法签名以包含 namespace
 	args := []string{"upgrade", releaseName, chartRef, "--version", targetVersion}

注意:此方法签名与接口定义不一致,接口中没有 namespace 参数,但实际执行 helm 命令时需要指定 namespace。


243-243: 移除硬编码的 stderr 重定向

在命令参数中硬编码 2>/dev/null 依赖于 shell 特性,这与之前建议的直接使用 exec.Command 不兼容。

-	args := []string{"search", "repo", chartRef, "-o", "json", "--versions", "2>/dev/null"}
+	args := []string{"search", "repo", chartRef, "-o", "json", "--versions"}

289-289: 处理 updateRepoByName 的返回值

调用 updateRepoByName 但忽略了其返回值,应该处理可能的错误。

-		h.updateRepoByName(repoEntry, item)
+		done, err := h.updateRepoByName(repoEntry, item)
+		if err != nil {
+			klog.Errorf("Failed to update repo %s: %v", item.Name, err)
+		}
🧹 Nitpick comments (2)
pkg/helm/helm.go (1)

8-539: 建议删除注释代码而非保留

整个 SDK 实现已被注释,既然已经切换到二进制命令方式,建议完全删除这些注释代码,以保持代码库的整洁。如果需要保留历史记录,Git 版本控制已经提供了这个功能。

-// import (
-//
-//	"errors"
-//	"fmt"
-...
-// func debug(format string, v ...interface{}) {
-// 	klog.V(6).Infof(format, v...)
-// }
pkg/helm/helm_cmd.go (1)

128-172: 优化批量保存逻辑

当前实现逐个保存 chart,对于包含大量 chart 的仓库可能效率较低。建议使用批量保存来提高性能。

+	var charts []models.HelmChart
 	for chartName, versionList := range index.Entries {
 		if len(versionList) == 0 {
 			continue
 		}
 		slice.SortBy(versionList, func(a *repo.ChartVersion, b *repo.ChartVersion) bool {
 			return a.Created.After(b.Created)
 		})
 		ct := versionList[0]
 		if ct.Metadata != nil {
 			m := models.HelmChart{
 				RepositoryID:   helmRepo.ID,
 				RepositoryName: helmRepo.Name,
 				Name:           chartName,
 				// ... 其他字段
 			}
-			err = m.Save(nil)
-			if err != nil {
-				fmt.Printf("[helm-cmd] warn: save helm chart to database error: %v\n", err)
-			}
+			charts = append(charts, m)
 		}
 	}
+	// 批量保存
+	if len(charts) > 0 {
+		if err := dao.DB().CreateInBatches(charts, 100).Error; err != nil {
+			return fmt.Errorf("batch save helm charts error: %v", err)
+		}
+	}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f09edf3 and 23e0e75.

📒 Files selected for processing (5)
  • pkg/controller/helm/helm_release.go (6 hunks)
  • pkg/helm/helm.go (1 hunks)
  • pkg/helm/helm_cmd.go (1 hunks)
  • pkg/models/helm_chart.go (2 hunks)
  • ui/public/pages/helm/release.json (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
  • ui/public/pages/helm/release.json
  • pkg/models/helm_chart.go
  • pkg/controller/helm/helm_release.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)

将updateRepoByName函数的返回值顺序从(error, bool)改为(bool, error)以符合Go语言惯例
简化AddOrUpdateRepo函数中的错误处理逻辑
将helm命令的环境变量设置改为追加模式,避免覆盖系统原有环境变量
Copy link
Contributor

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

♻️ Duplicate comments (7)
pkg/helm/helm_cmd.go (7)

42-42: 避免在日志中记录敏感信息

当前代码会将完整的命令字符串打印到日志中,这可能包含密码等敏感信息。


45-45: 严重安全问题:命令注入风险

使用 sh -c 执行拼接的命令字符串存在命令注入漏洞。攻击者可能通过特殊构造的输入执行任意命令。


114-115: 潜在的路径遍历安全风险

直接使用用户输入的 repoEntry.Name 构造文件路径可能导致路径遍历攻击。


217-217: 错误:使用 releaseName 构造 chartRef

使用 releaseName 作为 chart 名称是错误的。Release 名称和 Chart 名称可能不同。


243-243: 移除硬编码的 stderr 重定向

在命令参数中硬编码 2>/dev/null 不会生效,因为这是 shell 特性。


289-289: 处理 updateRepoByName 的错误返回值

当前代码忽略了 updateRepoByName 的错误返回值,可能导致更新失败时没有任何提示。

建议修改:

-		_, _ = h.updateRepoByName(repoEntry, item)
+		_, err := h.updateRepoByName(repoEntry, item)
+		if err != nil {
+			klog.Errorf("Failed to update repo %s: %v", item.Name, err)
+		}

40-63: 改进命令执行的安全性和错误处理

当前实现存在多个问题需要修复:

  1. 使用 sh -c 执行命令存在命令注入风险
  2. 错误处理逻辑不正确:stderr 有输出不一定表示错误

建议修改如下:

 func (h *HelmCmd) runAndLog(args []string, stdin string) ([]byte, error) {
 	cmdStr := h.HelmBin + " " + strings.Join(args, " ")
-	fmt.Printf("[helm-cmd] exec: %s\n", cmdStr)
-	// cmd := exec.Command(h.HelmBin, args...)
-
-	cmd := exec.Command("sh", "-c", cmdStr)
+	// 移除敏感信息的日志记录
+	klog.V(6).Infof("[helm-cmd] exec: %s %s", h.HelmBin, maskSensitiveArgs(args))
+	cmd := exec.Command(h.HelmBin, args...)
 	cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", "HELM_CACHE_HOME", h.repoCacheDir))
 
 	if stdin != "" {
 		cmd.Stdin = strings.NewReader(stdin)
 	}
 	var stdout, stderr bytes.Buffer
 	cmd.Stdout = &stdout
 	cmd.Stderr = &stderr
 	err := cmd.Run()
 	if stdout.Len() > 0 {
-		fmt.Printf("[helm-cmd] stdout: %s\n", stdout.String())
+		klog.V(6).Infof("[helm-cmd] stdout: %s", stdout.String())
 	}
 	if stderr.Len() > 0 {
-		fmt.Printf("[helm-cmd] stderr: %s\n", stderr.String())
-		err = fmt.Errorf(stderr.String())
+		klog.V(6).Infof("[helm-cmd] stderr: %s", stderr.String())
+		// 只有在命令执行失败时才将 stderr 作为错误
+		if err != nil {
+			err = fmt.Errorf("command failed: %v, stderr: %s", err, stderr.String())
+		}
 	}
 	return stdout.Bytes(), err
 }
+
+// maskSensitiveArgs 隐藏命令参数中的敏感信息
+func maskSensitiveArgs(args []string) []string {
+	masked := make([]string, len(args))
+	copy(masked, args)
+	for i := 0; i < len(masked); i++ {
+		if i > 0 && (masked[i-1] == "--password" || masked[i-1] == "--username") {
+			masked[i] = "***"
+		}
+	}
+	return masked
+}
🧹 Nitpick comments (2)
pkg/helm/helm_cmd.go (2)

88-94: 建议使用更安全的方式传递凭据

当前通过命令行参数传递用户名和密码,这些信息可能被系统进程列表(如 ps 命令)暴露。

考虑使用环境变量或配置文件传递敏感信息:

 args := []string{"repo", "add", repoEntry.Name, repoEntry.URL}
-if repoEntry.Username != "" {
-	args = append(args, "--username", repoEntry.Username)
-}
-if repoEntry.Password != "" {
-	args = append(args, "--password", repoEntry.Password)
-}
+// 使用配置文件传递凭据
+if repoEntry.Username != "" || repoEntry.Password != "" {
+	configFile, err := h.createTempRepoConfig(repoEntry)
+	if err != nil {
+		return fmt.Errorf("create temp config failed: %v", err)
+	}
+	defer os.Remove(configFile)
+	args = append(args, "--repo-config", configFile)
+}

295-326: 代码重复:考虑提取通用的 JSON 命令执行方法

多个方法(GetReleaseList、GetReleaseNote、GetReleaseValues 等)都遵循相同的模式:执行命令、获取 JSON 输出、解析结果。

建议提取一个通用方法减少代码重复:

// runJSONCommand 执行 helm 命令并返回 JSON 输出
func (h *HelmCmd) runJSONCommand(args []string) ([]byte, error) {
    args = append(args, "-o", "json")
    out, err := h.runAndLog(args, "")
    if err != nil {
        return nil, fmt.Errorf("helm %s failed: %v, output: %s", args[0], err, string(out))
    }
    return out, nil
}

// 使用示例
func (h *HelmCmd) GetReleaseList() ([]*models.Release, error) {
    out, err := h.runJSONCommand([]string{"list", "-A"})
    if err != nil {
        return nil, err
    }
    var releases []*models.Release
    if err := json.Unmarshal(out, &releases); err != nil {
        return nil, fmt.Errorf("unmarshal helm list output failed: %v", err)
    }
    return releases, nil
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23e0e75 and be7ecd8.

📒 Files selected for processing (1)
  • pkg/helm/helm_cmd.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)

添加新的API接口用于获取指定版本的release值
将GetReleaseValues和GetReleaseValuesWithRevision的输出格式从json改为yaml
简化UpgradeRelease接口参数,移除repo和version字段
优化前端HelmUpdateRelease组件,移除版本选择逻辑
Copy link
Contributor

@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

♻️ Duplicate comments (6)
pkg/helm/helm.go (1)

8-539: 建议删除注释代码而非保留

整个 SDK 实现已被注释掉。根据 PR 描述,这是从 SDK 迁移到二进制命令方式的一部分。建议完全删除这些注释代码,以保持代码库整洁。

如果确认不再需要 SDK 实现,建议:

  1. 删除所有注释代码(第8-539行)
  2. 在文件顶部添加说明,指出现在使用 HelmCmd 实现
  3. 或者将这些代码移到单独的废弃文件中以备参考
pkg/helm/helm_cmd.go (5)

288-288: 处理 updateRepoByName 的错误

虽然使用 _, _ 显式忽略了返回值,但建议至少记录错误信息以便调试。


40-63: 严重安全问题:命令注入风险

使用 sh -c 执行命令存在命令注入漏洞。攻击者可能通过特殊构造的参数执行任意命令。

必须修改为直接使用 exec.Command

 func (h *HelmCmd) runAndLog(args []string, stdin string) ([]byte, error) {
     cmdStr := h.HelmBin + " " + strings.Join(args, " ")
-    fmt.Printf("[helm-cmd] exec: %s\n", cmdStr)
-    // cmd := exec.Command(h.HelmBin, args...)
-
-    cmd := exec.Command("sh", "-c", cmdStr)
+    // 只记录命令用于调试,但要注意不记录敏感信息
+    safeArgs := make([]string, len(args))
+    copy(safeArgs, args)
+    for i, arg := range safeArgs {
+        if i > 0 && (args[i-1] == "--password" || args[i-1] == "--username") {
+            safeArgs[i] = "***"
+        }
+    }
+    fmt.Printf("[helm-cmd] exec: %s %s\n", h.HelmBin, strings.Join(safeArgs, " "))
+    
+    cmd := exec.Command(h.HelmBin, args...)
     cmd.Env = append(os.Environ(), fmt.Sprintf("%s=%s", "HELM_CACHE_HOME", h.repoCacheDir))
 
     if stdin != "" {
         cmd.Stdin = strings.NewReader(stdin)
     }
     var stdout, stderr bytes.Buffer
     cmd.Stdout = &stdout
     cmd.Stderr = &stderr
     err := cmd.Run()
     if stdout.Len() > 0 {
         fmt.Printf("[helm-cmd] stdout: %s\n", stdout.String())
     }
     if stderr.Len() > 0 {
         fmt.Printf("[helm-cmd] stderr: %s\n", stderr.String())
-        err = fmt.Errorf(stderr.String())
+        // 只在命令失败时将 stderr 作为错误信息
+        if err != nil {
+            err = fmt.Errorf("command failed: %v, stderr: %s", err, stderr.String())
+        }
     }
     return stdout.Bytes(), err
 }

88-94: 避免在日志中暴露敏感信息

当前实现会在日志中记录密码等敏感信息。

参见第40-63行的修复建议,其中包含了对敏感参数的处理。


114-115: 验证仓库名称以防止路径遍历

虽然路径是在缓存目录内构建的,但仍应验证仓库名称以防止路径遍历攻击。

添加仓库名称验证:

+    // 验证仓库名称,防止路径遍历
+    if strings.Contains(repoEntry.Name, "..") || strings.Contains(repoEntry.Name, "/") {
+        return false, fmt.Errorf("invalid repository name: %s", repoEntry.Name)
+    }
+    
     cachePath := fmt.Sprintf("%s/repository/%s-index.yaml", h.repoCacheDir, repoEntry.Name)

242-242: 移除硬编码的 stderr 重定向

在命令参数中包含 2>/dev/null 依赖于 shell 特性,与建议的直接使用 exec.Command 不兼容。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between be7ecd8 and c725041.

📒 Files selected for processing (5)
  • main.go (1 hunks)
  • pkg/controller/helm/helm_release.go (9 hunks)
  • pkg/helm/helm.go (1 hunks)
  • pkg/helm/helm_cmd.go (1 hunks)
  • ui/src/components/Amis/custom/Helm/HelmUpdateRealease.tsx (4 hunks)
✅ Files skipped from review due to trivial changes (1)
  • main.go
🧰 Additional context used
🧬 Code Graph Analysis (2)
pkg/helm/helm.go (4)
pkg/controller/helm/helm_repo.go (2)
  • AddOrUpdateRepo (28-55)
  • UpdateReposIndex (100-125)
pkg/models/helm_chart.go (2)
  • ReleaseHistory (59-65)
  • Release (49-58)
pkg/controller/helm/helm_release.go (5)
  • InstallRelease (62-103)
  • UninstallRelease (106-127)
  • UpgradeRelease (213-245)
  • GetReleaseNote (130-146)
  • GetReleaseValues (149-176)
pkg/controller/helm/helm_chart.go (1)
  • GetChartValue (26-46)
pkg/controller/helm/helm_release.go (1)
pkg/models/helm_chart.go (1)
  • Release (49-58)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (3)
ui/src/components/Amis/custom/Helm/HelmUpdateRealease.tsx (1)

57-63: 升级请求参数简化合理

移除了 versionrepoName 参数,只保留必要的 valuesnamenamespace,这与后端从 SDK 迁移到 CLI 的实现方式相匹配。

pkg/helm/helm.go (1)

39-52: 接口更新符合 CLI 实现需求

接口变更包括:

  • 为多个方法添加了明确的 namespace 参数
  • 简化了 UpgradeRelease 的参数
  • 新增了获取 release 详细信息的方法

这些变更与从 SDK 迁移到 CLI 的实现方式一致。

pkg/controller/helm/helm_release.go (1)

129-176: 新增的获取 Release 详情功能实现合理

新增的 GetReleaseNoteGetReleaseValues 处理器正确实现了:

  • 获取 Release 说明信息
  • 支持按版本获取 Release 配置值
  • 合理的错误处理

Copy link
Contributor

@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 (4)
pkg/helm/helm_cmd.go (4)

114-115: 验证文件路径以防止路径遍历攻击。

直接使用用户提供的仓库名称构建文件路径可能存在路径遍历风险。

建议添加路径验证:

+import "path/filepath"
+
+// 验证仓库名称
+if strings.Contains(repoEntry.Name, "..") || strings.Contains(repoEntry.Name, "/") {
+    return false, fmt.Errorf("invalid repository name: %s", repoEntry.Name)
+}
 cachePath := fmt.Sprintf("%s/repository/%s-index.yaml", h.repoCacheDir, repoEntry.Name)
+cachePath = filepath.Clean(cachePath)

42-42: 避免记录敏感信息。

命令字符串可能包含密码等敏感信息,不应该直接打印到日志中。


45-45: 避免使用 shell 执行命令,存在命令注入风险。

使用 sh -c 执行命令可能导致命令注入漏洞。建议直接使用 exec.Command(h.HelmBin, args...)

建议修改:

-cmd := exec.Command("sh", "-c", cmdStr)
+cmd := exec.Command(h.HelmBin, args...)

269-269: 移除硬编码的 stderr 重定向。

在命令参数中硬编码 2>/dev/null 依赖于 shell 特性,与直接使用 exec.Command 不兼容。

-args := []string{"search", "repo", chartRef, "-o", "json", "--versions", "2>/dev/null"}
+args := []string{"search", "repo", chartRef, "-o", "json", "--versions"}
🧹 Nitpick comments (1)
pkg/helm/helm_cmd.go (1)

315-315: 处理 updateRepoByName 的错误返回值。

虽然使用了 _, _ 明确忽略返回值,但建议至少记录错误以便调试。

-_, _ = h.updateRepoByName(repoEntry, item)
+_, err := h.updateRepoByName(repoEntry, item)
+if err != nil {
+    klog.Errorf("Failed to update repo %s: %v", item.Name, err)
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c725041 and bc33a02.

📒 Files selected for processing (3)
  • pkg/helm/helm_cmd.go (1 hunks)
  • pkg/models/helm_release.go (1 hunks)
  • pkg/models/migrate.go (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
pkg/models/migrate.go (2)
internal/dao/conn.go (1)
  • DB (176-182)
pkg/models/helm_release.go (1)
  • HelmRelease (11-23)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (5)
pkg/helm/helm_cmd.go (1)

46-46: 环境变量设置方式正确。

使用 cmd.Env 为每个命令单独设置环境变量,避免了并发环境中的竞态条件。

pkg/models/migrate.go (1)

67-69: 自动迁移添加正确

新增 HelmRelease 模型的数据库迁移遵循了现有的迁移模式,错误处理方式与其他模型保持一致。

pkg/models/helm_release.go (3)

11-23: HelmRelease 模型设计合理

结构体定义包含了 Helm 发布管理所需的关键字段,GORM 注解使用恰当:

  • 主键和索引设置合理
  • 命名空间和 Chart 名称设置了必填约束
  • JSON 标签支持 API 序列化
  • 时间戳字段便于跟踪记录变更

25-39: CRUD 方法实现标准

使用通用 DAO 函数实现标准的增删改查操作,与项目中其他模型保持一致的实现模式,代码复用性良好。


41-55: 专用查询函数设计恰当

两个专用函数针对 Helm 发布的业务场景:

  • GetHelmReleaseByNsAndReleaseName: 通过命名空间和发布名称查询,这是 Helm 管理中的常见需求
  • DeleteHelmReleaseByNsAndReleaseName: 对应的删除操作
  • 错误处理得当,使用了 GORM 的安全查询构建器

新增HelmViewRelease组件用于查看Helm发布的参数配置,替换原有的diffEditor实现
优化HelmUpdateRelease组件的代码格式
Copy link
Contributor

@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 (4)
ui/src/components/Amis/custom/Helm/HelmViewRelease.tsx (4)

18-18: 未使用的 ref 参数

组件使用了 React.forwardRef 但没有实际使用 ref,建议移除 forwardRef 包装或明确使用 ref。

-const HelmViewRelease = React.forwardRef<HTMLSpanElement, HelmViewReleaseProps>(({ data }, _) => {
+const HelmViewRelease: React.FC<HelmViewReleaseProps> = ({ data }) => {

21-24: 变量命名不一致

变量命名存在不一致问题,建议统一命名风格以提高代码可读性。

-    let chartName = data.chart
-    let releaseName = data.name
-    let namespace = data.namespace
-    let revision = data.revision
+    const chartName = data.chart;
+    const releaseName = data.name;
+    const namespace = data.namespace;
+    const revision = data.revision;

61-61: 建议将内联样式提取为 CSS 类

内联样式不利于维护和重用,建议提取为 CSS 类或使用 styled-components。

可以在组件文件同目录创建对应的 CSS 文件:

.editor-container {
    border: 1px solid #d9d9d9;
    border-radius: 4px;
}

然后在组件中使用:

-                    <div style={{ border: '1px solid #d9d9d9', borderRadius: '4px' }}>
+                    <div className="editor-container">

63-63: 编辑器高度计算可能不够灵活

硬编码的高度计算 calc(100vh - 200px) 可能在不同布局下不够灵活,建议考虑更动态的高度计算方式。

可以考虑使用 useRefResizeObserver 来动态调整编辑器高度,或者将高度作为 props 传入以增加组件的灵活性。

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bc33a02 and 61780ea.

📒 Files selected for processing (4)
  • ui/public/pages/helm/release.json (8 hunks)
  • ui/src/components/Amis/custom/Helm/HelmUpdateRealease.tsx (3 hunks)
  • ui/src/components/Amis/custom/Helm/HelmViewRelease.tsx (1 hunks)
  • ui/src/components/Amis/index.tsx (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • ui/src/components/Amis/index.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • ui/src/components/Amis/custom/Helm/HelmUpdateRealease.tsx
  • ui/public/pages/helm/release.json
🧰 Additional context used
🧬 Code Graph Analysis (1)
ui/src/components/Amis/custom/Helm/HelmViewRelease.tsx (1)
ui/src/components/Amis/fetcher.ts (1)
  • fetcher (8-60)
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (go)

在Helm接口和控制器中添加GetReleaseNoteWithRevision方法,支持通过指定版本号获取release notes。同时更新前端页面以适配新功能。
移除helm get notes命令中的json输出参数,并调整API返回格式为包含note字段的对象
更新前端页面以正确显示notes内容
在Dockerfile中增加helm工具的安装,同时添加tar和gzip工具包
优化apk包管理命令,删除无用缓存
升级基础镜像软件包并清理缓存,同时添加helm工具支持。优化构建步骤顺序以提高效率。
Copy link
Contributor

@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

♻️ Duplicate comments (9)
pkg/helm/helm_cmd.go (9)

48-48: kubeconfig 文件权限过于宽松

kubeconfig 包含敏感认证信息,但使用 0644 权限允许其他用户读取。

修改文件权限为仅所有者可读写:

-if err := os.WriteFile(kubeconfigPath, []byte(config), 0644); err != nil {
+if err := os.WriteFile(kubeconfigPath, []byte(config), 0600); err != nil {

68-68: 命令注入安全漏洞

使用 sh -c 执行命令存在命令注入风险。应直接使用 exec.Command 执行。

修改为直接执行:

-cmd := exec.Command("sh", "-c", cmdStr)
+cmd := exec.Command(h.HelmBin, args...)

84-87: 错误处理逻辑有误

即使命令成功执行,如果有 stderr 输出也会返回错误。某些命令正常运行时也会输出到 stderr。

修正错误处理:

 if stderr.Len() > 0 {
     klog.V(6).Infof("[helm-cmd] stderr: %s\n", stderr.String())
-    err = fmt.Errorf("%s", stderr.String())
+    // 只有在命令执行失败时才将 stderr 作为错误
+    if err != nil {
+        err = fmt.Errorf("command failed: %v, stderr: %s", err, stderr.String())
+    }
 }

116-120: 避免记录敏感信息

密码通过命令行参数传递并在日志中以明文形式记录,存在安全风险。

建议使用环境变量或标准输入传递密码:

 if repoEntry.Username != "" {
     args = append(args, "--username", repoEntry.Username)
 }
 if repoEntry.Password != "" {
-    args = append(args, "--password", repoEntry.Password)
+    // 通过标准输入传递密码,避免在命令行中暴露
+    args = append(args, "--password-stdin")
 }
-out, err := h.runAndLog(args, "")
+out, err := h.runAndLog(args, repoEntry.Password)

132-132: 返回值顺序不符合 Go 惯例

Go 惯例是将 error 作为最后一个返回值。当前返回 (bool, error)

修改返回值顺序并更新所有调用处:

-func (h *HelmCmd) updateRepoByName(repoEntry *repo.Entry, helmRepo *models.HelmRepository) (bool, error) {
+func (h *HelmCmd) updateRepoByName(repoEntry *repo.Entry, helmRepo *models.HelmRepository) (bool, error) {

250-250: Values 可能包含敏感信息

将完整的 values 内容存储到数据库可能暴露密码、密钥等敏感信息。

建议实施以下安全措施之一:

  • 对敏感字段进行脱敏处理
  • 加密存储 values 内容
  • 仅存储 values 的哈希值用于变更检测
  • 使用专门的凭据管理服务

296-296: 移除硬编码的 stderr 重定向

在命令参数中硬编码 2>/dev/null 依赖于 shell 特性,与直接使用 exec.Command 不兼容。

-args := []string{"search", "repo", chartRef, "-o", "json", "--versions", "2>/dev/null"}
+args := []string{"search", "repo", chartRef, "-o", "json", "--versions"}

342-342: 处理 updateRepoByName 的返回值

调用 updateRepoByName 但忽略了其返回值,应该处理可能的错误。

-_, _ = h.updateRepoByName(repoEntry, item)
+if _, err := h.updateRepoByName(repoEntry, item); err != nil {
+    klog.Errorf("Failed to update repo %s: %v", item.Name, err)
+}

43-43: 存在路径遍历安全漏洞

cluster 参数未经验证直接用于构建文件路径。如果包含 ../ 等路径遍历序列,可能导致文件被写入任意位置。

建议添加输入验证:

+import "path/filepath"

 kubeconfigPath := fmt.Sprintf("%s/%s-kubeconfig.yaml", repoCacheDir, strings.ReplaceAll(cluster, "/", "|"))
+// 验证路径安全性
+kubeconfigPath = filepath.Clean(kubeconfigPath)
+if !strings.HasPrefix(kubeconfigPath, repoCacheDir) {
+    return nil, fmt.Errorf("invalid cluster name")
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d24ef8 and 5dfe1d7.

📒 Files selected for processing (7)
  • main.go (1 hunks)
  • pkg/controller/helm/helm.go (1 hunks)
  • pkg/controller/helm/helm_release.go (9 hunks)
  • pkg/helm/helm.go (1 hunks)
  • pkg/helm/helm_cmd.go (1 hunks)
  • pkg/models/helm_release.go (1 hunks)
  • ui/public/pages/helm/release.json (9 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • main.go
  • pkg/controller/helm/helm.go
  • ui/public/pages/helm/release.json
  • pkg/models/helm_release.go
  • pkg/controller/helm/helm_release.go
🧰 Additional context used
🧬 Code Graph Analysis (1)
pkg/helm/helm_cmd.go (6)
pkg/controller/helm/helm_repo.go (2)
  • AddOrUpdateRepo (28-55)
  • UpdateReposIndex (100-125)
pkg/models/helm_repository.go (1)
  • HelmRepository (11-31)
internal/dao/conn.go (1)
  • DB (176-182)
pkg/models/helm_chart.go (3)
  • HelmChart (11-27)
  • ReleaseHistory (59-65)
  • Release (49-58)
pkg/controller/helm/helm_release.go (4)
  • UninstallRelease (106-127)
  • InstallRelease (62-103)
  • GetReleaseNote (130-149)
  • GetReleaseValues (152-179)
pkg/models/helm_release.go (3)
  • DeleteHelmReleaseByNsAndReleaseName (54-56)
  • HelmRelease (11-24)
  • GetHelmReleaseByNsAndReleaseName (43-51)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (4)
pkg/helm/helm_cmd.go (2)

153-199: Chart 索引处理实现良好

代码正确处理了仓库索引文件的解析和 Chart 信息的数据库存储:

  • 使用 repository_id 精确删除旧数据
  • 按创建时间排序获取最新版本
  • 对非关键错误进行了适当的日志记录而不中断流程

348-386: Get 方法实现正确

所有获取方法的实现都正确:

  • GetReleaseList 使用 -A 获取所有命名空间
  • 各方法都正确传递了命名空间参数
  • 支持带修订版本的查询
pkg/helm/helm.go (2)

10-10: 接口方法签名更新合理

添加 namespace 参数并更新返回类型为自定义模型是很好的改进,提高了接口的明确性和类型安全性。


17-17: GetReleaseList 返回类型更新符合重构目标

返回类型更新为自定义的 *models.Release 类型,与从 SDK 迁移到二进制命令方式的目标一致。这解决了之前评论中提到的实现不完整问题。

Copy link
Contributor

@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

🔭 Outside diff range comments (1)
Dockerfile (1)

2-7: ARG 参数未一一声明,可能导致构建警告

-ldflags 中引用了 $GIT_TAG, $GIT_REPOSITORY, $BUILD_DATE 但前面只声明了少部分 ARG。未声明的变量在构建时为空并触发 unused build-arg 警告,亦降低可读性。请补充声明或移除未使用的变量。

🧹 Nitpick comments (4)
Dockerfile.action (2)

30-31: 避免在运行镜像里执行 apk upgrade

apk upgrade 会把基础镜像的全部包都升级到 edge 仓库最新版本,可能导致:

  • 镜像尺寸暴涨;
  • 与基础镜像安全扫描基线不一致;
  • 难以重现的“雪花”环境。

除非确有必要安装特定补丁,建议仅使用 apk add --no-cache <pkg> 精确安装所需包。


32-33: 使用 COPY 替代 ADD 以符合最佳实践

此处只是把本地脚本放进镜像,ADD 的额外功能(自动解压 / 远程 URL)并未用到,容易误导阅读者,也触发 Hadolint DL3020。

-ADD reload.sh /app/reload.sh
+COPY reload.sh /app/reload.sh
Dockerfile (2)

16-19: apk upgrade 同样应避免

Dockerfile.action 中的情况一致,完整升级会引入不可控风险。仅安装所需的软件包即可,建议拆分为:

-RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
-    && apk upgrade && apk add --no-cache curl bash inotify-tools alpine-conf busybox-extras tzdata   tar gzip\
+RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories \
+    && apk add --no-cache curl bash inotify-tools busybox-extras tzdata tar gzip \

20-20: ADD reload.sh 改为 COPY

功能一致但 COPY 更语义化,亦可消除 Hadolint 警告。

-ADD reload.sh /app/reload.sh
+COPY reload.sh /app/reload.sh
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5dfe1d7 and 696baee.

📒 Files selected for processing (2)
  • Dockerfile (1 hunks)
  • Dockerfile.action (1 hunks)
🧰 Additional context used
🪛 Hadolint (2.12.0)
Dockerfile.action

[error] 32-32: Use COPY instead of ADD for files and folders

(DL3020)

Dockerfile

[error] 20-20: Use COPY instead of ADD for files and folders

(DL3020)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)

重构 HelmCmd 结构,新增集群内运行模式支持,包括 token、caFile 和 apiServer 配置
将 cluster 参数改为 ClusterConfig 类型以获取更多集群信息
优化 kubeconfig 处理逻辑,区分集群内外不同运行环境
Copy link
Contributor

@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

♻️ Duplicate comments (8)
pkg/helm/helm_cmd.go (8)

73-130: 改进命令执行的安全性和错误处理


103-103: 避免记录敏感信息


173-173: 返回值顺序不符合 Go 惯例


182-182: 路径遍历安全风险


194-194: 使用 repository_id 而非 repository_name 删除记录


273-299: 存储敏感数据的安全考虑


337-337: 移除硬编码的 stderr 重定向


383-383: 处理 updateRepoByName 的返回值

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 696baee and 43bb166.

📒 Files selected for processing (2)
  • pkg/controller/helm/helm.go (1 hunks)
  • pkg/helm/helm_cmd.go (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/controller/helm/helm.go
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (1)
pkg/helm/helm_cmd.go (1)

430-454: InCluster 认证实现正确

该方法正确读取了 Kubernetes ServiceAccount 的 token 和 CA 证书,实现符合 Kubernetes 的标准做法。

weibaohui added 7 commits July 1, 2025 22:03
- 在helm_cmd.go中添加索引生成时间的更新逻辑
- 移除helm_repository.go中未使用的content字段
- 调整helm_release.go中字段顺序并添加集群字段
将clusterID从路径替换改为base64编码,避免特殊字符问题
统一接口方法参数命名,将namespace简化为ns
移除调试日志输出
清理 Helm 组件中未使用的 releaseName、repoName 和 chart 属性,简化接口定义
修改了前端和后端代码,统一将获取helm release值和notes的API请求方法从POST改为GET,遵循RESTful规范
同时移除了不必要的类型忽略注释,使用类型断言替代
添加对 chart、name、namespace 和 revision 的默认值处理
当缺少必要信息时显示错误提示并返回 null
@weibaohui weibaohui merged commit 5fe8792 into main Jul 1, 2025
6 checks passed
@weibaohui weibaohui deleted the helm branch July 1, 2025 14:34
@weibaohui weibaohui mentioned this pull request Jul 1, 2025
@coderabbitai coderabbitai bot mentioned this pull request Jul 2, 2025
This was referenced Jul 18, 2025
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.

1 participant