mirror of
https://github.com/go-gitea/gitea.git
synced 2025-07-21 16:45:03 +02:00
Merge 4350e0d51ee2b325044a454dd8b5a2cd6cfe3408 into 6599efb3b1400ac06d06e1c8b68ae6037fbb7952
This commit is contained in:
commit
05a31f9fa4
@ -186,6 +186,9 @@ func AggregateJobStatus(jobs []*ActionRunJob) Status {
|
|||||||
case hasCancelled:
|
case hasCancelled:
|
||||||
return StatusCancelled
|
return StatusCancelled
|
||||||
case hasRunning:
|
case hasRunning:
|
||||||
|
if hasFailure {
|
||||||
|
return StatusRunningWithFailure
|
||||||
|
}
|
||||||
return StatusRunning
|
return StatusRunning
|
||||||
case hasFailure:
|
case hasFailure:
|
||||||
return StatusFailure
|
return StatusFailure
|
||||||
|
@ -65,7 +65,7 @@ func TestAggregateJobStatus(t *testing.T) {
|
|||||||
{[]Status{StatusFailure, StatusSkipped}, StatusFailure},
|
{[]Status{StatusFailure, StatusSkipped}, StatusFailure},
|
||||||
{[]Status{StatusFailure, StatusCancelled}, StatusCancelled},
|
{[]Status{StatusFailure, StatusCancelled}, StatusCancelled},
|
||||||
{[]Status{StatusFailure, StatusWaiting}, StatusFailure},
|
{[]Status{StatusFailure, StatusWaiting}, StatusFailure},
|
||||||
{[]Status{StatusFailure, StatusRunning}, StatusRunning},
|
{[]Status{StatusFailure, StatusRunning}, StatusRunningWithFailure},
|
||||||
{[]Status{StatusFailure, StatusBlocked}, StatusFailure},
|
{[]Status{StatusFailure, StatusBlocked}, StatusFailure},
|
||||||
|
|
||||||
// skipped with other status
|
// skipped with other status
|
||||||
|
@ -15,25 +15,27 @@ import (
|
|||||||
type Status int
|
type Status int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
StatusUnknown Status = iota // 0, consistent with runnerv1.Result_RESULT_UNSPECIFIED
|
StatusUnknown Status = iota // 0, consistent with runnerv1.Result_RESULT_UNSPECIFIED
|
||||||
StatusSuccess // 1, consistent with runnerv1.Result_RESULT_SUCCESS
|
StatusSuccess // 1, consistent with runnerv1.Result_RESULT_SUCCESS
|
||||||
StatusFailure // 2, consistent with runnerv1.Result_RESULT_FAILURE
|
StatusFailure // 2, consistent with runnerv1.Result_RESULT_FAILURE
|
||||||
StatusCancelled // 3, consistent with runnerv1.Result_RESULT_CANCELLED
|
StatusCancelled // 3, consistent with runnerv1.Result_RESULT_CANCELLED
|
||||||
StatusSkipped // 4, consistent with runnerv1.Result_RESULT_SKIPPED
|
StatusSkipped // 4, consistent with runnerv1.Result_RESULT_SKIPPED
|
||||||
StatusWaiting // 5, isn't a runnerv1.Result
|
StatusWaiting // 5, isn't a runnerv1.Result
|
||||||
StatusRunning // 6, isn't a runnerv1.Result
|
StatusRunning // 6, isn't a runnerv1.Result
|
||||||
StatusBlocked // 7, isn't a runnerv1.Result
|
StatusBlocked // 7, isn't a runnerv1.Result
|
||||||
|
StatusRunningWithFailure // 8, isn't a runnerv1.Result, used for aggregated status
|
||||||
)
|
)
|
||||||
|
|
||||||
var statusNames = map[Status]string{
|
var statusNames = map[Status]string{
|
||||||
StatusUnknown: "unknown",
|
StatusUnknown: "unknown",
|
||||||
StatusWaiting: "waiting",
|
StatusWaiting: "waiting",
|
||||||
StatusRunning: "running",
|
StatusRunning: "running",
|
||||||
StatusSuccess: "success",
|
StatusSuccess: "success",
|
||||||
StatusFailure: "failure",
|
StatusFailure: "failure",
|
||||||
StatusCancelled: "cancelled",
|
StatusCancelled: "cancelled",
|
||||||
StatusSkipped: "skipped",
|
StatusSkipped: "skipped",
|
||||||
StatusBlocked: "blocked",
|
StatusBlocked: "blocked",
|
||||||
|
StatusRunningWithFailure: "running_with_failure",
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the string name of the Status
|
// String returns the string name of the Status
|
||||||
@ -88,6 +90,10 @@ func (s Status) IsBlocked() bool {
|
|||||||
return s == StatusBlocked
|
return s == StatusBlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Status) IsRunningWithFailure() bool {
|
||||||
|
return s == StatusRunningWithFailure
|
||||||
|
}
|
||||||
|
|
||||||
// In returns whether s is one of the given statuses
|
// In returns whether s is one of the given statuses
|
||||||
func (s Status) In(statuses ...Status) bool {
|
func (s Status) In(statuses ...Status) bool {
|
||||||
return slices.Contains(statuses, s)
|
return slices.Contains(statuses, s)
|
||||||
|
@ -20,6 +20,8 @@ const (
|
|||||||
CommitStatusWarning CommitStatusState = "warning"
|
CommitStatusWarning CommitStatusState = "warning"
|
||||||
// CommitStatusSkipped is for when CommitStatus is Skipped
|
// CommitStatusSkipped is for when CommitStatus is Skipped
|
||||||
CommitStatusSkipped CommitStatusState = "skipped"
|
CommitStatusSkipped CommitStatusState = "skipped"
|
||||||
|
// CommitStatusRunningWithFailure is for only aggregated commit status
|
||||||
|
CommitStatusRunningWithFailure CommitStatusState = "running_with_failure"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (css CommitStatusState) String() string {
|
func (css CommitStatusState) String() string {
|
||||||
@ -56,20 +58,28 @@ func (css CommitStatusState) IsSkipped() bool {
|
|||||||
return css == CommitStatusSkipped
|
return css == CommitStatusSkipped
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsRunningWithFailure represents if commit status state is running with failure
|
||||||
|
func (css CommitStatusState) IsRunningWithFailure() bool {
|
||||||
|
return css == CommitStatusRunningWithFailure
|
||||||
|
}
|
||||||
|
|
||||||
type CommitStatusStates []CommitStatusState //nolint:revive // export stutter
|
type CommitStatusStates []CommitStatusState //nolint:revive // export stutter
|
||||||
|
|
||||||
// According to https://docs.github.com/en/rest/commits/statuses?apiVersion=2022-11-28#get-the-combined-status-for-a-specific-reference
|
// 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:
|
// > Additionally, a combined state is returned. The state is one of:
|
||||||
// > failure if any of the contexts report as error or failure
|
// > failure if any of the contexts report as error or failure and no contexts are pending
|
||||||
// > pending if there are no statuses or a context is pending
|
// > pending if there are no statuses or a context is pending with no failure
|
||||||
|
// > running_with_failure if there are contexts that are pending and at least one context is failure
|
||||||
// > success if the latest status for all contexts is success
|
// > success if the latest status for all contexts is success
|
||||||
func (css CommitStatusStates) Combine() CommitStatusState {
|
func (css CommitStatusStates) Combine() CommitStatusState {
|
||||||
successCnt := 0
|
successCnt := 0
|
||||||
|
hasRunning, hasFailure := false, false
|
||||||
for _, state := range css {
|
for _, state := range css {
|
||||||
switch {
|
switch {
|
||||||
case state.IsError() || state.IsFailure():
|
case state.IsError() || state.IsFailure():
|
||||||
return CommitStatusFailure
|
hasFailure = true
|
||||||
case state.IsPending():
|
case state.IsPending():
|
||||||
|
hasRunning = true
|
||||||
case state.IsSuccess() || state.IsWarning() || state.IsSkipped():
|
case state.IsSuccess() || state.IsWarning() || state.IsSkipped():
|
||||||
successCnt++
|
successCnt++
|
||||||
}
|
}
|
||||||
@ -77,5 +87,11 @@ func (css CommitStatusStates) Combine() CommitStatusState {
|
|||||||
if successCnt > 0 && successCnt == len(css) {
|
if successCnt > 0 && successCnt == len(css) {
|
||||||
return CommitStatusSuccess
|
return CommitStatusSuccess
|
||||||
}
|
}
|
||||||
|
if hasFailure {
|
||||||
|
if hasRunning {
|
||||||
|
return CommitStatusRunningWithFailure
|
||||||
|
}
|
||||||
|
return CommitStatusFailure
|
||||||
|
}
|
||||||
return CommitStatusPending
|
return CommitStatusPending
|
||||||
}
|
}
|
||||||
|
@ -3789,6 +3789,7 @@ status.failure = "Failure"
|
|||||||
status.cancelled = "Canceled"
|
status.cancelled = "Canceled"
|
||||||
status.skipped = "Skipped"
|
status.skipped = "Skipped"
|
||||||
status.blocked = "Blocked"
|
status.blocked = "Blocked"
|
||||||
|
status.running_with_failure = "Running with failure"
|
||||||
|
|
||||||
runners = Runners
|
runners = Runners
|
||||||
runners.runner_manage_panel = Runners Management
|
runners.runner_manage_panel = Runners Management
|
||||||
|
10
public/assets/img/svg/gitea-running-with-failure.svg
generated
Normal file
10
public/assets/img/svg/gitea-running-with-failure.svg
generated
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||||
|
<!-- Orange dot -->
|
||||||
|
<circle cx="7" cy="8" r="5" fill="#f1c40f"/>
|
||||||
|
|
||||||
|
<!-- Red X (two crossing rectangles) -->
|
||||||
|
<g transform="translate(6, 5)" fill="#e74c3c">
|
||||||
|
<rect x="0" y="2" width="8" height="2" transform="rotate(45 4 3)"/>
|
||||||
|
<rect x="0" y="2" width="8" height="2" transform="rotate(-45 4 3)"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 404 B |
@ -17,6 +17,8 @@
|
|||||||
{{svg "octicon-blocked" $size (printf "text yellow %s" $className)}}
|
{{svg "octicon-blocked" $size (printf "text yellow %s" $className)}}
|
||||||
{{else if eq .status "running"}}
|
{{else if eq .status "running"}}
|
||||||
{{svg "octicon-meter" $size (printf "text yellow circular-spin %s" $className)}}
|
{{svg "octicon-meter" $size (printf "text yellow circular-spin %s" $className)}}
|
||||||
|
{{else if eq .status "running_with_failure"}}
|
||||||
|
{{svg "gitea-running-with-failure" $size (printf "text yellow circular-spin %s" $className)}}
|
||||||
{{else}}{{/*failure, unknown*/}}
|
{{else}}{{/*failure, unknown*/}}
|
||||||
{{svg "octicon-x-circle-fill" $size (printf "text red %s" $className)}}
|
{{svg "octicon-x-circle-fill" $size (printf "text red %s" $className)}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
data-locale-status-cancelled="{{ctx.Locale.Tr "actions.status.cancelled"}}"
|
data-locale-status-cancelled="{{ctx.Locale.Tr "actions.status.cancelled"}}"
|
||||||
data-locale-status-skipped="{{ctx.Locale.Tr "actions.status.skipped"}}"
|
data-locale-status-skipped="{{ctx.Locale.Tr "actions.status.skipped"}}"
|
||||||
data-locale-status-blocked="{{ctx.Locale.Tr "actions.status.blocked"}}"
|
data-locale-status-blocked="{{ctx.Locale.Tr "actions.status.blocked"}}"
|
||||||
|
data-locale-status-running-with-failure="{{ctx.Locale.Tr "actions.status.running_with_failure"}}"
|
||||||
data-locale-artifacts-title="{{ctx.Locale.Tr "artifacts"}}"
|
data-locale-artifacts-title="{{ctx.Locale.Tr "artifacts"}}"
|
||||||
data-locale-artifact-expired="{{ctx.Locale.Tr "expired"}}"
|
data-locale-artifact-expired="{{ctx.Locale.Tr "expired"}}"
|
||||||
data-locale-confirm-delete-artifact="{{ctx.Locale.Tr "confirm_delete_artifact"}}"
|
data-locale-confirm-delete-artifact="{{ctx.Locale.Tr "confirm_delete_artifact"}}"
|
||||||
|
@ -17,3 +17,6 @@
|
|||||||
{{if eq .State "skipped"}}
|
{{if eq .State "skipped"}}
|
||||||
{{svg "octicon-skip" 18 "commit-status icon text grey"}}
|
{{svg "octicon-skip" 18 "commit-status icon text grey"}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{if eq .State "running_with_failure"}}
|
||||||
|
{{svg "gitea-running-with-failure" 18 "commit-status icon text red"}}
|
||||||
|
{{end}}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<!-- This vue should be kept the same as templates/repo/actions/status.tmpl
|
<!-- This vue should be kept the same as templates/repo/actions/status.tmpl
|
||||||
Please also update the template file above if this vue is modified.
|
Please also update the template file above if this vue is modified.
|
||||||
action status accepted: success, skipped, waiting, blocked, running, failure, cancelled, unknown
|
action status accepted: success, skipped, waiting, blocked, running, running_with_failure, failure, cancelled, unknown
|
||||||
-->
|
-->
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import {SvgIcon} from '../svg.ts';
|
import {SvgIcon} from '../svg.ts';
|
||||||
|
|
||||||
withDefaults(defineProps<{
|
withDefaults(defineProps<{
|
||||||
status: 'success' | 'skipped' | 'waiting' | 'blocked' | 'running' | 'failure' | 'cancelled' | 'unknown',
|
status: 'success' | 'skipped' | 'waiting' | 'blocked' | 'running' | 'running_with_failure' | 'failure' | 'cancelled' | 'unknown',
|
||||||
size?: number,
|
size?: number,
|
||||||
className?: string,
|
className?: string,
|
||||||
localeStatus?: string,
|
localeStatus?: string,
|
||||||
@ -25,6 +25,7 @@ withDefaults(defineProps<{
|
|||||||
<SvgIcon name="octicon-clock" class="text yellow" :size="size" :class="className" v-else-if="status === 'waiting'"/>
|
<SvgIcon name="octicon-clock" class="text yellow" :size="size" :class="className" v-else-if="status === 'waiting'"/>
|
||||||
<SvgIcon name="octicon-blocked" class="text yellow" :size="size" :class="className" v-else-if="status === 'blocked'"/>
|
<SvgIcon name="octicon-blocked" class="text yellow" :size="size" :class="className" v-else-if="status === 'blocked'"/>
|
||||||
<SvgIcon name="octicon-meter" class="text yellow" :size="size" :class="'circular-spin ' + className" v-else-if="status === 'running'"/>
|
<SvgIcon name="octicon-meter" class="text yellow" :size="size" :class="'circular-spin ' + className" v-else-if="status === 'running'"/>
|
||||||
|
<SvgIcon name="gitea-running-with-failure" class="text yellow" :size="size" :class="'circular-spin ' + className" v-else-if="status === 'running_with_failure'"/>
|
||||||
<SvgIcon name="octicon-x-circle-fill" class="text red" :size="size" v-else/><!-- failure, unknown -->
|
<SvgIcon name="octicon-x-circle-fill" class="text red" :size="size" v-else/><!-- failure, unknown -->
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
@ -39,6 +39,7 @@ export function initRepositoryActionView() {
|
|||||||
cancelled: el.getAttribute('data-locale-status-cancelled'),
|
cancelled: el.getAttribute('data-locale-status-cancelled'),
|
||||||
skipped: el.getAttribute('data-locale-status-skipped'),
|
skipped: el.getAttribute('data-locale-status-skipped'),
|
||||||
blocked: el.getAttribute('data-locale-status-blocked'),
|
blocked: el.getAttribute('data-locale-status-blocked'),
|
||||||
|
running_with_failure: el.getAttribute('data-locale-status-running-with-failure'),
|
||||||
},
|
},
|
||||||
logsAlwaysAutoScroll: el.getAttribute('data-locale-logs-always-auto-scroll'),
|
logsAlwaysAutoScroll: el.getAttribute('data-locale-logs-always-auto-scroll'),
|
||||||
logsAlwaysExpandRunning: el.getAttribute('data-locale-logs-always-expand-running'),
|
logsAlwaysExpandRunning: el.getAttribute('data-locale-logs-always-expand-running'),
|
||||||
|
@ -78,12 +78,14 @@ import octiconTrash from '../../public/assets/img/svg/octicon-trash.svg';
|
|||||||
import octiconTriangleDown from '../../public/assets/img/svg/octicon-triangle-down.svg';
|
import octiconTriangleDown from '../../public/assets/img/svg/octicon-triangle-down.svg';
|
||||||
import octiconX from '../../public/assets/img/svg/octicon-x.svg';
|
import octiconX from '../../public/assets/img/svg/octicon-x.svg';
|
||||||
import octiconXCircleFill from '../../public/assets/img/svg/octicon-x-circle-fill.svg';
|
import octiconXCircleFill from '../../public/assets/img/svg/octicon-x-circle-fill.svg';
|
||||||
|
import giteaRunningWithFailure from '../../public/assets/img/svg/gitea-running-with-failure.svg';
|
||||||
|
|
||||||
const svgs = {
|
const svgs = {
|
||||||
'gitea-double-chevron-left': giteaDoubleChevronLeft,
|
'gitea-double-chevron-left': giteaDoubleChevronLeft,
|
||||||
'gitea-double-chevron-right': giteaDoubleChevronRight,
|
'gitea-double-chevron-right': giteaDoubleChevronRight,
|
||||||
'gitea-empty-checkbox': giteaEmptyCheckbox,
|
'gitea-empty-checkbox': giteaEmptyCheckbox,
|
||||||
'gitea-exclamation': giteaExclamation,
|
'gitea-exclamation': giteaExclamation,
|
||||||
|
'gitea-running-with-failure': giteaRunningWithFailure,
|
||||||
'octicon-archive': octiconArchive,
|
'octicon-archive': octiconArchive,
|
||||||
'octicon-arrow-switch': octiconArrowSwitch,
|
'octicon-arrow-switch': octiconArrowSwitch,
|
||||||
'octicon-blocked': octiconBlocked,
|
'octicon-blocked': octiconBlocked,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user