← All projects

Developer tooling

CI failure triage

A JUnit artifact tool that keeps build history, separates retry passes from repeat failures, and exports an offline review report.

CLI, offline report and operating checks completed

Recorded test outcomes across five synthetic CI builds.
Recorded test outcomes across five synthetic CI builds.

Implementation

Ingests JUnit XML under explicit build, job and attempt identities. Artifact bytes and normalized cases commit in one transaction; exact repeats are idempotent and conflicting identities are rejected.

Full attempts replace job membership. Partial retries overlay only supplied tests. A single read transaction produces a consistent report while another process imports results.

Classifies retry passes, new and repeated failures, recoveries, skips and unreported tests. A missing test is never treated as a pass, and a retry pass is not presented as a root-cause diagnosis.

Exports a self-contained HTML report with build selection, search, classification filters, attempt details, original XML downloads and filtered CSV. No application server or network request is required.

Executed regression and operating checks include malformed input, resource limits, script/formula escaping, concurrent imports, abrupt process exit before commit, deterministic export and a 10,000-case workload.

Inputs and assumptions

  • One SQLite database represents one repository and comparison stream. Caller-supplied positive sequence numbers define build order.
  • Test identity is the exact job/file/classname/name tuple. Renaming or moving a test creates a new identity. Framework-specific inline retry extensions must be exported as explicit attempt artifacts.
  • The included five-build history and the larger acceptance workload are synthetic. No customer repository or CI provider data is used.

Results

Recorded results for the included reference case
Reference builds / job attempts5 / 12
Stored reference observations102
Latest known test identities21
Latest final failures or errors3
Retry passes / recovered / skipped / unreported1 / 1 / 1 / 1
Behavioral tests passed30
Operating outcomes checked13
Larger synthetic workload10000 test cases
Report figures (1)
Test-history matrix generated from the executed synthetic JUnit artifacts.
Actual classifications from five synthetic builds. The retained history distinguishes a retried pass, repeated failures, recovery, a skip and an unreported test.

Open the full report ↗

Verification

30 behavioral tests and 13 executed operating checks pass. The reference history has 102 observations across 12 job attempts; the latest build has three final failures/errors, one retry pass, one recovery, one skipped test and one unreported identity.

python run_demo.py
python verify.py
python acceptance.py
Download the verification record ↓

Additional scenarios

13 outcomes checked through executed synthetic operations. The report lists the expected and observed outcomes for each check.

Read the validation report ↗

Project files

The ZIP contains the source, inputs, results, and instructions. These files are also available individually.

Download project ZIP · 127 KB
Archive checksum

SHA-256

034810e1eec8442a975378cd6d7b9a28790f1786b5e211df30335ee7ceae01fd

Run locally

Python 3.10+ / SQLite via the Python standard library

Extract the ZIP and open a terminal in the ci-failure-triage folder. The README includes setup and usage details.

python run_demo.py
# Open report.html in a browser.
python verify.py
python acceptance.py
python triage.py --help

Limits

  • The supplied artifacts are synthetic. The tool works with local files; it has no provider API connector, automatic artifact collection or branch/commit comparison.
  • Classifications describe observed outcomes, not defect causes. A renamed test is a new identity; missing and skipped tests remain explicit. The check command gates final failures/errors only, not coverage completeness.
  • XML support is a declared JUnit-style subset with bounded UTF-8 inputs. DTD/entities and ambiguous outcomes are rejected. This is not universal support for every framework extension.
  • An abrupt subprocess exit exercises transaction recovery, not physical power-loss durability. The 10,000-case timings describe one local runtime rather than guaranteed production capacity.
  • Individual export files are atomically replaced; a whole output directory is not an atomic transaction. The HTML report embeds its own data and original artifact bytes.