Files
windmill/frontend/src/lib/components/JobStatus.svelte
T
Ruben FiszelandClaude Opus 5 4d3ff0299f feat: mark failed jobs as resolved so handled failures stop showing red (#10319)
* feat: mark failed jobs as resolved so handled failures stop showing red

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: constrain auto-resolve to the proven retry chain and honor resolved filter everywhere

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: apply resolved filter to queue-union, concurrency and delete paths, bound note

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: sweep resolutions on workspace delete, verify helper args, enforce UI limits

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: count resolution note in characters on both sides of the API

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: skip the queue lookup for cancel-all under the resolved-only filter

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: converge retry auto-resolution from either commit order, keep notes on re-resolve

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: correct the idempotency claim on the retry auto-resolve sweep

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat: gate resolution notes and attribution behind enterprise, add note popover

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: hide resolution from operators, exclude flow steps, enforce EE licence at runtime

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: add job_resolution.automatic to the summarized schema

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: preserve stored attribution when re-resolving without a valid licence

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* docs: condense the attribution-preservation comment to four lines

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: validate resolution notes by code point instead of a UTF-16 maxlength

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: keep the resolution popover open when a note is rejected

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* feat: offer to resolve the original failure after a successful re-run

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: verify supersession server-side and stop re-runs overwriting notes

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: apply tag scope to the superseding run

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix: exclude obscured cross-workspace runs from resolution actions

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-26 09:36:27 +02:00

94 lines
3.0 KiB
Svelte

<script lang="ts">
import { displayDate, msToReadableTime } from '$lib/utils'
import type { CompletedJob, QueuedJob } from '$lib/gen'
import Badge from './common/badge/Badge.svelte'
import { forLater } from '$lib/forLater'
import { Circle } from 'lucide-svelte'
import NoWorkerWithTagWarning from './runs/NoWorkerWithTagWarning.svelte'
import QueuePosition from './QueuePosition.svelte'
import WaitTimeWarning from './common/waitTimeWarning/WaitTimeWarning.svelte'
const SMALL_ICON_SIZE = 12
interface Props {
job: QueuedJob | CompletedJob | undefined
large?: boolean
}
let { job, large = false }: Props = $props()
</script>
{#if job && 'success' in job && job.success}
<Badge {large} color="green">
Successfully ran in {msToReadableTime(job.duration_ms)}
{job.is_skipped ? '(Skipped)' : ''}
{#if job.self_wait_time_ms || job.aggregate_wait_time_ms}
<WaitTimeWarning
self_wait_time_ms={job.self_wait_time_ms}
aggregate_wait_time_ms={job.aggregate_wait_time_ms}
variant="alert"
/>
{/if}
</Badge>
{:else if job && 'success' in job && job.resolved}
<Badge {large} color="orange" title={job.resolution_note}>
<!-- `resolved_by` is absent both for an automatic resolution and for a manual one
outside EE, so the automatic wording comes from `resolved_automatically`. -->
Failed after {msToReadableTime(job.duration_ms)}, resolved{job.resolved_automatically
? ' automatically'
: job.resolved_by
? ` by ${job.resolved_by}`
: ''}
{#if job.self_wait_time_ms || job.aggregate_wait_time_ms}
<WaitTimeWarning
self_wait_time_ms={job.self_wait_time_ms}
aggregate_wait_time_ms={job.aggregate_wait_time_ms}
variant="alert"
/>
{/if}
</Badge>
{:else if job && 'success' in job}
<Badge {large} color="red">
Failed after {msToReadableTime(job.duration_ms)}
{#if job.self_wait_time_ms || job.aggregate_wait_time_ms}
<WaitTimeWarning
self_wait_time_ms={job.self_wait_time_ms}
aggregate_wait_time_ms={job.aggregate_wait_time_ms}
variant="alert"
/>
{/if}
</Badge>
{:else if job && 'running' in job && job.running && job.suspend}
<div>
<Badge {large} color="violet">
Suspended
{#if job.flow_status}
({(job.flow_status?.step ?? 0) + 1} of {job.raw_flow?.modules?.length ?? '?'})
{/if}
</Badge>
</div>
{:else if job && 'running' in job && job.running}
<div>
<Badge {large} color="yellow">
Running
{#if job.flow_status}
({(job.flow_status?.step ?? 0) + 1} of {job.raw_flow?.modules?.length ?? '?'})
{/if}
</Badge>
</div>
{:else if job && 'running' in job && 'scheduled_for' in job && job.scheduled_for && forLater(job.scheduled_for)}
<div>
<Badge color="blue" {large}>
Scheduled for {displayDate(job.scheduled_for)}
</Badge>
</div>
{:else if job && 'running' in job}
<div class="flex flex-row gap-1 items-center">
<Badge color="orange" {large}>Queued</Badge>
<NoWorkerWithTagWarning tag={job.tag} />
<QueuePosition jobId={job.id} workspaceId={job.workspace_id} minimal />
</div>
{:else}
<Circle size={SMALL_ICON_SIZE} class="text-gray-200" />
{/if}