golang Gerrit代码审查系统客户端插件库go-gerrit的使用
Golang Gerrit代码审查系统客户端插件库go-gerrit的使用
简介
go-gerrit是一个用于Gerrit代码审查系统的Go客户端库。
功能特性
- 认证方式支持(HTTP Basic、HTTP Digest、HTTP Cookie)
- 支持所有Gerrit API端点
- /access/
- /accounts/
- /changes/
- /config/
- /groups/
- /plugins/
- /projects/
- 支持可选插件API如events-log
安装
go-gerrit遵循Go发布策略,支持当前版本及前两个Go版本。
安装命令:
$ go get github.com/andygrunwald/go-gerrit
API使用
认证方式
HTTP Basic认证
instance := "https://review.typo3.org/"
client, _ := gerrit.NewClient(instance, nil)
client.Authentication.SetBasicAuth("andy.grunwald", "my secrect password")
self, _, _ := client.Accounts.GetAccount("self")
fmt.Printf("Username: %s", self.Name)
// 输出: Username: Andy Grunwald
如果收到401未授权错误,请检查账户设置中的HTTP密码配置。
HTTP Digest认证
instance := "https://gerrit.wikimedia.org/r/"
client, _ := gerrit.NewClient(instance, nil)
client.Authentication.SetDigestAuth("andy.grunwald", "my secrect http password")
self, resp, err := client.Accounts.GetAccount("self")
fmt.Printf("Username: %s", self.Name)
// 输出: Username: Andy Grunwald
HTTP Cookie认证
instance := "https://gerrit-review.googlesource.com/"
client, _ := gerrit.NewClient(instance, nil)
client.Authentication.SetCookieAuth("o", "my-cookie-secret")
self, _, _ := client.Accounts.GetAccount("self")
fmt.Printf("Username: %s", self.Name)
// 输出: Username: Andy G.
示例代码
获取Gerrit实例版本
package main
import (
"fmt"
"github.com/andygrunwald/go-gerrit"
)
func main() {
instance := "https://gerrit-review.googlesource.com/"
client, err := gerrit.NewClient(instance, nil)
if err != nil {
panic(err)
}
v, _, err := client.Config.GetVersion()
if err != nil {
panic(err)
}
fmt.Printf("Version: %s", v)
// 输出: Version: 3.4.1-2066-g8db5605430
}
获取所有公开项目
package main
import (
"fmt"
"github.com/andygrunwald/go-gerrit"
)
func main() {
instance := "https://chromium-review.googlesource.com/"
client, err := gerrit.NewClient(instance, nil)
if err != nil {
panic(err)
}
opt := &gerrit.ProjectOptions{
Description: true,
}
projects, _, err := client.Projects.ListProjects(opt)
if err != nil {
panic(err)
}
for name, p := range *projects {
fmt.Printf("%s - State: %s\n", name, p.State)
}
// 输出示例:
// chromiumos/third_party/bluez - State: ACTIVE
// external/github.com/Polymer/ShadowDOM - State: ACTIVE
// external/github.com/domokit/mojo_sdk - State: ACTIVE
}
查询变更
package main
import (
"fmt"
"github.com/andygrunwald/go-gerrit"
)
func main() {
instance := "https://android-review.googlesource.com/"
client, err := gerrit.NewClient(instance, nil)
if err != nil {
panic(err)
}
opt := &gerrit.QueryChangeOptions{}
opt.Query = []string{"project:kernel/common"}
opt.AdditionalFields = []string{"LABELS"}
changes, _, err := client.Changes.QueryChanges(opt)
if err != nil {
panic(err)
}
for _, change := range *changes {
fmt.Printf("Project: %s -> %s -> %s%d\n", change.Project, change.Subject, instance, change.Number)
}
// 输出示例:
// Project: kernel/common -> ANDROID: GKI: Update symbols to symbol list -> https://android-review.googlesource.com/1830553
// Project: kernel/common -> ANDROID: db845c_gki.fragment: Remove CONFIG_USB_NET_AX8817X from fragment -> https://android-review.googlesource.com/1830439
}
开发
运行测试和检查
运行测试:
$ make test
运行检查、测试和静态分析:
$ make vet staticcheck test
本地Gerrit设置
建议使用官方Gerrit Code Review docker镜像:
$ docker run -ti -p 8080:8080 -p 29418:29418 gerritcodereview/gerrit:3.4.1
认证
对于本地开发设置,可以生成密码后使用:
client.Authentication.SetBasicAuth("admin", "secret")
常见问题
源代码如何组织?
源代码组织受Google的go-github启发。每个REST API端点(如/access/, /changes/)都在一个服务中实现(如access.go中的AccessService, changes.go中的ChangesService)。
与Gerrit版本的兼容性如何?
该库基于Gerrit版本2.11.3-1230-gb8336f1的REST API实现并测试。可能也适用于旧版本。
如何添加对可选插件REST API的支持?
取决于具体插件,可以先提出问题和用例。例如events-log插件因其流行而被支持。
许可证
本项目采用MIT许可证。
更多关于golang Gerrit代码审查系统客户端插件库go-gerrit的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang Gerrit代码审查系统客户端插件库go-gerrit的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-gerrit:Golang Gerrit客户端库使用指南
go-gerrit 是一个用于与 Gerrit 代码审查系统交互的 Golang 客户端库。它提供了方便的 API 来执行各种 Gerrit 操作,如查询变更、提交评论、管理账户等。
安装
首先安装 go-gerrit 库:
go get github.com/andygrunwald/go-gerrit
基本使用
1. 创建客户端连接
package main
import (
"fmt"
"log"
"github.com/andygrunwald/go-gerrit"
)
func main() {
// 创建匿名客户端
client, err := gerrit.NewClient("https://gerrit-review.googlesource.com", nil)
if err != nil {
log.Fatal(err)
}
// 或者使用基本认证
client, err = gerrit.NewClient(
"https://your-gerrit-instance.com",
&gerrit.BasicAuth{
Username: "your-username",
Password: "your-password-or-http-token",
},
)
if err != nil {
log.Fatal(err)
}
}
2. 查询变更列表
func listChanges(client *gerrit.Client) {
opt := &gerrit.QueryChangeOptions{
QueryOptions: gerrit.QueryOptions{
Limit: 10, // 限制返回结果数量
},
}
changes, _, err := client.Changes.QueryChanges(opt)
if err != nil {
log.Fatal(err)
}
for _, change := range *changes {
fmt.Printf("ID: %s, Project: %s, Subject: %s\n",
change.ID, change.Project, change.Subject)
}
}
3. 获取特定变更详情
func getChangeDetail(client *gerrit.Client, changeID string) {
change, _, err := client.Changes.GetChangeDetail(changeID, &gerrit.ChangeOptions{
AdditionalFields: []string{"LABELS", "DETAILED_ACCOUNTS"},
})
if err != nil {
log.Fatal(err)
}
fmt.Printf("Change %s:\n", change.ID)
fmt.Printf("Status: %s\n", change.Status)
fmt.Printf("Owner: %s (%s)\n", change.Owner.Name, change.Owner.Email)
fmt.Printf("Current Revision: %s\n", change.CurrentRevision)
}
4. 提交代码审查评论
func postReview(client *gerrit.Client, changeID, revisionID string) {
reviewInput := &gerrit.ReviewInput{
Message: "Looks good to me, but needs minor fixes.",
Labels: map[string]string{
"Code-Review": "+1",
},
Comments: map[string][]gerrit.CommentInput{
"src/main.go": {
{
Line: 42,
Message: "Consider using a constant here instead of magic number.",
},
},
},
}
_, _, err := client.Changes.SetReview(changeID, revisionID, reviewInput)
if err != nil {
log.Fatal(err)
}
fmt.Println("Review submitted successfully")
}
5. 创建新变更
func createChange(client *gerrit.Client) {
changeInput := &gerrit.ChangeInput{
Project: "my-project",
Branch: "master",
Subject: "Implement new feature X",
Status: "NEW",
WorkInProgress: true,
}
newChange, _, err := client.Changes.CreateChange(changeInput)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Created new change: %s\n", newChange.ID)
}
高级功能
1. 使用 SSH 认证
func sshClient() {
client, err := gerrit.NewSSHClient(
"gerrit.example.com:29418",
"/path/to/private/key",
"your-username",
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// 使用SSH客户端执行命令...
}
2. 处理分页结果
func paginatedChanges(client *gerrit.Client) {
opt := &gerrit.QueryChangeOptions{
QueryOptions: gerrit.QueryOptions{
Limit: 50,
Skip: 0,
Sort: "updated",
Option: []string{"LABELS"},
},
}
for {
changes, resp, err := client.Changes.QueryChanges(opt)
if err != nil {
log.Fatal(err)
}
for _, change := range *changes {
fmt.Printf("%s: %s\n", change.ID, change.Subject)
}
if len(*changes) < opt.Limit {
break
}
opt.Skip += opt.Limit
}
}
3. 监听事件流
func streamEvents(client *gerrit.Client) {
events := make(chan *gerrit.Event)
done := make(chan struct{})
go func() {
err := client.Events.StreamEvents(events, done, &gerrit.StreamEventsOptions{
SSH: true, // 使用SSH流
})
if err != nil {
log.Fatal(err)
}
}()
for event := range events {
switch event.Type {
case "patchset-created":
fmt.Printf("New patchset created for change %s\n", event.Change.Number)
case "comment-added":
fmt.Printf("New comment on change %s by %s\n",
event.Change.Number, event.Author.Name)
}
}
}
最佳实践
- 错误处理:Gerrit API 可能返回各种错误,始终检查错误响应
- 认证管理:使用 HTTP 令牌而非密码,并妥善保管
- 速率限制:避免过频繁的 API 调用,Gerrit 可能有速率限制
- 上下文使用:对于长时间运行的操作,使用 context 进行超时控制
go-gerrit 提供了完整的 Gerrit REST API 覆盖,更多功能可以参考其官方文档。