github.com/traefik/lobicornis@v1.3.0/gh/state.go (about) 1 package gh 2 3 import ( 4 "context" 5 "errors" 6 "fmt" 7 "log" 8 9 "github.com/google/go-github/github" 10 ) 11 12 const ( 13 // Pending Check state 14 Pending = "pending" 15 // Success Check state 16 Success = "success" 17 18 // Approved Review state 19 Approved = "APPROVED" 20 // Commented Review state 21 Commented = "COMMENTED" 22 // Dismissed Review state 23 Dismissed = "DISMISSED" 24 ) 25 26 // HasReviewsApprove check if a PR have the required number of review 27 func (g *GHub) HasReviewsApprove(ctx context.Context, pr *github.PullRequest, minReview int) error { 28 if minReview != 0 { 29 30 owner := pr.Base.Repo.Owner.GetLogin() 31 repositoryName := pr.Base.Repo.GetName() 32 prNumber := pr.GetNumber() 33 34 opt := &github.ListOptions{ 35 PerPage: 100, 36 } 37 38 reviewsState := make(map[string]string) 39 for { 40 reviews, resp, err := g.client.PullRequests.ListReviews(ctx, owner, repositoryName, prNumber, opt) 41 if err != nil { 42 return err 43 } 44 45 for _, review := range reviews { 46 if review.GetState() == Dismissed { 47 delete(reviewsState, review.User.GetLogin()) 48 } else if review.GetState() != Commented { 49 reviewsState[review.User.GetLogin()] = review.GetState() 50 } 51 } 52 if resp.NextPage == 0 { 53 break 54 } 55 opt.Page = resp.NextPage 56 } 57 58 if len(reviewsState) < minReview { 59 return fmt.Errorf("need more review [%v/2]", len(reviewsState)) 60 } 61 62 for login, state := range reviewsState { 63 if state != Approved { 64 return fmt.Errorf("%s by %s", state, login) 65 } 66 } 67 } 68 return nil 69 } 70 71 // IsUpToDateBranch check if a PR is up to date 72 func (g *GHub) IsUpToDateBranch(ctx context.Context, pr *github.PullRequest) (bool, error) { 73 cc, _, err := g.client.Repositories.CompareCommits(ctx, 74 pr.Base.Repo.Owner.GetLogin(), pr.Base.Repo.GetName(), 75 pr.Base.GetRef(), fmt.Sprintf("%s:%s", pr.Head.User.GetLogin(), pr.Head.GetRef())) 76 if err != nil { 77 return false, err 78 } 79 80 if g.debug { 81 log.Println("Merge Base Commit:", cc.MergeBaseCommit.GetSHA()) 82 log.Println("Behind By:", cc.GetBehindBy()) 83 } 84 85 return cc.GetBehindBy() == 0, nil 86 } 87 88 // GetStatus provide checks status (CI) 89 func (g *GHub) GetStatus(ctx context.Context, pr *github.PullRequest) (string, error) { 90 91 owner := pr.Base.Repo.Owner.GetLogin() 92 repositoryName := pr.Base.Repo.GetName() 93 prRef := pr.Head.GetSHA() 94 95 sts, _, err := g.client.Repositories.GetCombinedStatus(ctx, owner, repositoryName, prRef, nil) 96 if err != nil { 97 return "", err 98 } 99 100 if sts.GetState() == Success { 101 return sts.GetState(), nil 102 } 103 104 // pending: if there are no statuses or a context is pending 105 // https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref 106 if sts.GetState() == Pending { 107 if sts.GetTotalCount() == 0 { 108 return Success, nil 109 } 110 return sts.GetState(), nil 111 } 112 113 statuses, _, err := g.client.Repositories.ListStatuses(ctx, owner, repositoryName, prRef, nil) 114 if err != nil { 115 return "", err 116 } 117 var summary string 118 for _, stat := range statuses { 119 if stat.GetState() != Success { 120 summary += stat.GetDescription() + "\n" 121 } 122 } 123 return "", errors.New(summary) 124 }