mirror of https://github.com/go-gitea/gitea.git
Fix actions skipped commit status indicator (#34507)
Addresses https://github.com/go-gitea/gitea/issues/34500 Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>pull/34531/head^2
parent
c6e2093f42
commit
0cec4b84e2
|
@ -230,18 +230,24 @@ func (status *CommitStatus) HideActionsURL(ctx context.Context) {
|
||||||
|
|
||||||
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
|
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
|
||||||
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
|
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
|
||||||
|
// This function is widely used, but it is not quite right.
|
||||||
|
// Ideally it should return something like "CommitStatusSummary" with properly aggregated state.
|
||||||
|
// GitHub's behavior: if all statuses are "skipped", GitHub will return "success" as the combined status.
|
||||||
var lastStatus *CommitStatus
|
var lastStatus *CommitStatus
|
||||||
state := api.CommitStatusSuccess
|
state := api.CommitStatusSuccess
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
if status.State.NoBetterThan(state) {
|
if state == status.State || status.State.HasHigherPriorityThan(state) {
|
||||||
state = status.State
|
state = status.State
|
||||||
lastStatus = status
|
lastStatus = status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if lastStatus == nil {
|
if lastStatus == nil {
|
||||||
if len(statuses) > 0 {
|
if len(statuses) > 0 {
|
||||||
|
// FIXME: a bad case: Gitea just returns the first commit status, its status is "skipped" in this case.
|
||||||
lastStatus = statuses[0]
|
lastStatus = statuses[0]
|
||||||
} else {
|
} else {
|
||||||
|
// FIXME: another bad case: if the "statuses" slice is empty, the returned value is an invalid CommitStatus, all its fields are empty.
|
||||||
|
// Frontend code (tmpl&vue) sometimes depend on the empty fields to skip rendering commit status elements (need to double check in the future)
|
||||||
lastStatus = &CommitStatus{}
|
lastStatus = &CommitStatus{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,11 @@ func UpdateCommitStatusSummary(ctx context.Context, repoID int64, sha string) er
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
state := CalcCommitStatus(commitStatuses)
|
// it guarantees that commitStatuses is not empty because this function is always called after a commit status is created
|
||||||
|
if len(commitStatuses) == 0 {
|
||||||
|
setting.PanicInDevOrTesting("no commit statuses found for repo %d and sha %s", repoID, sha)
|
||||||
|
}
|
||||||
|
state := CalcCommitStatus(commitStatuses) // non-empty commitStatuses is guaranteed
|
||||||
// mysql will return 0 when update a record which state hasn't been changed which behaviour is different from other database,
|
// mysql will return 0 when update a record which state hasn't been changed which behaviour is different from other database,
|
||||||
// so we need to use insert in on duplicate
|
// so we need to use insert in on duplicate
|
||||||
if setting.Database.Type.IsMySQL() {
|
if setting.Database.Type.IsMySQL() {
|
||||||
|
|
|
@ -18,6 +18,8 @@ const (
|
||||||
CommitStatusFailure CommitStatusState = "failure"
|
CommitStatusFailure CommitStatusState = "failure"
|
||||||
// CommitStatusWarning is for when the CommitStatus is Warning
|
// CommitStatusWarning is for when the CommitStatus is Warning
|
||||||
CommitStatusWarning CommitStatusState = "warning"
|
CommitStatusWarning CommitStatusState = "warning"
|
||||||
|
// CommitStatusSkipped is for when CommitStatus is Skipped
|
||||||
|
CommitStatusSkipped CommitStatusState = "skipped"
|
||||||
)
|
)
|
||||||
|
|
||||||
var commitStatusPriorities = map[CommitStatusState]int{
|
var commitStatusPriorities = map[CommitStatusState]int{
|
||||||
|
@ -26,25 +28,17 @@ var commitStatusPriorities = map[CommitStatusState]int{
|
||||||
CommitStatusWarning: 2,
|
CommitStatusWarning: 2,
|
||||||
CommitStatusPending: 3,
|
CommitStatusPending: 3,
|
||||||
CommitStatusSuccess: 4,
|
CommitStatusSuccess: 4,
|
||||||
|
CommitStatusSkipped: 5,
|
||||||
}
|
}
|
||||||
|
|
||||||
func (css CommitStatusState) String() string {
|
func (css CommitStatusState) String() string {
|
||||||
return string(css)
|
return string(css)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoBetterThan returns true if this State is no better than the given State
|
// HasHigherPriorityThan returns true if this state has higher priority than the other
|
||||||
// This function only handles the states defined in CommitStatusPriorities
|
// Undefined states are considered to have the highest priority like CommitStatusError(0)
|
||||||
func (css CommitStatusState) NoBetterThan(css2 CommitStatusState) bool {
|
func (css CommitStatusState) HasHigherPriorityThan(other CommitStatusState) bool {
|
||||||
// NoBetterThan only handles the 5 states above
|
return commitStatusPriorities[css] < commitStatusPriorities[other]
|
||||||
if _, exist := commitStatusPriorities[css]; !exist {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, exist := commitStatusPriorities[css2]; !exist {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return commitStatusPriorities[css] <= commitStatusPriorities[css2]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPending represents if commit status state is pending
|
// IsPending represents if commit status state is pending
|
||||||
|
|
|
@ -10,165 +10,21 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNoBetterThan(t *testing.T) {
|
func TestNoBetterThan(t *testing.T) {
|
||||||
type args struct {
|
|
||||||
css CommitStatusState
|
|
||||||
css2 CommitStatusState
|
|
||||||
}
|
|
||||||
var unExpectedState CommitStatusState
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
s1, s2 CommitStatusState
|
||||||
args args
|
higher bool
|
||||||
want bool
|
|
||||||
}{
|
}{
|
||||||
{
|
{CommitStatusError, CommitStatusFailure, true},
|
||||||
name: "success is no better than success",
|
{CommitStatusFailure, CommitStatusWarning, true},
|
||||||
args: args{
|
{CommitStatusWarning, CommitStatusPending, true},
|
||||||
css: CommitStatusSuccess,
|
{CommitStatusPending, CommitStatusSuccess, true},
|
||||||
css2: CommitStatusSuccess,
|
{CommitStatusSuccess, CommitStatusSkipped, true},
|
||||||
},
|
|
||||||
want: true,
|
{CommitStatusError, "unknown-xxx", false},
|
||||||
},
|
{"unknown-xxx", CommitStatusFailure, true},
|
||||||
{
|
|
||||||
name: "success is no better than pending",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusSuccess,
|
|
||||||
css2: CommitStatusPending,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "success is no better than failure",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusSuccess,
|
|
||||||
css2: CommitStatusFailure,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "success is no better than error",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusSuccess,
|
|
||||||
css2: CommitStatusError,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "pending is no better than success",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusPending,
|
|
||||||
css2: CommitStatusSuccess,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "pending is no better than pending",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusPending,
|
|
||||||
css2: CommitStatusPending,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "pending is no better than failure",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusPending,
|
|
||||||
css2: CommitStatusFailure,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "pending is no better than error",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusPending,
|
|
||||||
css2: CommitStatusError,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "failure is no better than success",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusFailure,
|
|
||||||
css2: CommitStatusSuccess,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "failure is no better than pending",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusFailure,
|
|
||||||
css2: CommitStatusPending,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "failure is no better than failure",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusFailure,
|
|
||||||
css2: CommitStatusFailure,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "failure is no better than error",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusFailure,
|
|
||||||
css2: CommitStatusError,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "error is no better than success",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusError,
|
|
||||||
css2: CommitStatusSuccess,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "error is no better than pending",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusError,
|
|
||||||
css2: CommitStatusPending,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "error is no better than failure",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusError,
|
|
||||||
css2: CommitStatusFailure,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "error is no better than error",
|
|
||||||
args: args{
|
|
||||||
css: CommitStatusError,
|
|
||||||
css2: CommitStatusError,
|
|
||||||
},
|
|
||||||
want: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "unExpectedState is no better than success",
|
|
||||||
args: args{
|
|
||||||
css: unExpectedState,
|
|
||||||
css2: CommitStatusSuccess,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "unExpectedState is no better than unExpectedState",
|
|
||||||
args: args{
|
|
||||||
css: unExpectedState,
|
|
||||||
css2: unExpectedState,
|
|
||||||
},
|
|
||||||
want: false,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
assert.Equal(t, tt.higher, tt.s1.HasHigherPriorityThan(tt.s2), "s1=%s, s2=%s, expected=%v", tt.s1, tt.s2, tt.higher)
|
||||||
result := tt.args.css.NoBetterThan(tt.args.css2)
|
|
||||||
assert.Equal(t, tt.want, result)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
assert.False(t, CommitStatusError.HasHigherPriorityThan(CommitStatusError))
|
||||||
}
|
}
|
||||||
|
|
|
@ -149,12 +149,14 @@ func createCommitStatus(ctx context.Context, job *actions_model.ActionRunJob) er
|
||||||
|
|
||||||
func toCommitStatus(status actions_model.Status) api.CommitStatusState {
|
func toCommitStatus(status actions_model.Status) api.CommitStatusState {
|
||||||
switch status {
|
switch status {
|
||||||
case actions_model.StatusSuccess, actions_model.StatusSkipped:
|
case actions_model.StatusSuccess:
|
||||||
return api.CommitStatusSuccess
|
return api.CommitStatusSuccess
|
||||||
case actions_model.StatusFailure, actions_model.StatusCancelled:
|
case actions_model.StatusFailure, actions_model.StatusCancelled:
|
||||||
return api.CommitStatusFailure
|
return api.CommitStatusFailure
|
||||||
case actions_model.StatusWaiting, actions_model.StatusBlocked, actions_model.StatusRunning:
|
case actions_model.StatusWaiting, actions_model.StatusBlocked, actions_model.StatusRunning:
|
||||||
return api.CommitStatusPending
|
return api.CommitStatusPending
|
||||||
|
case actions_model.StatusSkipped:
|
||||||
|
return api.CommitStatusSkipped
|
||||||
default:
|
default:
|
||||||
return api.CommitStatusError
|
return api.CommitStatusError
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,13 +42,14 @@ func ToCombinedStatus(ctx context.Context, statuses []*git_model.CommitStatus, r
|
||||||
SHA: statuses[0].SHA,
|
SHA: statuses[0].SHA,
|
||||||
TotalCount: len(statuses),
|
TotalCount: len(statuses),
|
||||||
Repository: repo,
|
Repository: repo,
|
||||||
URL: "",
|
URL: "", // never set or used?
|
||||||
|
State: api.CommitStatusSuccess,
|
||||||
}
|
}
|
||||||
|
|
||||||
retStatus.Statuses = make([]*api.CommitStatus, 0, len(statuses))
|
retStatus.Statuses = make([]*api.CommitStatus, 0, len(statuses))
|
||||||
for _, status := range statuses {
|
for _, status := range statuses {
|
||||||
retStatus.Statuses = append(retStatus.Statuses, ToCommitStatus(ctx, status))
|
retStatus.Statuses = append(retStatus.Statuses, ToCommitStatus(ctx, status))
|
||||||
if retStatus.State == "" || status.State.NoBetterThan(retStatus.State) {
|
if status.State.HasHigherPriorityThan(retStatus.State) {
|
||||||
retStatus.State = status.State
|
retStatus.State = status.State
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,9 +58,13 @@ func ToCombinedStatus(ctx context.Context, statuses []*git_model.CommitStatus, r
|
||||||
// > failure if any of the contexts report as error or failure
|
// > failure if any of the contexts report as error or failure
|
||||||
// > pending if there are no statuses or a context is pending
|
// > pending if there are no statuses or a context is pending
|
||||||
// > success if the latest status for all contexts is success
|
// > success if the latest status for all contexts is success
|
||||||
if retStatus.State.IsError() {
|
switch retStatus.State {
|
||||||
retStatus.State = api.CommitStatusFailure
|
case api.CommitStatusSkipped:
|
||||||
|
retStatus.State = api.CommitStatusSuccess // all skipped means success
|
||||||
|
case api.CommitStatusPending, api.CommitStatusSuccess:
|
||||||
|
// use the current state for pending or success
|
||||||
|
default:
|
||||||
|
retStatus.State = api.CommitStatusFailure // otherwise, it is a failure
|
||||||
}
|
}
|
||||||
|
|
||||||
return retStatus
|
return retStatus
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,59 +46,33 @@ func MergeRequiredContextsCommitStatus(commitStatuses []*git_model.CommitStatus,
|
||||||
|
|
||||||
// If required rule not match any action, then it is pending
|
// If required rule not match any action, then it is pending
|
||||||
if targetStatus == "" {
|
if targetStatus == "" {
|
||||||
if structs.CommitStatusPending.NoBetterThan(returnedStatus) {
|
if structs.CommitStatusPending.HasHigherPriorityThan(returnedStatus) {
|
||||||
returnedStatus = structs.CommitStatusPending
|
returnedStatus = structs.CommitStatusPending
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
if targetStatus.NoBetterThan(returnedStatus) {
|
if targetStatus.HasHigherPriorityThan(returnedStatus) {
|
||||||
returnedStatus = targetStatus
|
returnedStatus = targetStatus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if matchedCount == 0 && returnedStatus == structs.CommitStatusSuccess {
|
if matchedCount == 0 && returnedStatus == structs.CommitStatusSuccess {
|
||||||
status := git_model.CalcCommitStatus(commitStatuses)
|
if len(commitStatuses) == 0 {
|
||||||
if status != nil {
|
// "no statuses" should mean "pending"
|
||||||
return status.State
|
return structs.CommitStatusPending
|
||||||
}
|
}
|
||||||
return structs.CommitStatusSuccess
|
status := git_model.CalcCommitStatus(commitStatuses)
|
||||||
|
if status.State == structs.CommitStatusSkipped {
|
||||||
|
return structs.CommitStatusSuccess // if all statuses are skipped, return success
|
||||||
|
}
|
||||||
|
return status.State
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnedStatus
|
return returnedStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ctx := range requiredContexts {
|
|
||||||
var found bool
|
|
||||||
for _, commitStatus := range commitStatuses {
|
|
||||||
if commitStatus.Context == ctx {
|
|
||||||
if commitStatus.State != structs.CommitStatusSuccess {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsPullCommitStatusPass returns if all required status checks PASS
|
// IsPullCommitStatusPass returns if all required status checks PASS
|
||||||
func IsPullCommitStatusPass(ctx context.Context, pr *issues_model.PullRequest) (bool, error) {
|
func IsPullCommitStatusPass(ctx context.Context, pr *issues_model.PullRequest) (bool, error) {
|
||||||
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
pb, err := git_model.GetFirstMatchProtectedBranchRule(ctx, pr.BaseRepoID, pr.BaseBranch)
|
||||||
|
|
|
@ -14,52 +14,70 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMergeRequiredContextsCommitStatus(t *testing.T) {
|
func TestMergeRequiredContextsCommitStatus(t *testing.T) {
|
||||||
testCases := [][]*git_model.CommitStatus{
|
cases := []struct {
|
||||||
|
commitStatuses []*git_model.CommitStatus
|
||||||
|
requiredContexts []string
|
||||||
|
expected structs.CommitStatusState
|
||||||
|
}{
|
||||||
{
|
{
|
||||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
commitStatuses: []*git_model.CommitStatus{},
|
||||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
requiredContexts: []string{},
|
||||||
{Context: "Build 3", State: structs.CommitStatusSuccess},
|
expected: structs.CommitStatusPending,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
commitStatuses: []*git_model.CommitStatus{
|
||||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
{Context: "Build xxx", State: structs.CommitStatusSkipped},
|
||||||
{Context: "Build 2t", State: structs.CommitStatusPending},
|
},
|
||||||
|
requiredContexts: []string{"Build*"},
|
||||||
|
expected: structs.CommitStatusSuccess,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
commitStatuses: []*git_model.CommitStatus{
|
||||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
{Context: "Build 1", State: structs.CommitStatusSkipped},
|
||||||
{Context: "Build 2t", State: structs.CommitStatusFailure},
|
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||||
|
{Context: "Build 3", State: structs.CommitStatusSuccess},
|
||||||
|
},
|
||||||
|
requiredContexts: []string{"Build*"},
|
||||||
|
expected: structs.CommitStatusSuccess,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
commitStatuses: []*git_model.CommitStatus{
|
||||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||||
{Context: "Build 2t", State: structs.CommitStatusSuccess},
|
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||||
|
{Context: "Build 2t", State: structs.CommitStatusPending},
|
||||||
|
},
|
||||||
|
requiredContexts: []string{"Build*", "Build 2t*"},
|
||||||
|
expected: structs.CommitStatusPending,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
commitStatuses: []*git_model.CommitStatus{
|
||||||
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||||
{Context: "Build 2t", State: structs.CommitStatusSuccess},
|
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||||
|
{Context: "Build 2t", State: structs.CommitStatusFailure},
|
||||||
|
},
|
||||||
|
requiredContexts: []string{"Build*", "Build 2t*"},
|
||||||
|
expected: structs.CommitStatusFailure,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commitStatuses: []*git_model.CommitStatus{
|
||||||
|
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||||
|
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||||
|
{Context: "Build 2t", State: structs.CommitStatusSuccess},
|
||||||
|
},
|
||||||
|
requiredContexts: []string{"Build*", "Build 2t*", "Build 3*"},
|
||||||
|
expected: structs.CommitStatusPending,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
commitStatuses: []*git_model.CommitStatus{
|
||||||
|
{Context: "Build 1", State: structs.CommitStatusSuccess},
|
||||||
|
{Context: "Build 2", State: structs.CommitStatusSuccess},
|
||||||
|
{Context: "Build 2t", State: structs.CommitStatusSuccess},
|
||||||
|
},
|
||||||
|
requiredContexts: []string{"Build*", "Build *", "Build 2t*", "Build 1*"},
|
||||||
|
expected: structs.CommitStatusSuccess,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
testCasesRequiredContexts := [][]string{
|
for i, c := range cases {
|
||||||
{"Build*"},
|
assert.Equal(t, c.expected, MergeRequiredContextsCommitStatus(c.commitStatuses, c.requiredContexts), "case %d", i)
|
||||||
{"Build*", "Build 2t*"},
|
|
||||||
{"Build*", "Build 2t*"},
|
|
||||||
{"Build*", "Build 2t*", "Build 3*"},
|
|
||||||
{"Build*", "Build *", "Build 2t*", "Build 1*"},
|
|
||||||
}
|
|
||||||
|
|
||||||
testCasesExpected := []structs.CommitStatusState{
|
|
||||||
structs.CommitStatusSuccess,
|
|
||||||
structs.CommitStatusPending,
|
|
||||||
structs.CommitStatusFailure,
|
|
||||||
structs.CommitStatusPending,
|
|
||||||
structs.CommitStatusSuccess,
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, commitStatuses := range testCases {
|
|
||||||
if MergeRequiredContextsCommitStatus(commitStatuses, testCasesRequiredContexts[i]) != testCasesExpected[i] {
|
|
||||||
assert.Fail(t, "Test case failed", "Test case %d failed", i+1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,3 +14,6 @@
|
||||||
{{if eq .State "warning"}}
|
{{if eq .State "warning"}}
|
||||||
{{svg "gitea-exclamation" 18 "commit-status icon text yellow"}}
|
{{svg "gitea-exclamation" 18 "commit-status icon text yellow"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if eq .State "skipped"}}
|
||||||
|
{{svg "octicon-skip" 18 "commit-status icon text grey"}}
|
||||||
|
{{end}}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {fomanticQuery} from '../modules/fomantic/base.ts';
|
||||||
|
|
||||||
const {appSubUrl, assetUrlPrefix, pageData} = window.config;
|
const {appSubUrl, assetUrlPrefix, pageData} = window.config;
|
||||||
|
|
||||||
type CommitStatus = 'pending' | 'success' | 'error' | 'failure' | 'warning';
|
type CommitStatus = 'pending' | 'success' | 'error' | 'failure' | 'warning' | 'skipped';
|
||||||
|
|
||||||
type CommitStatusMap = {
|
type CommitStatusMap = {
|
||||||
[status in CommitStatus]: {
|
[status in CommitStatus]: {
|
||||||
|
@ -22,6 +22,7 @@ const commitStatus: CommitStatusMap = {
|
||||||
error: {name: 'gitea-exclamation', color: 'red'},
|
error: {name: 'gitea-exclamation', color: 'red'},
|
||||||
failure: {name: 'octicon-x', color: 'red'},
|
failure: {name: 'octicon-x', color: 'red'},
|
||||||
warning: {name: 'gitea-exclamation', color: 'yellow'},
|
warning: {name: 'gitea-exclamation', color: 'yellow'},
|
||||||
|
skipped: {name: 'octicon-skip', color: 'grey'},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
|
|
Loading…
Reference in New Issue