mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-24 06:14:37 +02:00
Introduce combined status
This commit is contained in:
@@ -10,20 +10,16 @@ import (
|
||||
"code.gitea.io/gitea/models/db"
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
issues_model "code.gitea.io/gitea/models/issues"
|
||||
"code.gitea.io/gitea/modules/commitstatus"
|
||||
"code.gitea.io/gitea/modules/gitrepo"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// MergeRequiredContextsCommitStatus returns a commit status state for given required contexts
|
||||
func MergeRequiredContextsCommitStatus(commitStatuses []*git_model.CommitStatus, requiredContexts []string) structs.CommitStatusState {
|
||||
// matchedCount is the number of `CommitStatus.Context` that match any context of `requiredContexts`
|
||||
matchedCount := 0
|
||||
returnedStatus := structs.CommitStatusSuccess
|
||||
|
||||
func MergeRequiredContextsCommitStatus(commitStatuses []*git_model.CommitStatus, requiredContexts []string) commitstatus.CombinedStatus {
|
||||
if len(requiredContexts) > 0 {
|
||||
requiredContextsGlob := make(map[string]glob.Glob, len(requiredContexts))
|
||||
for _, ctx := range requiredContexts {
|
||||
@@ -34,57 +30,35 @@ func MergeRequiredContextsCommitStatus(commitStatuses []*git_model.CommitStatus,
|
||||
}
|
||||
}
|
||||
|
||||
requiredCommitStatuses := make([]*git_model.CommitStatus, 0, len(commitStatuses))
|
||||
for _, gp := range requiredContextsGlob {
|
||||
var targetStatus structs.CommitStatusState
|
||||
for _, commitStatus := range commitStatuses {
|
||||
if gp.Match(commitStatus.Context) {
|
||||
targetStatus = commitStatus.State
|
||||
matchedCount++
|
||||
requiredCommitStatuses = append(requiredCommitStatuses, commitStatus)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If required rule not match any action, then it is pending
|
||||
if targetStatus == "" {
|
||||
if structs.CommitStatusPending.NoBetterThan(returnedStatus) {
|
||||
returnedStatus = structs.CommitStatusPending
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
if targetStatus.NoBetterThan(returnedStatus) {
|
||||
returnedStatus = targetStatus
|
||||
}
|
||||
}
|
||||
if len(requiredCommitStatuses) > 0 {
|
||||
return git_model.CalcCommitStatus(requiredCommitStatuses)
|
||||
}
|
||||
}
|
||||
|
||||
if matchedCount == 0 && returnedStatus == structs.CommitStatusSuccess {
|
||||
status := git_model.CalcCommitStatus(commitStatuses)
|
||||
if status != nil {
|
||||
return status.State
|
||||
}
|
||||
return structs.CommitStatusSuccess
|
||||
}
|
||||
|
||||
return returnedStatus
|
||||
return git_model.CalcCommitStatus(commitStatuses)
|
||||
}
|
||||
|
||||
// IsCommitStatusContextSuccess returns true if all required status check contexts succeed.
|
||||
func IsCommitStatusContextSuccess(commitStatuses []*git_model.CommitStatus, requiredContexts []string) bool {
|
||||
// If no specific context is required, require that last commit status is a success
|
||||
if len(requiredContexts) == 0 {
|
||||
status := git_model.CalcCommitStatus(commitStatuses)
|
||||
if status == nil || status.State != structs.CommitStatusSuccess {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
return git_model.CalcCommitStatus(commitStatuses) == commitstatus.CombinedStatusSuccess
|
||||
}
|
||||
|
||||
for _, ctx := range requiredContexts {
|
||||
var found bool
|
||||
for _, commitStatus := range commitStatuses {
|
||||
if commitStatus.Context == ctx {
|
||||
if commitStatus.State != structs.CommitStatusSuccess {
|
||||
if commitStatus.State != commitstatus.CommitStatusSuccess {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -117,7 +91,7 @@ func IsPullCommitStatusPass(ctx context.Context, pr *issues_model.PullRequest) (
|
||||
}
|
||||
|
||||
// GetPullRequestCommitStatusState returns pull request merged commit status state
|
||||
func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullRequest) (structs.CommitStatusState, error) {
|
||||
func GetPullRequestCommitStatusState(ctx context.Context, pr *issues_model.PullRequest) (commitstatus.CombinedStatus, error) {
|
||||
// Ensure HeadRepo is loaded
|
||||
if err := pr.LoadHeadRepo(ctx); err != nil {
|
||||
return "", errors.Wrap(err, "LoadHeadRepo")
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
git_model "code.gitea.io/gitea/models/git"
|
||||
"code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/commitstatus"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@@ -16,29 +16,29 @@ import (
|
||||
func TestMergeRequiredContextsCommitStatus(t *testing.T) {
|
||||
testCases := [][]*git_model.CommitStatus{
|
||||
{
|
||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 3", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 1", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 3", State: commitstatus.CommitStatusSuccess},
|
||||
},
|
||||
{
|
||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: structs.CommitStatusPending},
|
||||
{Context: "Build 1", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: commitstatus.CommitStatusPending},
|
||||
},
|
||||
{
|
||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: structs.CommitStatusFailure},
|
||||
{Context: "Build 1", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: commitstatus.CommitStatusFailure},
|
||||
},
|
||||
{
|
||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 1", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: commitstatus.CommitStatusSuccess},
|
||||
},
|
||||
{
|
||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: structs.CommitStatusSuccess},
|
||||
{Context: "Build 1", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2", State: commitstatus.CommitStatusSuccess},
|
||||
{Context: "Build 2t", State: commitstatus.CommitStatusSuccess},
|
||||
},
|
||||
}
|
||||
testCasesRequiredContexts := [][]string{
|
||||
@@ -49,12 +49,12 @@ func TestMergeRequiredContextsCommitStatus(t *testing.T) {
|
||||
{"Build*", "Build *", "Build 2t*", "Build 1*"},
|
||||
}
|
||||
|
||||
testCasesExpected := []structs.CommitStatusState{
|
||||
structs.CommitStatusSuccess,
|
||||
structs.CommitStatusPending,
|
||||
structs.CommitStatusFailure,
|
||||
structs.CommitStatusPending,
|
||||
structs.CommitStatusSuccess,
|
||||
testCasesExpected := []commitstatus.CombinedStatus{
|
||||
commitstatus.CombinedStatusSuccess,
|
||||
commitstatus.CombinedStatusPending,
|
||||
commitstatus.CombinedStatusFailure,
|
||||
commitstatus.CombinedStatusPending,
|
||||
commitstatus.CombinedStatusSuccess,
|
||||
}
|
||||
|
||||
for i, commitStatuses := range testCases {
|
||||
|
||||
@@ -946,13 +946,13 @@ func GetSquashMergeCommitMessages(ctx context.Context, pr *issues_model.PullRequ
|
||||
}
|
||||
|
||||
// GetIssuesLastCommitStatus returns a map of issue ID to the most recent commit's latest status
|
||||
func GetIssuesLastCommitStatus(ctx context.Context, issues issues_model.IssueList) (map[int64]*git_model.CommitStatus, error) {
|
||||
func GetIssuesLastCommitStatus(ctx context.Context, issues issues_model.IssueList) (map[int64]*git_model.CommitStatusSummary, error) {
|
||||
_, lastStatus, err := GetIssuesAllCommitStatus(ctx, issues)
|
||||
return lastStatus, err
|
||||
}
|
||||
|
||||
// GetIssuesAllCommitStatus returns a map of issue ID to a list of all statuses for the most recent commit as well as a map of issue ID to only the commit's latest status
|
||||
func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList) (map[int64][]*git_model.CommitStatus, map[int64]*git_model.CommitStatus, error) {
|
||||
func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList) (map[int64][]*git_model.CommitStatus, map[int64]*git_model.CommitStatusSummary, error) {
|
||||
if err := issues.LoadPullRequests(ctx); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@@ -963,7 +963,7 @@ func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList
|
||||
var (
|
||||
gitRepos = make(map[int64]*git.Repository)
|
||||
res = make(map[int64][]*git_model.CommitStatus)
|
||||
lastRes = make(map[int64]*git_model.CommitStatus)
|
||||
lastRes = make(map[int64]*git_model.CommitStatusSummary)
|
||||
err error
|
||||
)
|
||||
defer func() {
|
||||
@@ -986,27 +986,26 @@ func GetIssuesAllCommitStatus(ctx context.Context, issues issues_model.IssueList
|
||||
gitRepos[issue.RepoID] = gitRepo
|
||||
}
|
||||
|
||||
statuses, lastStatus, err := getAllCommitStatus(ctx, gitRepo, issue.PullRequest)
|
||||
statuses, err := getAllCommitStatus(ctx, gitRepo, issue.PullRequest)
|
||||
if err != nil {
|
||||
log.Error("getAllCommitStatus: cant get commit statuses of pull [%d]: %v", issue.PullRequest.ID, err)
|
||||
continue
|
||||
}
|
||||
res[issue.PullRequest.ID] = statuses
|
||||
lastRes[issue.PullRequest.ID] = lastStatus
|
||||
lastRes[issue.PullRequest.ID] = git_model.CalcCommitStatusSummary(statuses)
|
||||
}
|
||||
return res, lastRes, nil
|
||||
}
|
||||
|
||||
// getAllCommitStatus get pr's commit statuses.
|
||||
func getAllCommitStatus(ctx context.Context, gitRepo *git.Repository, pr *issues_model.PullRequest) (statuses []*git_model.CommitStatus, lastStatus *git_model.CommitStatus, err error) {
|
||||
func getAllCommitStatus(ctx context.Context, gitRepo *git.Repository, pr *issues_model.PullRequest) (statuses []*git_model.CommitStatus, err error) {
|
||||
sha, shaErr := gitRepo.GetRefCommitID(pr.GetGitRefName())
|
||||
if shaErr != nil {
|
||||
return nil, nil, shaErr
|
||||
return nil, shaErr
|
||||
}
|
||||
|
||||
statuses, _, err = git_model.GetLatestCommitStatus(ctx, pr.BaseRepo.ID, sha, db.ListOptionsAll)
|
||||
lastStatus = git_model.CalcCommitStatus(statuses)
|
||||
return statuses, lastStatus, err
|
||||
return statuses, err
|
||||
}
|
||||
|
||||
// IsHeadEqualWithBranch returns if the commits of branchName are available in pull request head
|
||||
|
||||
Reference in New Issue
Block a user