go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/analysis/internal/gerrit/gerrit.go (about) 1 // Copyright 2022 The LUCI Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package gerrit contains logic for interacting with Gerrit. 16 package gerrit 17 18 import ( 19 "context" 20 "net/http" 21 22 "go.chromium.org/luci/common/api/gerrit" 23 "go.chromium.org/luci/common/errors" 24 gerritpb "go.chromium.org/luci/common/proto/gerrit" 25 "go.chromium.org/luci/server/auth" 26 27 "go.chromium.org/luci/analysis/internal/scopedauth" 28 ) 29 30 // testingGerritClientKey is the context key to indicate using a substitute 31 // Gerrit client in tests. 32 var testingGerritClientKey = "used in tests only for setting the mock gerrit client" 33 34 // gerritClientFactory generates gerrit clients for testing that are specific to 35 // the host requested. 36 type gerritClientFactory interface { 37 WithHost(host string) gerritpb.GerritClient 38 } 39 40 // Client is the client to communicate with Gerrit. 41 // It wraps a gerritpb.GerritClient. 42 type Client struct { 43 gerritClient gerritpb.GerritClient 44 } 45 46 func newGerritClient(ctx context.Context, host, project string) (gerritpb.GerritClient, error) { 47 if testingClientFactory, ok := ctx.Value(&testingGerritClientKey).(gerritClientFactory); ok { 48 // return a Gerrit client for tests. 49 return testingClientFactory.WithHost(host), nil 50 } 51 52 t, err := scopedauth.GetRPCTransport(ctx, project, auth.WithScopes(gerrit.OAuthScope)) 53 if err != nil { 54 return nil, err 55 } 56 57 return gerrit.NewRESTClient(&http.Client{Transport: t}, host, true) 58 } 59 60 // NewClient creates a client to communicate with Gerrit, acting as the 61 // given LUCI Project. 62 func NewClient(ctx context.Context, host, project string) (*Client, error) { 63 client, err := newGerritClient(ctx, host, project) 64 if err != nil { 65 return nil, errors.Annotate(err, "creating Gerrit client for host %s", host).Err() 66 } 67 68 return &Client{ 69 gerritClient: client, 70 }, nil 71 } 72 73 // GetChange gets a gerrit change by its ID. 74 func (c *Client) GetChange(ctx context.Context, req *gerritpb.GetChangeRequest) (*gerritpb.ChangeInfo, error) { 75 res, err := c.gerritClient.GetChange(ctx, req) 76 if err != nil { 77 return nil, err 78 } 79 return res, nil 80 }