Skip to content

Unify template-resolve-and-sanitize pipeline in ArtifactNamingHelper#9855

Merged
Evangelink merged 1 commit into
mainfrom
dev/amauryleve/expert-bassoon
Jul 11, 2026
Merged

Unify template-resolve-and-sanitize pipeline in ArtifactNamingHelper#9855
Evangelink merged 1 commit into
mainfrom
dev/amauryleve/expert-bassoon

Conversation

@Evangelink

Copy link
Copy Markdown
Member

Fixes #9841.

Problem

ArtifactNamingService.ResolveFileName (in Microsoft.Testing.Platform) and ReportFileNameHelper.ResolveAndSanitize (in SharedExtensionHelpers) implemented the same algorithm: resolve template placeholders via ArtifactNamingHelper, split the result into directory + leaf, sanitize the leaf, and reassemble the path. The only real differences were where the process name/id came from and which sanitizer was used.

Change

Applied recommendation #2 from the issue (smaller, less invasive): extracted the shared pipeline into a single static overload ArtifactNamingHelper.ResolveAndSanitize(template, processName, processId, timestamp, sanitizeLeafFileName) that takes the leaf sanitizer as a Func<string, string> delegate.

  • ArtifactNamingService.ResolveFileName now delegates, passing ArtifactFileNameSanitizer.ReplaceInvalidFileNameChars.
  • ReportFileNameHelper.ResolveAndSanitize now delegates, passing ReportFileNameSanitizer.ReplaceInvalidFileNameChars. Its public signature is unchanged (matches the shipped InternalAPI), so no shipped-API churn.
  • The non-empty leaf-name guard that only ArtifactNamingService previously had is now applied on both paths.

The two sanitizers (ArtifactFileNameSanitizer / ReportFileNameSanitizer) are intentionally left as-is and passed in as delegates — consolidating them is tracked separately (the related issue referenced in #9841).

Notes

  • The new ArtifactNamingHelper.ResolveAndSanitize member is added to the InternalAPI.Unshipped.txt of every project that links the ArtifactNamingHelper source (RS0051).

Testing

  • Microsoft.Testing.Platform.UnitTests — ArtifactNaming* tests: 24/24 passed.
  • Microsoft.Testing.Extensions.UnitTests — ReportFileName* tests: 12/12 passed.
  • Report extensions (Trx/Html/JUnit/Ctrf/…) build clean with no RS0051 warnings.

Extract the shared resolve-template/split-path/sanitize-leaf/recombine pipeline into a single static ArtifactNamingHelper.ResolveAndSanitize overload that accepts a leaf sanitizer delegate. ArtifactNamingService and ReportFileNameHelper now both delegate to it, removing the near-identical duplicated logic described in #9841. The non-empty leaf guard is now applied on both paths.

Fixes #9841

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 8c5b1087-7e14-45e5-a444-daf19d40d832
Copilot AI review requested due to automatic review settings July 11, 2026 12:12

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Unifies artifact template resolution and leaf-name sanitization in ArtifactNamingHelper, resolving #9841.

Changes:

  • Extracts the shared resolve-and-sanitize pipeline.
  • Delegates platform and report naming paths to the shared helper.
  • Tracks the new internal API across all linked-source assemblies.
Show a summary per file
File Description
SharedExtensionHelpers/ReportFileNameHelper.cs Delegates report naming to the shared pipeline.
Microsoft.Testing.Platform/Services/ArtifactNamingService.cs Delegates artifact naming to the shared pipeline.
Microsoft.Testing.Platform/Services/ArtifactNamingHelper.cs Adds the shared resolve-and-sanitize implementation.
Microsoft.Testing.Platform/InternalAPI/InternalAPI.Unshipped.txt Tracks the new internal method.
Microsoft.Testing.Extensions.VideoRecorder/InternalAPI/InternalAPI.Unshipped.txt Tracks the linked method.
Microsoft.Testing.Extensions.TrxReport/InternalAPI/InternalAPI.Unshipped.txt Tracks the linked method.
Microsoft.Testing.Extensions.JUnitReport/InternalAPI/InternalAPI.Unshipped.txt Tracks the linked method.
Microsoft.Testing.Extensions.HtmlReport/InternalAPI/InternalAPI.Unshipped.txt Tracks the linked method.
Microsoft.Testing.Extensions.HangDump/InternalAPI/InternalAPI.Unshipped.txt Tracks the linked method.
Microsoft.Testing.Extensions.CtrfReport/InternalAPI/InternalAPI.Unshipped.txt Tracks the linked method.
Microsoft.Testing.Extensions.CrashDump/InternalAPI/InternalAPI.Unshipped.txt Tracks the linked method.

Review details

  • Files reviewed: 11/11 changed files
  • Comments generated: 0
  • Review effort level: Medium

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

🤖 Automated review by GitHub Copilot. Generated by the Expert Code Review workflow. To request a follow-up action, reply by tagging @copilot directly.

Review Summary

Clean, well-scoped refactoring that unifies two near-identical template-resolve-and-sanitize pipelines into a single ArtifactNamingHelper.ResolveAndSanitize method. Both callers (ArtifactNamingService.ResolveFileName and ReportFileNameHelper.ResolveAndSanitize) now delegate to it, passing their respective sanitizer functions.

# Dimension Verdict
1 Algorithmic Correctness ✅ Logic is identical to the extracted code. One minor behavioral tightening noted inline (empty leaf name now throws for ReportFileNameHelper path too).
2 Edge Cases & Error Handling
3 Concurrency & Thread Safety N/A
4 Performance & Allocations ✅ No change in allocation profile
5 API Design & Public Surface ✅ Internal API, properly declared in InternalAPI.Unshipped.txt for all referencing projects
6 Backward Compatibility ✅ Internal-only change
7 Cross-TFM Correctness ✅ No TFM-specific code
8 Security
9 Naming & Conventions
10 Code Style & Formatting
11 Documentation ✅ Thorough XML docs
12 Localization N/A
13 Testing ✅ Existing tests cover both callers
14–22 Remaining dimensions N/A or ✅

Overall: This is a textbook DRY refactoring. No blocking issues found.

Comment thread src/Platform/SharedExtensionHelpers/ReportFileNameHelper.cs
@github-actions

Copy link
Copy Markdown
Contributor

🔴 Build Failure Analysis

Build: FAILED | Duration: 255s | Errors: 5 (4 unique) | Warnings: 1

Root Cause

All 4 compilation errors are CA1416 (platform compatibility) in test/UnitTests/Microsoft.Testing.Platform.UnitTests/Logging/FileLoggerTests.cs at lines 465 and 490 (two TFMs, so each appears twice):

error CA1416: This call site is reachable on all platforms.
'ITask.RunLongRunning(Func<Task>, string, CancellationToken)' is unsupported on: 'browser'.

The ITask.RunLongRunning method is annotated with [UnsupportedOSPlatform("browser")], and the two inner ITask wrapper classes (MonitoringTask and NeverCompletingTask) in FileLoggerTests.cs delegate to it without suppressing the warning.

Relationship to This PR

⚠️ This file is not modified by this PR. These appear to be pre-existing errors on the base branch that may have been recently introduced by a prior commit adding the [UnsupportedOSPlatform] attribute to ITask.RunLongRunning, or a change that enabled CA1416 for this project.

Suggested Fix

Add [SupportedOSPlatform] or suppress CA1416 on the two wrapper classes in FileLoggerTests.cs. For example, add #pragma warning disable CA1416 around the RunLongRunning delegation calls at lines 465 and 490, since the test never actually runs on browser:

#pragma warning disable CA1416 // Platform compatibility — tests don't target browser
        public Task RunLongRunning(Func<Task> action, string name, CancellationToken cancellationToken)
            => _inner.RunLongRunning(action, name, cancellationToken);
#pragma warning restore CA1416

This fix would need to be applied to both MonitoringTask (line 465) and NeverCompletingTask (line 490).

🤖 Automated content by GitHub Copilot. Generated by the Build Failure Analysis workflow. · 53.8 AIC · ⌖ 5.67 AIC · ⊞ 7.3K · [◷]( · )

@Evangelink

Copy link
Copy Markdown
Member Author

Thanks for the analysis. Confirmed these CA1416 errors are pre-existing on main and not caused by this PR — the failing file (\ est/UnitTests/Microsoft.Testing.Platform.UnitTests/Logging/FileLoggerTests.cs) is not modified here, and the \ITask.RunLongRunning\ delegations already exist on \main. They're being addressed separately, so this PR (a scoped dedup refactor) intentionally leaves them alone; CI should go green once main is fixed and this branch is rebased.

@Evangelink
Evangelink merged commit e2d1590 into main Jul 11, 2026
28 of 35 checks passed
@Evangelink
Evangelink deleted the dev/amauryleve/expert-bassoon branch July 11, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[duplicate-code] Duplicate Code: Template-Resolve-and-Sanitize Pipeline in ArtifactNamingService vs ReportFileNameHelper

2 participants