feat: [CODE-2515] handle failure ignored status (#3677)

* fix: [CODE-2515] lint checks
* fix: [CODE-2515] lint checks
* feat: [CODE-2525] handle failure ignored status
This commit is contained in:
Ritik Kapoor 2025-04-21 21:01:53 +00:00 committed by Harness
parent af75e56eb6
commit 6662ddb5b3
13 changed files with 82 additions and 10 deletions

View File

@ -124,6 +124,15 @@
}
}
&.ignoreFailed {
svg {
path[fill='#fff'],
circle[fill='#fff'] {
fill: var(--grey-1000) !important;
}
}
}
&.error {
--fgColor: var(--red-900);
--bgColor: var(--red-50);

View File

@ -20,6 +20,7 @@ export declare const error: string
export declare const executionWaiting: string
export declare const failure: string
export declare const iconOnly: string
export declare const ignoreFailed: string
export declare const main: string
export declare const noBackground: string
export declare const pending: string

View File

@ -28,7 +28,9 @@ export enum ExecutionState {
FAILURE = 'failure',
ERROR = 'error',
SKIPPED = 'skipped',
KILLED = 'killed'
KILLED = 'killed',
FAILURE_IGNORED = 'failure_ignored',
IGNORE_FAILED = 'ignorefailed'
}
interface ExecutionStatusProps {
@ -101,6 +103,16 @@ export const ExecutionStatus: React.FC<ExecutionStatusProps> = ({
css: null,
title: getString('killed').toLocaleUpperCase()
},
[ExecutionState.FAILURE_IGNORED]: {
icon: 'ignoreFailed',
css: null,
title: getString('failureIgnored').toLocaleUpperCase()
},
[ExecutionState.IGNORE_FAILED]: {
icon: 'ignoreFailed',
css: css.ignoreFailed,
title: getString('failureIgnored').toLocaleUpperCase()
},
[ExecutionStateExtended.ABORTED]: {
icon: 'execution-stopped',
css: null,

View File

@ -451,6 +451,7 @@ export interface StringsMap {
failedToFetchFileContent: string
failedToImportSpace: string
failedToSavePipeline: string
failureIgnored: string
fastForwardMerge: string
featureRoadmap: string
fileDeleted: string
@ -899,6 +900,7 @@ export interface StringsMap {
'pr.useCmdLineToResolveConflicts': string
'prChecks.error': string
'prChecks.failure': string
'prChecks.failureIgnored': string
'prChecks.killed': string
'prChecks.notFound': string
'prChecks.pending': string

View File

@ -50,6 +50,7 @@ export function usePRChecksDecision({
case ExecutionState.FAILURE:
case ExecutionState.RUNNING:
case ExecutionState.PENDING:
case ExecutionState.FAILURE_IGNORED:
case ExecutionState.SUCCESS:
_count[check.status]++
setCount({ ..._count })
@ -90,6 +91,13 @@ export function usePRChecksDecision({
setColor(Color.GREY_600)
setBackground(Color.GREY_100)
setMessage(stringSubstitute(getString('prChecks.skipped'), { count: _count.skipped, total }) as string)
} else if (_count.failure_ignored) {
_status = ExecutionState.FAILURE_IGNORED
setColor(Color.GREEN_800)
setBackground(Color.GREEN_50)
setMessage(
stringSubstitute(getString('prChecks.failureIgnored'), { count: _count.failure_ignored, total }) as string
)
} else if (_count.success) {
_status = ExecutionState.SUCCESS
setColor(Color.GREEN_800)
@ -147,5 +155,6 @@ const DEFAULT_COUNTS = {
running: 0,
success: 0,
skipped: 0,
killed: 0
killed: 0,
failure_ignored: 0
}

View File

@ -97,6 +97,13 @@ export function usePRChecksDecision({
setColor(Color.GREY_600)
setBackground(Color.GREY_100)
setMessage(stringSubstitute(getString('prChecks.skipped'), { count: _count.skipped, total }) as string)
} else if (_count.failure_ignored) {
_status = ExecutionState.FAILURE_IGNORED
setColor(Color.GREEN_800)
setBackground(Color.GREEN_50)
setMessage(
stringSubstitute(getString('prChecks.failureIgnored'), { count: _count.failure_ignored, total }) as string
)
} else if (_count.success) {
_status = ExecutionState.SUCCESS
setColor(Color.GREEN_800)
@ -154,5 +161,6 @@ const DEFAULT_COUNTS = {
running: 0,
success: 0,
skipped: 0,
killed: 0
killed: 0,
failure_ignored: 0
}

View File

@ -386,6 +386,7 @@ prChecks:
skipped: '{count}/{total} {count|1:check,checks} skipped.'
success: '{count}/{total} {count|1:check,checks} succeeded.'
killed: '{count}/{total} {count|1:check,checks} killed.'
failureIgnored: '{count}/{total} {count|1:check,checks} failure ignored.'
notFound: No pipelines or external checks found for this repository.
viewExternal: View Details
prReview:
@ -760,6 +761,7 @@ failed: Failed
error: Error
skipped: Skipped
killed: Killed
failureIgnored: Success (Failure Ignored)
repoDelete:
title: Delete Repository
deleteConfirm1: This will permanently delete the "{{repo}}" repository.

View File

@ -70,6 +70,7 @@ const ChecksSection = (props: ChecksSectionProps) => {
failedReq: 0,
pendingReq: 0,
runningReq: 0,
failureIgnoredReq: 0,
successReq: 0,
failed: 0,
pending: 0,
@ -103,6 +104,12 @@ const ChecksSection = (props: ChecksSectionProps) => {
} else {
statusCounts.running += 1
}
} else if (status === CheckStatus.FAILURE_IGNORED) {
if (required) {
statusCounts.failureIgnoredReq += 1
} else {
statusCounts.failureIgnoredReq += 1
}
} else if (status === CheckStatus.SUCCESS) {
if (required) {
statusCounts.successReq += 1
@ -170,7 +177,13 @@ const ChecksSection = (props: ChecksSectionProps) => {
content = `${message}`
color = Color.PRIMARY_6
} else if (checks.every(check => check.check.status === CheckStatus.SUCCESS)) {
} else if (
checks.every(
check =>
check?.check?.status !== undefined &&
[CheckStatus.SUCCESS, CheckStatus.FAILURE_IGNORED].includes(check.check.status as CheckStatus)
)
) {
title = getString('checkSection.allChecksSucceeded')
content = `${message}`
color = Color.GREY_600
@ -195,7 +208,13 @@ const ChecksSection = (props: ChecksSectionProps) => {
title = getString('checkSection.someChecksRunning')
content = `${message}`
color = Color.PRIMARY_6
} else if (checks.every(check => check.check.status === CheckStatus.SUCCESS)) {
} else if (
checks.every(
check =>
check?.check?.status !== undefined &&
[CheckStatus.SUCCESS, CheckStatus.FAILURE_IGNORED].includes(check.check.status as CheckStatus)
)
) {
title = getString('checkSection.allChecksSucceeded')
content = `${message}`
color = Color.GREY_600
@ -298,7 +317,7 @@ const ChecksSection = (props: ChecksSectionProps) => {
font={{ variation: FontVariation.BODY }}>
<StringSubstitute
str={getString(
check.check.status === CheckStatus.SUCCESS
check.check.status === CheckStatus.SUCCESS || check.check.status === CheckStatus.FAILURE_IGNORED
? 'checkStatus.succeeded'
: check.check.status === CheckStatus.FAILURE
? 'checkStatus.failed'

View File

@ -20,6 +20,7 @@ import { ExecutionState, ExecutionStatus } from 'components/ExecutionStatus/Exec
import Fail from '../../../../../icons/code-fail.svg?url'
import Timeout from '../../../../../icons/code-timeout.svg?url'
import Success from '../../../../../icons/code-success.svg?url'
import IgnoreFailed from '../../../../../icons/ignoreFailed.svg?url'
import css from '../PullRequestOverviewPanel.module.scss'
// Define the StatusCircle component
@ -37,6 +38,7 @@ const StatusCircle = ({
pending: number
running: number
succeeded: number
failureIgnoredReq: number
total: number
}
}
@ -58,6 +60,8 @@ const StatusCircle = ({
? ExecutionState.PENDING
: data.running > 0
? ExecutionState.RUNNING
: data.failureIgnoredReq > 0
? ExecutionState.FAILURE_IGNORED
: data.succeeded > 0
? ExecutionState.SUCCESS
: ExecutionState.SKIPPED
@ -66,6 +70,8 @@ const StatusCircle = ({
<>
{status === ExecutionState.SUCCESS ? (
<img alt={getString('success')} width={27} height={27} src={Success} />
) : (status as ExecutionState) === ExecutionState.FAILURE_IGNORED ? (
<img alt={'ignore failed'} width={26} height={26} src={IgnoreFailed} />
) : (status as ExecutionState) === ExecutionState.FAILURE ? (
<img alt={getString('failed')} width={26} height={26} src={Fail} />
) : (status as ExecutionState) === ExecutionState.PENDING ? (

View File

@ -28,7 +28,7 @@ import { CodeIcon } from 'utils/GitUtils'
import type { TypesPullReq, RepoRepositoryOutput } from 'services/code'
import { LoadingSpinner } from 'components/LoadingSpinner/LoadingSpinner'
import { TabTitleWithCount, tabContainerCSS } from 'components/TabTitleWithCount/TabTitleWithCount'
import { ExecutionStatus } from 'components/ExecutionStatus/ExecutionStatus'
import { ExecutionStatus, ExecutionState } from 'components/ExecutionStatus/ExecutionStatus'
import { useSetPageContainerWidthVar } from 'hooks/useSetPageContainerWidthVar'
import { useScrollTop } from 'hooks/useScrollTop'
import { PullRequestMetaLine } from './PullRequestMetaLine'
@ -252,7 +252,9 @@ export default function PullRequest() {
padding={{ left: 'xsmall' }}
tag="span"
font={{ variation: FontVariation.FORM_MESSAGE_WARNING }}>
{pullReqChecksDecision?.count[pullReqChecksDecision?.overallStatus]}
{pullReqChecksDecision?.overallStatus === ExecutionState.IGNORE_FAILED
? pullReqChecksDecision?.count?.failure_ignored || 0
: pullReqChecksDecision?.count?.[pullReqChecksDecision?.overallStatus] || 0}
</Text>
</Layout.Horizontal>
</Container>

View File

@ -24,7 +24,7 @@ export type EnumCIStatus =
export type EnumCheckPayloadKind = '' | 'markdown' | 'pipeline' | 'raw'
export type EnumCheckStatus = 'error' | 'failure' | 'pending' | 'running' | 'success'
export type EnumCheckStatus = 'error' | 'failure' | 'failure_ignored' | 'pending' | 'running' | 'success'
export type EnumConnectorAuthType = 'basic' | 'bearer'

View File

@ -12424,6 +12424,7 @@ components:
enum:
- error
- failure
- failure_ignored
- pending
- running
- success

View File

@ -478,7 +478,8 @@ export enum CheckStatus {
FAILURE = 'failure',
ERROR = 'error',
SKIPPED = 'skipped',
KILLED = 'killed'
KILLED = 'killed',
FAILURE_IGNORED = 'failure_ignored'
}
export enum PRCommentFilterType {