mirror of
https://github.com/harness/drone.git
synced 2025-05-12 23:20:10 +08:00
162 lines
4.4 KiB
Go
162 lines
4.4 KiB
Go
// Copyright 2022 Harness Inc. All rights reserved.
|
|
// Use of this source code is governed by the Polyform Free Trial License
|
|
// that can be found in the LICENSE.md file for this repository.
|
|
|
|
package pullreq
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/harness/gitness/events"
|
|
"github.com/harness/gitness/gitrpc"
|
|
gitrpcenum "github.com/harness/gitness/gitrpc/enum"
|
|
gitevents "github.com/harness/gitness/internal/events/git"
|
|
"github.com/harness/gitness/types"
|
|
"github.com/harness/gitness/types/enum"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
func (s *Service) handleEventBranchUpdated(ctx context.Context,
|
|
event *events.Event[*gitevents.BranchUpdatedPayload],
|
|
) error {
|
|
s.forEveryOpenPR(ctx, event.Payload.RepoID, event.Payload.Ref, func(pr *types.PullReq) error {
|
|
targetRepo, err := s.repoStore.Find(ctx, pr.TargetRepoID)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get target repository after branch update: %w", err)
|
|
}
|
|
|
|
// TODO: This doesn't work for forked repos (only works when sourceRepo==targetRepo)
|
|
err = s.gitRPCClient.UpdateRef(ctx, gitrpc.UpdateRefParams{
|
|
WriteParams: gitrpc.WriteParams{RepoUID: targetRepo.GitUID},
|
|
Name: strconv.Itoa(int(pr.Number)),
|
|
Type: gitrpcenum.RefTypePullReqHead,
|
|
NewValue: event.Payload.NewSHA,
|
|
OldValue: event.Payload.OldSHA,
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to update PR head ref after branch update: %w", err)
|
|
}
|
|
|
|
pr, err = s.pullreqStore.UpdateActivitySeq(ctx, pr)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to get pull request activity number after branch update: %w", err)
|
|
}
|
|
|
|
now := time.Now().UnixMilli()
|
|
act := &types.PullReqActivity{
|
|
CreatedBy: event.Payload.PrincipalID,
|
|
Created: now,
|
|
Updated: now,
|
|
Edited: now,
|
|
RepoID: pr.TargetRepoID,
|
|
PullReqID: pr.ID,
|
|
Order: pr.ActivitySeq,
|
|
SubOrder: 0,
|
|
ReplySeq: 0,
|
|
Type: enum.PullReqActivityTypeBranchUpdate,
|
|
Kind: enum.PullReqActivityKindSystem,
|
|
Text: "",
|
|
}
|
|
|
|
_ = act.SetPayload(&types.PullRequestActivityPayloadBranchUpdate{
|
|
Old: event.Payload.OldSHA,
|
|
New: event.Payload.NewSHA,
|
|
})
|
|
|
|
err = s.activityStore.Create(ctx, act)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create pull request activity: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) handleEventBranchDeleted(ctx context.Context,
|
|
event *events.Event[*gitevents.BranchDeletedPayload],
|
|
) error {
|
|
s.forEveryOpenPR(ctx, event.Payload.RepoID, event.Payload.Ref, func(pr *types.PullReq) error {
|
|
pr, err := s.pullreqStore.UpdateOptLock(ctx, pr, func(pr *types.PullReq) error {
|
|
pr.ActivitySeq++
|
|
pr.State = enum.PullReqStateClosed
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("failed to close and get pull request activity number after branch delete: %w", err)
|
|
}
|
|
|
|
now := time.Now().UnixMilli()
|
|
act := &types.PullReqActivity{
|
|
CreatedBy: event.Payload.PrincipalID,
|
|
Created: now,
|
|
Updated: now,
|
|
Edited: now,
|
|
RepoID: pr.TargetRepoID,
|
|
PullReqID: pr.ID,
|
|
Order: pr.ActivitySeq,
|
|
SubOrder: 0,
|
|
ReplySeq: 0,
|
|
Type: enum.PullReqActivityTypeBranchDelete,
|
|
Kind: enum.PullReqActivityKindSystem,
|
|
Text: "",
|
|
}
|
|
|
|
_ = act.SetPayload(&types.PullRequestActivityPayloadBranchDelete{
|
|
SHA: event.Payload.SHA,
|
|
})
|
|
|
|
err = s.activityStore.Create(ctx, act)
|
|
if err != nil {
|
|
return fmt.Errorf("failed to create pull request activity: %w", err)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
return nil
|
|
}
|
|
|
|
func (s *Service) forEveryOpenPR(ctx context.Context,
|
|
repoID int64, ref string,
|
|
fn func(pr *types.PullReq) error,
|
|
) {
|
|
const refPrefix = "refs/heads/"
|
|
const largeLimit = 1000000
|
|
|
|
if !strings.HasPrefix(ref, refPrefix) {
|
|
log.Ctx(ctx).Error().Msg("failed to get branch name from branch ref")
|
|
return
|
|
}
|
|
|
|
branch := ref[len(refPrefix):]
|
|
if len(branch) == 0 {
|
|
log.Ctx(ctx).Error().Msg("got an empty branch name from branch ref")
|
|
return
|
|
}
|
|
|
|
pullreqList, err := s.pullreqStore.List(ctx, &types.PullReqFilter{
|
|
Page: 0,
|
|
Size: largeLimit,
|
|
SourceRepoID: repoID,
|
|
SourceBranch: branch,
|
|
States: []enum.PullReqState{enum.PullReqStateOpen},
|
|
Sort: enum.PullReqSortNumber,
|
|
Order: enum.OrderAsc,
|
|
})
|
|
if err != nil {
|
|
log.Ctx(ctx).Err(err).Msg("failed to get list of open pull requests")
|
|
return
|
|
}
|
|
|
|
for _, pr := range pullreqList {
|
|
if err = fn(pr); err != nil {
|
|
log.Ctx(ctx).Err(err).Msg("failed to process pull req")
|
|
}
|
|
}
|
|
}
|