You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

commit_status.go 3.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // Copyright 2019 The Gitea Authors.
  2. // All rights reserved.
  3. // Use of this source code is governed by a MIT-style
  4. // license that can be found in the LICENSE file.
  5. package pull
  6. import (
  7. "code.gitea.io/gitea/models"
  8. "code.gitea.io/gitea/modules/git"
  9. "code.gitea.io/gitea/modules/structs"
  10. "github.com/pkg/errors"
  11. )
  12. // MergeRequiredContextsCommitStatus returns a commit status state for given required contexts
  13. func MergeRequiredContextsCommitStatus(commitStatuses []*models.CommitStatus, requiredContexts []string) structs.CommitStatusState {
  14. if len(requiredContexts) == 0 {
  15. status := models.CalcCommitStatus(commitStatuses)
  16. if status != nil {
  17. return status.State
  18. }
  19. return structs.CommitStatusSuccess
  20. }
  21. var returnedStatus = structs.CommitStatusSuccess
  22. for _, ctx := range requiredContexts {
  23. var targetStatus structs.CommitStatusState
  24. for _, commitStatus := range commitStatuses {
  25. if commitStatus.Context == ctx {
  26. targetStatus = commitStatus.State
  27. break
  28. }
  29. }
  30. if targetStatus == "" {
  31. targetStatus = structs.CommitStatusPending
  32. }
  33. if targetStatus.NoBetterThan(returnedStatus) {
  34. returnedStatus = targetStatus
  35. }
  36. }
  37. return returnedStatus
  38. }
  39. // IsCommitStatusContextSuccess returns true if all required status check contexts succeed.
  40. func IsCommitStatusContextSuccess(commitStatuses []*models.CommitStatus, requiredContexts []string) bool {
  41. // If no specific context is required, require that last commit status is a success
  42. if len(requiredContexts) == 0 {
  43. status := models.CalcCommitStatus(commitStatuses)
  44. if status == nil || status.State != structs.CommitStatusSuccess {
  45. return false
  46. }
  47. return true
  48. }
  49. for _, ctx := range requiredContexts {
  50. var found bool
  51. for _, commitStatus := range commitStatuses {
  52. if commitStatus.Context == ctx {
  53. if commitStatus.State != structs.CommitStatusSuccess {
  54. return false
  55. }
  56. found = true
  57. break
  58. }
  59. }
  60. if !found {
  61. return false
  62. }
  63. }
  64. return true
  65. }
  66. // IsPullCommitStatusPass returns if all required status checks PASS
  67. func IsPullCommitStatusPass(pr *models.PullRequest) (bool, error) {
  68. if err := pr.LoadProtectedBranch(); err != nil {
  69. return false, errors.Wrap(err, "GetLatestCommitStatus")
  70. }
  71. if pr.ProtectedBranch == nil || !pr.ProtectedBranch.EnableStatusCheck {
  72. return true, nil
  73. }
  74. state, err := GetPullRequestCommitStatusState(pr)
  75. if err != nil {
  76. return false, err
  77. }
  78. return state.IsSuccess(), nil
  79. }
  80. // GetPullRequestCommitStatusState returns pull request merged commit status state
  81. func GetPullRequestCommitStatusState(pr *models.PullRequest) (structs.CommitStatusState, error) {
  82. // Ensure HeadRepo is loaded
  83. if err := pr.LoadHeadRepo(); err != nil {
  84. return "", errors.Wrap(err, "LoadHeadRepo")
  85. }
  86. // check if all required status checks are successful
  87. headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
  88. if err != nil {
  89. return "", errors.Wrap(err, "OpenRepository")
  90. }
  91. defer headGitRepo.Close()
  92. if !headGitRepo.IsBranchExist(pr.HeadBranch) {
  93. return "", errors.New("Head branch does not exist, can not merge")
  94. }
  95. sha, err := headGitRepo.GetBranchCommitID(pr.HeadBranch)
  96. if err != nil {
  97. return "", errors.Wrap(err, "GetBranchCommitID")
  98. }
  99. if err := pr.LoadBaseRepo(); err != nil {
  100. return "", errors.Wrap(err, "LoadBaseRepo")
  101. }
  102. commitStatuses, err := models.GetLatestCommitStatus(pr.BaseRepo, sha, 0)
  103. if err != nil {
  104. return "", errors.Wrap(err, "GetLatestCommitStatus")
  105. }
  106. return MergeRequiredContextsCommitStatus(commitStatuses, pr.ProtectedBranch.StatusCheckContexts), nil
  107. }