aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/commitstatus/commit_status.go (renamed from modules/structs/commit_status.go)50
-rw-r--r--modules/commitstatus/commit_status_test.go201
-rw-r--r--modules/structs/commit_status_test.go30
-rw-r--r--modules/structs/status.go38
4 files changed, 253 insertions, 66 deletions
diff --git a/modules/structs/commit_status.go b/modules/commitstatus/commit_status.go
index 398001974d..12004474ed 100644
--- a/modules/structs/commit_status.go
+++ b/modules/commitstatus/commit_status.go
@@ -1,11 +1,11 @@
// Copyright 2020 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
-package structs
+package commitstatus
// CommitStatusState holds the state of a CommitStatus
-// It can be "pending", "success", "error" and "failure"
-type CommitStatusState string
+// swagger:enum CommitStatusState
+type CommitStatusState string //nolint
const (
// CommitStatusPending is for when the CommitStatus is Pending
@@ -22,25 +22,10 @@ const (
CommitStatusSkipped CommitStatusState = "skipped"
)
-var commitStatusPriorities = map[CommitStatusState]int{
- CommitStatusError: 0,
- CommitStatusFailure: 1,
- CommitStatusWarning: 2,
- CommitStatusPending: 3,
- CommitStatusSuccess: 4,
- CommitStatusSkipped: 5,
-}
-
func (css CommitStatusState) String() string {
return string(css)
}
-// HasHigherPriorityThan returns true if this state has higher priority than the other
-// Undefined states are considered to have the highest priority like CommitStatusError(0)
-func (css CommitStatusState) HasHigherPriorityThan(other CommitStatusState) bool {
- return commitStatusPriorities[css] < commitStatusPriorities[other]
-}
-
// IsPending represents if commit status state is pending
func (css CommitStatusState) IsPending() bool {
return css == CommitStatusPending
@@ -65,3 +50,32 @@ func (css CommitStatusState) IsFailure() bool {
func (css CommitStatusState) IsWarning() bool {
return css == CommitStatusWarning
}
+
+// IsSkipped represents if commit status state is skipped
+func (css CommitStatusState) IsSkipped() bool {
+ return css == CommitStatusSkipped
+}
+
+type CommitStatusStates []CommitStatusState //nolint
+
+// According to https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#get-the-combined-status-for-a-specific-reference
+// > Additionally, a combined state is returned. The state is one of:
+// > failure if any of the contexts report as error or failure
+// > pending if there are no statuses or a context is pending
+// > success if the latest status for all contexts is success
+func (css CommitStatusStates) Combine() CommitStatusState {
+ successCnt := 0
+ for _, state := range css {
+ switch {
+ case state.IsError() || state.IsFailure():
+ return CommitStatusFailure
+ case state.IsPending():
+ case state.IsSuccess() || state.IsWarning() || state.IsSkipped():
+ successCnt++
+ }
+ }
+ if successCnt > 0 && successCnt == len(css) {
+ return CommitStatusSuccess
+ }
+ return CommitStatusPending
+}
diff --git a/modules/commitstatus/commit_status_test.go b/modules/commitstatus/commit_status_test.go
new file mode 100644
index 0000000000..10d8f20aa4
--- /dev/null
+++ b/modules/commitstatus/commit_status_test.go
@@ -0,0 +1,201 @@
+// Copyright 2025 The Gitea Authors. All rights reserved.
+// SPDX-License-Identifier: MIT
+
+package commitstatus
+
+import "testing"
+
+func TestCombine(t *testing.T) {
+ tests := []struct {
+ name string
+ states CommitStatusStates
+ expected CommitStatusState
+ }{
+ // 0 states
+ {
+ name: "empty",
+ states: CommitStatusStates{},
+ expected: CommitStatusPending,
+ },
+ // 1 state
+ {
+ name: "pending",
+ states: CommitStatusStates{CommitStatusPending},
+ expected: CommitStatusPending,
+ },
+ {
+ name: "success",
+ states: CommitStatusStates{CommitStatusSuccess},
+ expected: CommitStatusSuccess,
+ },
+ {
+ name: "error",
+ states: CommitStatusStates{CommitStatusError},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "failure",
+ states: CommitStatusStates{CommitStatusFailure},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "warning",
+ states: CommitStatusStates{CommitStatusWarning},
+ expected: CommitStatusSuccess,
+ },
+ // 2 states
+ {
+ name: "pending and success",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess},
+ expected: CommitStatusPending,
+ },
+ {
+ name: "pending and error",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusError},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "pending and failure",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusFailure},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "pending and warning",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusWarning},
+ expected: CommitStatusPending,
+ },
+ {
+ name: "success and error",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusError},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "success and failure",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusFailure},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "success and warning",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusWarning},
+ expected: CommitStatusSuccess,
+ },
+ {
+ name: "error and failure",
+ states: CommitStatusStates{CommitStatusError, CommitStatusFailure},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "error and warning",
+ states: CommitStatusStates{CommitStatusError, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "failure and warning",
+ states: CommitStatusStates{CommitStatusFailure, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ // 3 states
+ {
+ name: "pending, success and warning",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess, CommitStatusWarning},
+ expected: CommitStatusPending,
+ },
+ {
+ name: "pending, success and error",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess, CommitStatusError},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "pending, success and failure",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess, CommitStatusFailure},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "pending, error and failure",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusError, CommitStatusFailure},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "success, error and warning",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusError, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "success, failure and warning",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusFailure, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "error, failure and warning",
+ states: CommitStatusStates{CommitStatusError, CommitStatusFailure, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "success, warning and skipped",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusWarning, CommitStatusSkipped},
+ expected: CommitStatusSuccess,
+ },
+ // All success
+ {
+ name: "all success",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusSuccess, CommitStatusSuccess},
+ expected: CommitStatusSuccess,
+ },
+ // All pending
+ {
+ name: "all pending",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusPending, CommitStatusPending},
+ expected: CommitStatusPending,
+ },
+ {
+ name: "all skipped",
+ states: CommitStatusStates{CommitStatusSkipped, CommitStatusSkipped, CommitStatusSkipped},
+ expected: CommitStatusSuccess,
+ },
+ // 4 states
+ {
+ name: "pending, success, error and warning",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess, CommitStatusError, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "pending, success, failure and warning",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess, CommitStatusFailure, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "pending, error, failure and warning",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusError, CommitStatusFailure, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "success, error, failure and warning",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusError, CommitStatusFailure, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "mixed states",
+ states: CommitStatusStates{CommitStatusPending, CommitStatusSuccess, CommitStatusError, CommitStatusWarning},
+ expected: CommitStatusFailure,
+ },
+ {
+ name: "mixed states with all success",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusSuccess, CommitStatusPending, CommitStatusWarning},
+ expected: CommitStatusPending,
+ },
+ {
+ name: "all success with warning",
+ states: CommitStatusStates{CommitStatusSuccess, CommitStatusSuccess, CommitStatusSuccess, CommitStatusWarning},
+ expected: CommitStatusSuccess,
+ },
+ }
+
+ for _, tt := range tests {
+ t.Run(tt.name, func(t *testing.T) {
+ result := tt.states.Combine()
+ if result != tt.expected {
+ t.Errorf("expected %v, got %v", tt.expected, result)
+ }
+ })
+ }
+}
diff --git a/modules/structs/commit_status_test.go b/modules/structs/commit_status_test.go
deleted file mode 100644
index c11daf248d..0000000000
--- a/modules/structs/commit_status_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2023 The Gitea Authors. All rights reserved.
-// SPDX-License-Identifier: MIT
-
-package structs
-
-import (
- "testing"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestNoBetterThan(t *testing.T) {
- tests := []struct {
- s1, s2 CommitStatusState
- higher bool
- }{
- {CommitStatusError, CommitStatusFailure, true},
- {CommitStatusFailure, CommitStatusWarning, true},
- {CommitStatusWarning, CommitStatusPending, true},
- {CommitStatusPending, CommitStatusSuccess, true},
- {CommitStatusSuccess, CommitStatusSkipped, true},
-
- {CommitStatusError, "unknown-xxx", false},
- {"unknown-xxx", CommitStatusFailure, true},
- }
- for _, tt := range tests {
- assert.Equal(t, tt.higher, tt.s1.HasHigherPriorityThan(tt.s2), "s1=%s, s2=%s, expected=%v", tt.s1, tt.s2, tt.higher)
- }
- assert.False(t, CommitStatusError.HasHigherPriorityThan(CommitStatusError))
-}
diff --git a/modules/structs/status.go b/modules/structs/status.go
index c1d8b902ec..a9779541ff 100644
--- a/modules/structs/status.go
+++ b/modules/structs/status.go
@@ -5,17 +5,19 @@ package structs
import (
"time"
+
+ "code.gitea.io/gitea/modules/commitstatus"
)
// CommitStatus holds a single status of a single Commit
type CommitStatus struct {
- ID int64 `json:"id"`
- State CommitStatusState `json:"status"`
- TargetURL string `json:"target_url"`
- Description string `json:"description"`
- URL string `json:"url"`
- Context string `json:"context"`
- Creator *User `json:"creator"`
+ ID int64 `json:"id"`
+ State commitstatus.CommitStatusState `json:"status"`
+ TargetURL string `json:"target_url"`
+ Description string `json:"description"`
+ URL string `json:"url"`
+ Context string `json:"context"`
+ Creator *User `json:"creator"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
@@ -24,19 +26,19 @@ type CommitStatus struct {
// CombinedStatus holds the combined state of several statuses for a single commit
type CombinedStatus struct {
- State CommitStatusState `json:"state"`
- SHA string `json:"sha"`
- TotalCount int `json:"total_count"`
- Statuses []*CommitStatus `json:"statuses"`
- Repository *Repository `json:"repository"`
- CommitURL string `json:"commit_url"`
- URL string `json:"url"`
+ State commitstatus.CommitStatusState `json:"state"`
+ SHA string `json:"sha"`
+ TotalCount int `json:"total_count"`
+ Statuses []*CommitStatus `json:"statuses"`
+ Repository *Repository `json:"repository"`
+ CommitURL string `json:"commit_url"`
+ URL string `json:"url"`
}
// CreateStatusOption holds the information needed to create a new CommitStatus for a Commit
type CreateStatusOption struct {
- State CommitStatusState `json:"state"`
- TargetURL string `json:"target_url"`
- Description string `json:"description"`
- Context string `json:"context"`
+ State commitstatus.CommitStatusState `json:"state"`
+ TargetURL string `json:"target_url"`
+ Description string `json:"description"`
+ Context string `json:"context"`
}