blob: 591b5b98ffca8eb6f141c08b57febbeb11d28e43 [file] [log] [blame]
package issuetracker
// Initializes and polls the various issue frameworks.
import (
"context"
"strconv"
"strings"
"go.skia.org/infra/perf/go/config"
"golang.org/x/oauth2/google"
"google.golang.org/api/option"
"go.skia.org/infra/go/secret"
"go.skia.org/infra/go/skerr"
"go.skia.org/infra/go/sklog"
issuetracker "go.skia.org/infra/go/issuetracker/v1"
)
// IssueTracker defines an interface for accessing issuetracker v1 api.
type IssueTracker interface {
// ListIssues sends a GET request to issuetracker api with the specified query parameter.
// The response from the api is unmarshalled into the provided response object.
ListIssues(ctx context.Context, requestObj ListIssuesRequest) ([]*issuetracker.Issue, error)
// CreateComment adds a new comment to a existing bug given the bug id and the comment body.
CreateComment(ctx context.Context, req *CreateCommentRequest) (*CreateCommentResponse, error)
}
// / IssueTrackerImpl implements IssueTracker using the issue tracker API
type issueTrackerImpl struct {
client *issuetracker.Service
}
// ListIssuesRequest defines the request object for ListIssues.
type ListIssuesRequest struct {
IssueIds []int `json:"issueIds"`
}
// CreateCommentRequest is the request object for CreateComment
type CreateCommentRequest struct {
IssueId int64 `json:"issue_id"`
Comment string `json:"comment"`
}
// CreateCommentResponse is the response object for CreateComment
type CreateCommentResponse struct {
IssueId int64 `json:"issud_id"`
CommentNumber int64 `json:"comment_number"`
}
// NewIssueTracker returns a new issueTracker object.
func NewIssueTracker(ctx context.Context, cfg config.IssueTrackerConfig) (IssueTracker, error) {
secretClient, err := secret.NewClient(ctx)
if err != nil {
return nil, skerr.Wrapf(err, "creating secret client")
}
apiKey, err := secretClient.Get(ctx, cfg.IssueTrackerAPIKeySecretProject, cfg.IssueTrackerAPIKeySecretName, secret.VersionLatest)
if err != nil {
return nil, skerr.Wrapf(err, "loading API Key secrets from project: %q name: %q", cfg.IssueTrackerAPIKeySecretProject, cfg.IssueTrackerAPIKeySecretName)
}
client, err := google.DefaultClient(context.Background(), "https://www.googleapis.com/auth/buganizer")
if err != nil {
return nil, skerr.Wrapf(err, "creating authorized HTTP client")
}
c, err := issuetracker.NewService(ctx, option.WithAPIKey(apiKey), option.WithHTTPClient(client))
if err != nil {
return nil, skerr.Wrapf(err, "creating issuetracker service")
}
c.BasePath = "https://issuetracker.googleapis.com"
return &issueTrackerImpl{
client: c,
}, nil
}
func (s *issueTrackerImpl) CreateComment(ctx context.Context, req *CreateCommentRequest) (*CreateCommentResponse, error) {
if req == nil {
return nil, skerr.Fmt("Create comment request is null.")
}
if req.IssueId <= 0 || req.Comment == "" {
return nil, skerr.Fmt("Invalid CreateCommentRequest properties. Issue Id: %d, Comment: %s", req.IssueId, req.Comment)
}
sklog.Debugf("[Perf_issuetracker] Received CreateCommentRequest. Issue Id: %d, Comment: %s", req.IssueId, req.Comment)
// FormattingMode is default to PLAIN
issueComment := &issuetracker.IssueComment{
Comment: req.Comment,
}
resp, err := s.client.Issues.Comments.Create(int64(req.IssueId), issueComment).Do()
if err != nil {
return nil, skerr.Wrapf(err, "Failed to create a new comment for bug id: %d. Comment: %s", req.IssueId, req.Comment)
}
sklog.Debugf("[Perf_issuetracker] CreateCommentResponse. Issue Id: %d, comment Id: %d", resp.IssueId, resp.CommentNumber)
return &CreateCommentResponse{
IssueId: int64(resp.IssueId),
CommentNumber: int64(resp.CommentNumber),
}, nil
}
// ListIssues finds the specified issueID and returns a list of issue object.
func (s *issueTrackerImpl) ListIssues(ctx context.Context, requestObj ListIssuesRequest) ([]*issuetracker.Issue, error) {
slice := make([]string, len(requestObj.IssueIds))
for i, issueId := range requestObj.IssueIds {
slice[i] = strconv.Itoa(issueId)
}
query := strings.Join(slice, " | ")
query = "id:(" + query + ")"
if len(requestObj.IssueIds) == 0 {
return nil, skerr.Wrapf(nil, "No issue IDs provided")
}
sklog.Debugf("[Perf_issuetracker] Start sending list issues request to v1 issuetracker with query: %s", query)
resp, err := s.client.Issues.List().Query(query).Do()
if err != nil {
return nil, skerr.Wrapf(err, "Failed to find issue with request. ")
}
if len(resp.Issues) > 0 {
sklog.Debugf("[Perf_issuetracker] Received list issues response from v1: IssueID=%s, State=%s", resp.Issues[0].IssueId, resp.Issues[0].IssueState.Title)
}
return resp.Issues, nil
}