summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--integrations/pull_status_test.go25
-rw-r--r--models/commit_status.go59
-rw-r--r--models/commit_status_test.go11
-rw-r--r--modules/structs/attachment.go1
-rw-r--r--modules/structs/commit_status.go63
-rw-r--r--routers/api/v1/repo/status.go18
-rw-r--r--routers/repo/pull.go4
-rw-r--r--services/pull/commit_status.go57
-rw-r--r--templates/repo/issue/view_content/pull.tmpl5
9 files changed, 159 insertions, 84 deletions
diff --git a/integrations/pull_status_test.go b/integrations/pull_status_test.go
index fde2d3cc9b..95ed755fbb 100644
--- a/integrations/pull_status_test.go
+++ b/integrations/pull_status_test.go
@@ -11,7 +11,6 @@ import (
"strings"
"testing"
- "code.gitea.io/gitea/models"
api "code.gitea.io/gitea/modules/structs"
"github.com/stretchr/testify/assert"
@@ -48,20 +47,20 @@ func TestPullCreate_CommitStatus(t *testing.T) {
commitID := path.Base(commitURL)
- statusList := []models.CommitStatusState{
- models.CommitStatusPending,
- models.CommitStatusError,
- models.CommitStatusFailure,
- models.CommitStatusWarning,
- models.CommitStatusSuccess,
+ statusList := []api.CommitStatusState{
+ api.CommitStatusPending,
+ api.CommitStatusError,
+ api.CommitStatusFailure,
+ api.CommitStatusWarning,
+ api.CommitStatusSuccess,
}
- statesIcons := map[models.CommitStatusState]string{
- models.CommitStatusPending: "circle icon yellow",
- models.CommitStatusSuccess: "check icon green",
- models.CommitStatusError: "warning icon red",
- models.CommitStatusFailure: "remove icon red",
- models.CommitStatusWarning: "warning sign icon yellow",
+ statesIcons := map[api.CommitStatusState]string{
+ api.CommitStatusPending: "circle icon yellow",
+ api.CommitStatusSuccess: "check icon green",
+ api.CommitStatusError: "warning icon red",
+ api.CommitStatusFailure: "remove icon red",
+ api.CommitStatusWarning: "warning sign icon yellow",
}
// Update commit status, and check if icon is updated as well
diff --git a/models/commit_status.go b/models/commit_status.go
index 4e0f8166f3..4102e731e1 100644
--- a/models/commit_status.go
+++ b/models/commit_status.go
@@ -19,52 +19,19 @@ import (
"xorm.io/xorm"
)
-// CommitStatusState holds the state of a Status
-// It can be "pending", "success", "error", "failure", and "warning"
-type CommitStatusState string
-
-// IsWorseThan returns true if this State is worse than the given State
-func (css CommitStatusState) IsWorseThan(css2 CommitStatusState) bool {
- switch css {
- case CommitStatusError:
- return true
- case CommitStatusFailure:
- return css2 != CommitStatusError
- case CommitStatusWarning:
- return css2 != CommitStatusError && css2 != CommitStatusFailure
- case CommitStatusSuccess:
- return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning
- default:
- return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning && css2 != CommitStatusSuccess
- }
-}
-
-const (
- // CommitStatusPending is for when the Status is Pending
- CommitStatusPending CommitStatusState = "pending"
- // CommitStatusSuccess is for when the Status is Success
- CommitStatusSuccess CommitStatusState = "success"
- // CommitStatusError is for when the Status is Error
- CommitStatusError CommitStatusState = "error"
- // CommitStatusFailure is for when the Status is Failure
- CommitStatusFailure CommitStatusState = "failure"
- // CommitStatusWarning is for when the Status is Warning
- CommitStatusWarning CommitStatusState = "warning"
-)
-
// CommitStatus holds a single Status of a single Commit
type CommitStatus struct {
- ID int64 `xorm:"pk autoincr"`
- Index int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
- RepoID int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
- Repo *Repository `xorm:"-"`
- State CommitStatusState `xorm:"VARCHAR(7) NOT NULL"`
- SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
- TargetURL string `xorm:"TEXT"`
- Description string `xorm:"TEXT"`
- ContextHash string `xorm:"char(40) index"`
- Context string `xorm:"TEXT"`
- Creator *User `xorm:"-"`
+ ID int64 `xorm:"pk autoincr"`
+ Index int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
+ RepoID int64 `xorm:"INDEX UNIQUE(repo_sha_index)"`
+ Repo *Repository `xorm:"-"`
+ State api.CommitStatusState `xorm:"VARCHAR(7) NOT NULL"`
+ SHA string `xorm:"VARCHAR(64) NOT NULL INDEX UNIQUE(repo_sha_index)"`
+ TargetURL string `xorm:"TEXT"`
+ Description string `xorm:"TEXT"`
+ ContextHash string `xorm:"char(40) index"`
+ Context string `xorm:"TEXT"`
+ Creator *User `xorm:"-"`
CreatorID int64
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
@@ -118,9 +85,9 @@ func (status *CommitStatus) APIFormat() *api.Status {
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
var lastStatus *CommitStatus
- var state CommitStatusState
+ var state api.CommitStatusState
for _, status := range statuses {
- if status.State.IsWorseThan(state) {
+ if status.State.NoBetterThan(state) {
state = status.State
lastStatus = status
}
diff --git a/models/commit_status_test.go b/models/commit_status_test.go
index 97783ae6f1..90d72cd74d 100644
--- a/models/commit_status_test.go
+++ b/models/commit_status_test.go
@@ -7,6 +7,7 @@ package models
import (
"testing"
+ "code.gitea.io/gitea/modules/structs"
"github.com/stretchr/testify/assert"
)
@@ -23,22 +24,22 @@ func TestGetCommitStatuses(t *testing.T) {
assert.Len(t, statuses, 5)
assert.Equal(t, "ci/awesomeness", statuses[0].Context)
- assert.Equal(t, CommitStatusPending, statuses[0].State)
+ assert.Equal(t, structs.CommitStatusPending, statuses[0].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[0].APIURL())
assert.Equal(t, "cov/awesomeness", statuses[1].Context)
- assert.Equal(t, CommitStatusWarning, statuses[1].State)
+ assert.Equal(t, structs.CommitStatusWarning, statuses[1].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[1].APIURL())
assert.Equal(t, "cov/awesomeness", statuses[2].Context)
- assert.Equal(t, CommitStatusSuccess, statuses[2].State)
+ assert.Equal(t, structs.CommitStatusSuccess, statuses[2].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[2].APIURL())
assert.Equal(t, "ci/awesomeness", statuses[3].Context)
- assert.Equal(t, CommitStatusFailure, statuses[3].State)
+ assert.Equal(t, structs.CommitStatusFailure, statuses[3].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[3].APIURL())
assert.Equal(t, "deploy/awesomeness", statuses[4].Context)
- assert.Equal(t, CommitStatusError, statuses[4].State)
+ assert.Equal(t, structs.CommitStatusError, statuses[4].State)
assert.Equal(t, "https://try.gitea.io/api/v1/repos/user2/repo1/statuses/1234123412341234123412341234123412341234", statuses[4].APIURL())
}
diff --git a/modules/structs/attachment.go b/modules/structs/attachment.go
index 954956f328..7becd94335 100644
--- a/modules/structs/attachment.go
+++ b/modules/structs/attachment.go
@@ -3,6 +3,7 @@
// license that can be found in the LICENSE file.
package structs // import "code.gitea.io/gitea/modules/structs"
+
import (
"time"
)
diff --git a/modules/structs/commit_status.go b/modules/structs/commit_status.go
new file mode 100644
index 0000000000..397356b133
--- /dev/null
+++ b/modules/structs/commit_status.go
@@ -0,0 +1,63 @@
+// Copyright 2020 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package structs
+
+// CommitStatusState holds the state of a Status
+// It can be "pending", "success", "error", "failure", and "warning"
+type CommitStatusState string
+
+const (
+ // CommitStatusPending is for when the Status is Pending
+ CommitStatusPending CommitStatusState = "pending"
+ // CommitStatusSuccess is for when the Status is Success
+ CommitStatusSuccess CommitStatusState = "success"
+ // CommitStatusError is for when the Status is Error
+ CommitStatusError CommitStatusState = "error"
+ // CommitStatusFailure is for when the Status is Failure
+ CommitStatusFailure CommitStatusState = "failure"
+ // CommitStatusWarning is for when the Status is Warning
+ CommitStatusWarning CommitStatusState = "warning"
+)
+
+// NoBetterThan returns true if this State is no better than the given State
+func (css CommitStatusState) NoBetterThan(css2 CommitStatusState) bool {
+ switch css {
+ case CommitStatusError:
+ return true
+ case CommitStatusFailure:
+ return css2 != CommitStatusError
+ case CommitStatusWarning:
+ return css2 != CommitStatusError && css2 != CommitStatusFailure
+ case CommitStatusPending:
+ return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning
+ default:
+ return css2 != CommitStatusError && css2 != CommitStatusFailure && css2 != CommitStatusWarning && css2 != CommitStatusPending
+ }
+}
+
+// IsPending represents if commit status state is pending
+func (css CommitStatusState) IsPending() bool {
+ return css == CommitStatusPending
+}
+
+// IsSuccess represents if commit status state is success
+func (css CommitStatusState) IsSuccess() bool {
+ return css == CommitStatusSuccess
+}
+
+// IsError represents if commit status state is error
+func (css CommitStatusState) IsError() bool {
+ return css == CommitStatusError
+}
+
+// IsFailure represents if commit status state is failure
+func (css CommitStatusState) IsFailure() bool {
+ return css == CommitStatusFailure
+}
+
+// IsWarning represents if commit status state is warning
+func (css CommitStatusState) IsWarning() bool {
+ return css == CommitStatusWarning
+}
diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go
index c137b64f5c..b6b3d495ca 100644
--- a/routers/api/v1/repo/status.go
+++ b/routers/api/v1/repo/status.go
@@ -53,7 +53,7 @@ func NewCommitStatus(ctx *context.APIContext, form api.CreateStatusOption) {
return
}
status := &models.CommitStatus{
- State: models.CommitStatusState(form.State),
+ State: api.CommitStatusState(form.State),
TargetURL: form.TargetURL,
Description: form.Description,
Context: form.Context,
@@ -220,13 +220,13 @@ func getCommitStatuses(ctx *context.APIContext, sha string) {
}
type combinedCommitStatus struct {
- State models.CommitStatusState `json:"state"`
- SHA string `json:"sha"`
- TotalCount int `json:"total_count"`
- Statuses []*api.Status `json:"statuses"`
- Repo *api.Repository `json:"repository"`
- CommitURL string `json:"commit_url"`
- URL string `json:"url"`
+ State api.CommitStatusState `json:"state"`
+ SHA string `json:"sha"`
+ TotalCount int `json:"total_count"`
+ Statuses []*api.Status `json:"statuses"`
+ Repo *api.Repository `json:"repository"`
+ CommitURL string `json:"commit_url"`
+ URL string `json:"url"`
}
// GetCombinedCommitStatusByRef returns the combined status for any given commit hash
@@ -293,7 +293,7 @@ func GetCombinedCommitStatusByRef(ctx *context.APIContext) {
retStatus.Statuses = make([]*api.Status, 0, len(statuses))
for _, status := range statuses {
retStatus.Statuses = append(retStatus.Statuses, status.APIFormat())
- if status.State.IsWorseThan(retStatus.State) {
+ if status.State.NoBetterThan(retStatus.State) {
retStatus.State = status.State
}
}
diff --git a/routers/repo/pull.go b/routers/repo/pull.go
index f6397096e2..c84174783a 100644
--- a/routers/repo/pull.go
+++ b/routers/repo/pull.go
@@ -417,7 +417,9 @@ func PrepareViewPullInfo(ctx *context.Context, issue *models.Issue) *git.Compare
}
return false
}
- ctx.Data["IsRequiredStatusCheckSuccess"] = pull_service.IsCommitStatusContextSuccess(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
+ state := pull_service.MergeRequiredContextsCommitStatus(commitStatuses, pull.ProtectedBranch.StatusCheckContexts)
+ ctx.Data["RequiredStatusCheckState"] = state
+ ctx.Data["IsRequiredStatusCheckSuccess"] = state.IsSuccess()
}
ctx.Data["HeadBranchMovedOn"] = headBranchSha != sha
diff --git a/services/pull/commit_status.go b/services/pull/commit_status.go
index ca00cdaad9..3dccfb1f0c 100644
--- a/services/pull/commit_status.go
+++ b/services/pull/commit_status.go
@@ -8,15 +8,47 @@ package pull
import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
+ "code.gitea.io/gitea/modules/structs"
+
"github.com/pkg/errors"
)
+// MergeRequiredContextsCommitStatus returns a commit status state for given required contexts
+func MergeRequiredContextsCommitStatus(commitStatuses []*models.CommitStatus, requiredContexts []string) structs.CommitStatusState {
+ if len(requiredContexts) == 0 {
+ status := models.CalcCommitStatus(commitStatuses)
+ if status != nil {
+ return status.State
+ }
+ return structs.CommitStatusSuccess
+ }
+
+ var returnedStatus = structs.CommitStatusPending
+ for _, ctx := range requiredContexts {
+ var targetStatus structs.CommitStatusState
+ for _, commitStatus := range commitStatuses {
+ if commitStatus.Context == ctx {
+ targetStatus = commitStatus.State
+ break
+ }
+ }
+
+ if targetStatus == "" {
+ targetStatus = structs.CommitStatusPending
+ }
+ if targetStatus.NoBetterThan(returnedStatus) {
+ returnedStatus = targetStatus
+ }
+ }
+ return returnedStatus
+}
+
// IsCommitStatusContextSuccess returns true if all required status check contexts succeed.
func IsCommitStatusContextSuccess(commitStatuses []*models.CommitStatus, requiredContexts []string) bool {
// If no specific context is required, require that last commit status is a success
if len(requiredContexts) == 0 {
status := models.CalcCommitStatus(commitStatuses)
- if status == nil || status.State != models.CommitStatusSuccess {
+ if status == nil || status.State != structs.CommitStatusSuccess {
return false
}
return true
@@ -26,7 +58,7 @@ func IsCommitStatusContextSuccess(commitStatuses []*models.CommitStatus, require
var found bool
for _, commitStatus := range commitStatuses {
if commitStatus.Context == ctx {
- if commitStatus.State != models.CommitStatusSuccess {
+ if commitStatus.State != structs.CommitStatusSuccess {
return false
}
@@ -50,30 +82,39 @@ func IsPullCommitStatusPass(pr *models.PullRequest) (bool, error) {
return true, nil
}
+ state, err := GetPullRequestCommitStatusState(pr)
+ if err != nil {
+ return false, err
+ }
+ return state.IsSuccess(), nil
+}
+
+// GetPullRequestCommitStatusState returns pull request merged commit status state
+func GetPullRequestCommitStatusState(pr *models.PullRequest) (structs.CommitStatusState, error) {
// check if all required status checks are successful
headGitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
if err != nil {
- return false, errors.Wrap(err, "OpenRepository")
+ return "", errors.Wrap(err, "OpenRepository")
}
defer headGitRepo.Close()
if !headGitRepo.IsBranchExist(pr.HeadBranch) {
- return false, errors.New("Head branch does not exist, can not merge")
+ return "", errors.New("Head branch does not exist, can not merge")
}
sha, err := headGitRepo.GetBranchCommitID(pr.HeadBranch)
if err != nil {
- return false, errors.Wrap(err, "GetBranchCommitID")
+ return "", errors.Wrap(err, "GetBranchCommitID")
}
if err := pr.LoadBaseRepo(); err != nil {
- return false, errors.Wrap(err, "LoadBaseRepo")
+ return "", errors.Wrap(err, "LoadBaseRepo")
}
commitStatuses, err := models.GetLatestCommitStatus(pr.BaseRepo, sha, 0)
if err != nil {
- return false, errors.Wrap(err, "GetLatestCommitStatus")
+ return "", errors.Wrap(err, "GetLatestCommitStatus")
}
- return IsCommitStatusContextSuccess(commitStatuses, pr.ProtectedBranch.StatusCheckContexts), nil
+ return MergeRequiredContextsCommitStatus(commitStatuses, pr.ProtectedBranch.StatusCheckContexts), nil
}
diff --git a/templates/repo/issue/view_content/pull.tmpl b/templates/repo/issue/view_content/pull.tmpl
index e0a48442e0..32c744515c 100644
--- a/templates/repo/issue/view_content/pull.tmpl
+++ b/templates/repo/issue/view_content/pull.tmpl
@@ -47,7 +47,8 @@
{{else if .IsPullRequestBroken}}red
{{else if .IsBlockedByApprovals}}red
{{else if .IsBlockedByRejection}}red
- {{else if and .EnableStatusCheck (not .IsRequiredStatusCheckSuccess)}}red
+ {{else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsFailure .RequiredStatusCheckState.IsError)}}red
+ {{else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsPending .RequiredStatusCheckState.IsWarning)}}yellow
{{else if and .RequireSigned (not .WillSign)}}}red
{{else if .Issue.PullRequest.IsChecking}}yellow
{{else if .Issue.PullRequest.CanAutoMerge}}green
@@ -118,7 +119,7 @@
<i class="icon icon-octicon"><span class="octicon octicon-x"></span></i>
{{$.i18n.Tr "repo.pulls.blocked_by_rejection"}}
</div>
- {{else if and .EnableStatusCheck (not .IsRequiredStatusCheckSuccess)}}
+ {{else if and .EnableStatusCheck (or .RequiredStatusCheckState.IsError .RequiredStatusCheckState.IsFailure)}}
<div class="item text red">
<i class="icon icon-octicon"><span class="octicon octicon-x"></span></i>
{{$.i18n.Tr "repo.pulls.required_status_check_failed"}}