pkg/event_processor/bitbucket/bitbucket.go (146 lines of code) (raw):

package bitbucket import ( "context" "encoding/json" "errors" "fmt" "github.com/go-resty/resty/v2" "go.uber.org/zap" ctrlClient "sigs.k8s.io/controller-runtime/pkg/client" codebaseApi "github.com/epam/edp-codebase-operator/v2/api/v1" "github.com/epam/edp-tekton/pkg/event_processor" ) type EventProcessor struct { ksClient ctrlClient.Reader logger *zap.SugaredLogger restyClient *resty.Client } type EventProcessorOptions struct { Logger *zap.SugaredLogger RestyClient *resty.Client } func NewEventProcessor(ksClient ctrlClient.Reader, options *EventProcessorOptions) *EventProcessor { if options == nil { options = &EventProcessorOptions{} } if options.Logger == nil { options.Logger = zap.NewNop().Sugar() } if options.RestyClient == nil { options.RestyClient = resty.New().SetHostURL("https://api.bitbucket.org/2.0") } return &EventProcessor{ ksClient: ksClient, logger: options.Logger, restyClient: options.RestyClient, } } func (p *EventProcessor) Process(ctx context.Context, body []byte, ns, eventType string) (*event_processor.EventInfo, error) { switch eventType { case event_processor.BitbucketEventTypeCommentAdded: return p.processCommentEvent(ctx, body, ns) default: return p.processMergeEvent(ctx, body, ns) } } func (p *EventProcessor) processMergeEvent(ctx context.Context, body []byte, ns string) (*event_processor.EventInfo, error) { bitbucketEvent := &event_processor.BitbucketEvent{} if err := json.Unmarshal(body, bitbucketEvent); err != nil { return nil, fmt.Errorf("failed to unmarshal Bitbucket event: %w", err) } if bitbucketEvent.Repository.FullName == "" { return nil, errors.New("bitbucket repository path empty") } if bitbucketEvent.PullRequest.Destination.Branch.Name == "" { return nil, errors.New("bitbucket target branch empty") } repoPath := event_processor.ConvertRepositoryPath(bitbucketEvent.Repository.FullName) codebase, err := event_processor.GetCodebaseByRepoPath(ctx, p.ksClient, ns, repoPath) if err != nil { return nil, fmt.Errorf("failed to get codebase by repo path: %w", err) } commitMessage, err := p.getPRLatestCommitMessage(ctx, codebase, bitbucketEvent.Repository.FullName, bitbucketEvent.PullRequest.ID) if err != nil { return nil, err } return &event_processor.EventInfo{ GitProvider: event_processor.GitProviderBitbucket, RepoPath: repoPath, TargetBranch: bitbucketEvent.PullRequest.Destination.Branch.Name, Type: event_processor.EventTypeMerge, Codebase: codebase, PullRequest: &event_processor.PullRequest{ HeadSha: bitbucketEvent.PullRequest.Source.Commit.Hash, Title: bitbucketEvent.PullRequest.Title, HeadRef: bitbucketEvent.PullRequest.Source.Branch.Name, ChangeNumber: bitbucketEvent.PullRequest.ID, LastCommitMessage: commitMessage, }, }, nil } func (p *EventProcessor) processCommentEvent(ctx context.Context, body []byte, ns string) (*event_processor.EventInfo, error) { bitbucketEvent := &event_processor.BitbucketCommentEvent{} if err := json.Unmarshal(body, bitbucketEvent); err != nil { return nil, fmt.Errorf("failed to unmarshal Bitbucket event: %w", err) } if bitbucketEvent.Repository.FullName == "" { return nil, errors.New("bitbucket repository path empty") } repoPath := event_processor.ConvertRepositoryPath(bitbucketEvent.Repository.FullName) codebase, err := event_processor.GetCodebaseByRepoPath(ctx, p.ksClient, ns, repoPath) if err != nil { return nil, fmt.Errorf("failed to get codebase by repo path: %w", err) } commitMessage, err := p.getPRLatestCommitMessage(ctx, codebase, bitbucketEvent.Repository.FullName, bitbucketEvent.PullRequest.ID) if err != nil { return nil, err } return &event_processor.EventInfo{ GitProvider: event_processor.GitProviderBitbucket, RepoPath: repoPath, TargetBranch: bitbucketEvent.PullRequest.Destination.Branch.Name, Type: event_processor.EventTypeReviewComment, Codebase: codebase, HasPipelineRecheck: event_processor.ContainsPipelineRecheck(bitbucketEvent.Comment.Content.Raw), PullRequest: &event_processor.PullRequest{ HeadSha: bitbucketEvent.PullRequest.Source.Commit.Hash, Title: bitbucketEvent.PullRequest.Title, HeadRef: bitbucketEvent.PullRequest.Source.Branch.Name, ChangeNumber: bitbucketEvent.PullRequest.ID, LastCommitMessage: commitMessage, }, }, nil } type getPRCommitsResp struct { Values []struct { Message string `json:"message"` } `json:"values"` } func (p *EventProcessor) getPRLatestCommitMessage( ctx context.Context, codebase *codebaseApi.Codebase, repoFullName string, prID int, ) (string, error) { gitServerToken, err := event_processor.GetGitServerToken(ctx, p.ksClient, codebase) if err != nil { return "", fmt.Errorf("failed to get git server token for Bitbucket: %w", err) } commits := getPRCommitsResp{} r, err := p.restyClient.R(). SetContext(ctx). ForceContentType("application/json"). SetHeader("Authorization", fmt.Sprintf("Basic %s", gitServerToken)). SetResult(&commits). Get(fmt.Sprintf("/repositories/%s/pullrequests/%d/commits?fields=values.message&pagelen=1", repoFullName, prID)) if err != nil { return "", fmt.Errorf("failed to get PR latest commit message: %w", err) } if r.IsError() { return "", fmt.Errorf("failed to get PR latest commit message: %s", r.String()) } if len(commits.Values) == 0 { return "", errors.New("pull request doesn't have commits") } return commits.Values[0].Message, nil }