go-gerrit is a Go client library for the Gerrit Code Review system.
go-gerrit follows the Go Release Policy. This means we support the current + 2 previous Go versions.
It is go gettable ...
$ go get github.com/andygrunwald/go-gerrit
Have a look at the GoDoc documentation for a detailed API description.
The Gerrit Code Review - REST API was the foundation document.
Gerrit supports multiple ways for authentication.
Some Gerrit instances (like TYPO3) has auth.gitBasicAuth activated. With this, you can authenticate with HTTP Basic like this:
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
If you get a 401 Unauthorized
, check your Account Settings and have a look at the HTTP Password
configuration.
Some Gerrit instances (like Wikimedia) has Digest access authentication activated.
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
If the chosen Gerrit instance does not support digest auth, an error like WWW-Authenticate header type is not Digest
is thrown.
If you get a 401 Unauthorized
, check your Account Settings and have a look at the HTTP Password
configuration.
Some Gerrit instances hosted like the one hosted googlesource.com (e.g. Go, Android or Gerrit) support HTTP Cookie authentication.
You need the cookie name and the cookie value. You can get them by click on "Settings > HTTP Password > Obtain Password" in your Gerrit instance.
There you can receive your values.
The cookie name will be (mostly) o
(if hosted on googlesource.com).
Your cookie secret will be something like git-your@email.com=SomeHash...
.
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.
More examples are available
Receive the version of the Gerrit instance used by the Gerrit team for development:
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
}
List all projects from Chromium:
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
// ...
}
Get some changes of the kernel/common project from the AndroidGerrit Review System.
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
// Project: kernel/common -> ANDROID: Update the ABI representation -> https://android-review.googlesource.com/1830469
// ...
}
Tests only:
$ make test
Checks, tests and linters
$ make vet staticcheck test
For local development, we suggest the usage of the official Gerrit Code Review docker image:
$ docker run -ti -p 8080:8080 -p 29418:29418 gerritcodereview/gerrit:3.4.1
Wait a few minutes until the Gerrit Code Review NNN ready
message appears,
where NNN is your current Gerrit version, then open your browser to http://localhost:8080
and you will be in Gerrit Code Review.
For local development setups, go to http://localhost:8080/settings/#HTTPCredentials and click GENERATE NEW PASSWORD
.
Now you can use (only for development purposes):
client.Authentication.SetBasicAuth("admin", "secret")
Replace secret
with your new value.
The source code organization is inspired by go-github by Google.
Every REST API Endpoint (e.g. /access/
, /changes/
) is coupled in a service (e.g. AccessService
in access.go, ChangesService
in changes.go).
Every service is part of gerrit.Client
as a member variable.
gerrit.Client
can provide essential helper functions to avoid unnecessary code duplications, such as building a new request or parse responses.
Based on this structure, implementing a new API functionality is straight forward.
Here is an example of *ChangeService.DeleteTopic*
/ DELETE /changes/{change-id}/topic:
func (s *ChangesService) DeleteTopic(changeID string) (*Response, error) {
u := fmt.Sprintf("changes/%s/topic", changeID)
return s.client.DeleteRequest(u, nil)
}
The library was implemented based on the REST API of Gerrit version 2.11.3-1230-gb8336f1 and tested against this version.
This library might be working with older versions as well. If you notice an incompatibility open a new issue. We also appreciate your Pull Requests to improve this library. We welcome contributions!
It will depend on the plugin, and you are welcome to open a new issue first to propose the idea and use-case.
As an example, the addition of support for events-log
plugin was supported because the plugin itself is fairly
popular.
The structures that the REST API uses could also be used by gerrit stream-events
.
This project is released under the terms of the MIT license.