Consolidate reports across retry attempts - #10542
Conversation
Relay typed artifacts from retry attempts and consolidate CTRF and JUnit reports without removing per-attempt diagnostics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Consolidates retry-aware CTRF and JUnit reports while preserving every physical attempt under Retries/.
Changes:
- Relays typed artifacts and adds retry-specific post-processing modes.
- Collapses CTRF and JUnit attempts into logical test results.
- Preserves final-attempt semantics for TRX and HTML.
Show a summary per file
| File | Description |
|---|---|
test/UnitTests/Microsoft.Testing.Platform.UnitTests/Extensions/ArtifactPostProcessing/ArtifactPostProcessingTests.cs |
Updates processor stub capabilities. |
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/TrxArtifactPostProcessorTests.cs |
Verifies TRX modes. |
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/JUnitReportMergerTests.cs |
Tests retry collapsing. |
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/JUnitArtifactPostProcessorTests.cs |
Verifies JUnit modes. |
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/HtmlArtifactPostProcessorTests.cs |
Verifies HTML modes. |
test/UnitTests/Microsoft.Testing.Extensions.UnitTests/CtrfArtifactPostProcessorTests.cs |
Tests CTRF retry processing. |
test/IntegrationTests/MSTest.Acceptance.IntegrationTests/JUnitReportTests.cs |
Validates consolidated JUnit output. |
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/RetryFailedTestsTests.cs |
Validates retry artifact layouts and CTRF. |
test/IntegrationTests/Microsoft.Testing.Platform.Acceptance.IntegrationTests/DotnetTestPipe/DotnetTestPipeArtifactPostProcessingTests.cs |
Updates sample processor modes. |
src/Platform/Microsoft.Testing.Platform/PublicAPI/PublicAPI.Unshipped.txt |
Tracks the new public API. |
src/Platform/Microsoft.Testing.Platform/Extensions/ArtifactPostProcessing/IArtifactPostProcessor.cs |
Defines post-processing modes. |
src/Platform/Microsoft.Testing.Platform/Extensions/ArtifactPostProcessing/ArtifactPostProcessingManager.cs |
Validates supported modes. |
src/Platform/Microsoft.Testing.Platform/Extensions/ArtifactPostProcessing/ArtifactPostProcessingHandshakeProperties.cs |
Restricts handshakes to module merging. |
src/Platform/Microsoft.Testing.Platform/Extensions/ArtifactPostProcessing/ArtifactPostProcessingDispatcherTool.cs |
Filters processors by mode. |
src/Platform/Microsoft.Testing.Extensions.TrxReport/TrxArtifactPostProcessor.cs |
Keeps TRX module-only. |
src/Platform/Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Unshipped.txt |
Tracks TRX API changes. |
src/Platform/Microsoft.Testing.Extensions.Retry/Serializers/ArtifactRequest.cs |
Adds artifact IPC serialization. |
src/Platform/Microsoft.Testing.Extensions.Retry/RetrySummaryReporter.cs |
Preserves and publishes final artifacts. |
src/Platform/Microsoft.Testing.Extensions.Retry/RetryOrchestrator.cs |
Coordinates retry report processing. |
src/Platform/Microsoft.Testing.Extensions.Retry/RetryLifecycleCallbacks.cs |
Registers artifact serialization. |
src/Platform/Microsoft.Testing.Extensions.Retry/RetryFailedTestsPipeServer.cs |
Collects child artifacts. |
src/Platform/Microsoft.Testing.Extensions.Retry/RetryDataConsumer.cs |
Relays session artifacts. |
src/Platform/Microsoft.Testing.Extensions.Retry/RetryArtifactProcessor.cs |
Processes ordered attempt artifacts. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hant.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.zh-Hans.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.tr.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ru.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pt-BR.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.pl.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ko.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.ja.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.it.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.fr.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.es.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.de.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/xlf/ExtensionResources.cs.xlf |
Updates localized resources. |
src/Platform/Microsoft.Testing.Extensions.Retry/Resources/ExtensionResources.resx |
Adds publication and failure messages. |
src/Platform/Microsoft.Testing.Extensions.Retry/InternalAPI/InternalAPI.Unshipped.txt |
Tracks retry internals. |
src/Platform/Microsoft.Testing.Extensions.JUnitReport/JUnitReportMerger.cs |
Collapses JUnit retry outcomes. |
src/Platform/Microsoft.Testing.Extensions.JUnitReport/JUnitArtifactPostProcessor.cs |
Enables retry-aware JUnit merging. |
src/Platform/Microsoft.Testing.Extensions.JUnitReport/InternalAPI/InternalAPI.Unshipped.txt |
Tracks JUnit internals. |
src/Platform/Microsoft.Testing.Extensions.HtmlReport/InternalAPI/InternalAPI.Unshipped.txt |
Tracks HTML mode capability. |
src/Platform/Microsoft.Testing.Extensions.HtmlReport/HtmlArtifactPostProcessor.cs |
Keeps HTML module-only. |
src/Platform/Microsoft.Testing.Extensions.CtrfReport/InternalAPI/InternalAPI.Unshipped.txt |
Tracks CTRF internals. |
src/Platform/Microsoft.Testing.Extensions.CtrfReport/CtrfReportMerger.FileMerge.cs |
Adds mode-aware file merging. |
src/Platform/Microsoft.Testing.Extensions.CtrfReport/CtrfArtifactPostProcessor.cs |
Enables retry-aware CTRF collapsing. |
docs/RFCs/018-Artifact-Post-Processing.md |
Documents processing modes. |
docs/RFCs/016-JUnit-Report.md |
Documents consolidated retry behavior. |
Review details
Tip
Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
- Files reviewed: 48/48 changed files
- Comments generated: 2
- Review effort level: Balanced
Use stable JUnit producer identity across narrowed attempts and normalize artifact paths before applying consolidated replacements. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
There was a problem hiding this comment.
Review details
Suppressed comments (2)
src/Platform/Microsoft.Testing.Platform/Extensions/ArtifactPostProcessing/ArtifactPostProcessingManager.cs:40
- The new capability validation has no tests for any of its rejection cases (empty modes, duplicate modes, or an undefined enum value), while the existing kind/extension validation is covered case-by-case in
ArtifactPostProcessingTests. Please add manager tests for these three invalid declarations so this opt-in boundary cannot regress silently.
src/Platform/Microsoft.Testing.Extensions.Retry/RetryArtifactProcessor.cs:63 - This fail-closed guard is central to avoiding a valid-looking but incomplete retry report, but the added tests cover only complete happy paths. Add focused tests for a missing attempt and multiple artifacts from one attempt, asserting that no replacement is published (and ideally that the processor is not invoked).
if (artifactsByAttempt.Length != attemptCount
|| artifactsByAttempt.Any(group => group.Count() != 1))
{
continue;
- Files reviewed: 49/49 changed files
- Comments generated: 0 new
- Review effort level: Balanced
Capture the connected retry pipe client through a non-null helper so static analysis can prove the dereference is safe. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
There was a problem hiding this comment.
Review details
Suppressed comments (1)
src/Platform/Microsoft.Testing.Extensions.JUnitReport/JUnitReportMerger.cs:216
- The retry suite keeps the first attempt's full
<testsuite>template.JUnitXmlWriterputs the child process'sexit-codein that template, so a fail-then-pass run can publishfailures="0"while still carrying the first attempt's failingexit-code="2"(the acceptance expectations confirm 2 for failed runs and 0 for successful runs). Recompute attempt-scoped suite metadata from the logical/final run instead of retaining it from the first attempt; preserve the earliest timestamp separately if needed.
string suiteIdentity = BuildSuiteIdentity(suite);
if (!suiteIndices.TryGetValue(suiteIdentity, out int suiteIndex))
{
suiteIndex = suites.Count;
suiteIndices.Add(suiteIdentity, suiteIndex);
suites.Add(new RetrySuite(new XElement(suite)));
- Files reviewed: 49/49 changed files
- Comments generated: 0 new
- Review effort level: Balanced
This comment has been minimized.
This comment has been minimized.
Propagate suite properties from the final physical attempt so consolidated JUnit counters and exit-code metadata describe the same outcome. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Track same-identity occurrences independently within each physical report so retry consolidation does not discard duplicate results. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Review details
Suppressed comments (2)
test/IntegrationTests/MSTest.Acceptance.IntegrationTests/JUnitReportTests.cs:206
- This has the same ancestor-path ambiguity as the attempt-1 lookup: any workspace component named
2makes unrelated report paths match and causesSingleto fail. Restrict the comparison to the report's parent directory.
test/IntegrationTests/MSTest.Acceptance.IntegrationTests/JUnitReportTests.cs:202 - This matches any
.../1/...component in the full path, not specifically the retry-attempt directory. On agents whose workspace already contains a1component (for example Azure Pipelines'_work/1/...), both report paths match andSinglethrows. Compare the report's immediate parent directory instead.
This issue also appears on line 206 of the same file.
- Files reviewed: 49/49 changed files
- Comments generated: 0 new
- Review effort level: Balanced
This comment has been minimized.
This comment has been minimized.
Select per-attempt JUnit reports by their immediate parent directory so CI workspace path components cannot produce false matches. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Resolve artifact post-processing API conflicts by preserving both retry modes and authoritative run summaries, and update newly added CI summary processors for mode support. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
There was a problem hiding this comment.
Review details
Suppressed comments (1)
src/Platform/Microsoft.Testing.Platform/Extensions/ArtifactPostProcessing/ArtifactPostProcessingHandshakeProperties.cs:29
- The new
TestModulesfilter is not applied torequiredKindsbelow. If aRetryAttempts-onlyIArtifactPostProcessorRequiresPostProcessingis registered alongside any module processor, its kind is advertised as required in the normal SDK handshake; the producer then suppresses standalone output even though the dispatcher excludes that processor forTestModules. Filter required processors throughSupportsTestModuleMergingas well.
- Files reviewed: 51/51 changed files
- Comments generated: 1
- Review effort level: Balanced
This comment has been minimized.
This comment has been minimized.
Snapshot reports written outside the attempt directory, merge their immutable copies, and publish the final logical report back to the requested destination. Also limit required handshake kinds to module-capable processors. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: cc4e6933-6640-41a2-9fec-557983005fdb
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Wait for the asynchronous flush error log before verifying it, matching the existing synchronization used for other telemetry continuations. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
🧵 Parallel-safety audit — PR #10542Parallelization — one row per test assembly audited:
All four assemblies opt in via Findings: A (global-state) Analysis performed: I reviewed all 11 changed test files (unit tests for CTRF/JUnit/HTML/TRX artifact post-processors,
Nothing to flag for parallel-safety in this PR. Advisory only — heuristic, non-blocking. Re-run with
|
🧪 Expert test review — PR #10542
Summary: This PR's test changes are consistently strong. Every new or This advisory comment was generated automatically. Grades are heuristic
|
--retry-failed-testscurrently publishes only the final attempt's narrowed report at the top level, so report consumers can miss tests that passed earlier in the run. This change consolidates retry-aware formats while preserving every physical attempt for diagnostics.Changes
retryAttempts,retries,flaky, and corrected summary counters.Retries/; TRX and HTML intentionally retain final-attempt top-level semantics.Testing
Fixes #10293