Files
orca/config/scripts/ci/e2e-failures/ci-e2e-failure-summary.mjs
T
Neil 9bd6272fdf refactor(tooling): organize build, CI, and test owners (#38130)
* refactor(tooling): organize test runtime and maintenance owners

* test(tooling): preserve relocated runtime fixture dependency edges

* refactor(tooling): preserve xterm routing owner checks

* ci(tooling): include routing owner in sparse checkout

* test(tooling): preserve copied workflow dependency closures

* fix(tooling): normalize hashed JSON assets in release parity

* fix(tooling): distinguish asset aliases from literal references

* fix(tooling): frame normalized asset reference payloads

* fix(tooling): normalize decoded JSON asset references

* refactor(tooling): organize build, CI and release owners

* fix(tooling): align moved generator and workflow path contracts

* fix(tooling): update generated plugin bundle owner banners

* test(tooling): create relocated mobile verifier fixture directories

* test(tooling): copy headless detector dependency closure

* test(tooling): align native batch policy fixtures with owner path

* fix(tooling): link moved reliability command to historical evidence

* fix(tooling): preserve nested sandbox owners and canonical guide source

* fix(tooling): target release version owners in checkout fixture
2026-11-04 21:08:19 -08:00

93 lines
3.3 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { appendFileSync, readFileSync } from 'node:fs'
import { pathToFileURL } from 'node:url'
import { trackE2eFailures } from './ci-e2e-failure-tracking.mjs'
export function e2eFailureSummary(report) {
const failures = []
let passed = 0
let skipped = 0
function visit(suite, parents = [], parentFile) {
const titles = [...parents, suite.title].filter(Boolean)
const file = suite.file ?? parentFile
for (const spec of suite.specs ?? []) {
for (const test of spec.tests ?? []) {
if (test.status === 'expected') {
passed++
continue
}
if (test.status === 'skipped') {
skipped++
continue
}
const errors = test.results.flatMap((result) => result.errors ?? [])
failures.push({
file: spec.file ?? file,
title: [...titles, spec.title].join(' › '),
project: test.projectName,
status: test.status,
message: errors
.map((error) => error.message ?? error.value ?? '')
.join('\n')
.slice(0, 2000)
})
}
}
for (const child of suite.suites ?? []) {
visit(child, titles, file)
}
}
for (const suite of report.suites ?? []) {
visit(suite)
}
return { passed, skipped, failures, errors: report.errors ?? [] }
}
export function renderE2eFailures(summary, records = [], now = new Date()) {
const escape = (value) =>
String(value ?? '')
.replaceAll('&', '&')
.replaceAll('<', '&lt;')
.replaceAll('>', '&gt;')
const tracked = trackE2eFailures(summary.failures, records, now)
const details = (failure) =>
`<details><summary>${escape(failure.status)}: ${escape(failure.file)} — ${escape(failure.title)}</summary><pre>${escape(failure.message)}</pre></details>`
return [
'## E2E results',
'',
`${summary.passed} expected results; ${summary.skipped} skipped; ${summary.failures.length} unexpected/flaky results; ${summary.errors.length} run errors.`,
'',
`### Untracked failures (${tracked.untracked.length})`,
'',
...tracked.untracked.map(details),
'',
`### Tracked failures (${tracked.known.length})`,
'',
...tracked.known.flatMap((failure) => [
details(failure),
`Owner: ${escape(failure.tracking.owner)}; ${escape(failure.tracking.issue)}; expires ${escape(failure.tracking.expires)}.`
]),
...(tracked.invalid.length
? [`${tracked.invalid.length} invalid/expired tracking entries were not used.`]
: []),
...summary.errors.map((error) => `<pre>${escape(error.message ?? error.value)}</pre>`),
'',
'Failures retain their original verdict. Repeated failures need a tracked owner, reproduction and review date; do not treat a red baseline as passing.',
''
].join('\n')
}
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
try {
const summary = e2eFailureSummary(JSON.parse(readFileSync(process.argv[2], 'utf8')))
const records = JSON.parse(
readFileSync(new URL('../../../e2e-failure-tracking.json', import.meta.url), 'utf8')
)
appendFileSync(process.env.GITHUB_STEP_SUMMARY, renderE2eFailures(summary, records))
} catch (error) {
appendFileSync(
process.env.GITHUB_STEP_SUMMARY,
`E2E report unavailable (${error.code ?? 'invalid report'}); inspect the failing step and traces.\n`
)
}
}