Skip to content

Add maui desktop testing#5161

Draft
LoopedBard3 wants to merge 18 commits intodotnet:mainfrom
LoopedBard3:AddMauiDesktopTesting
Draft

Add maui desktop testing#5161
LoopedBard3 wants to merge 18 commits intodotnet:mainfrom
LoopedBard3:AddMauiDesktopTesting

Conversation

@LoopedBard3
Copy link
Copy Markdown
Member

No description provided.

LoopedBard3 and others added 3 commits March 17, 2026 14:33
New scenario that clones dotnet/maui, builds dependencies, patches in
PerfLabExporter via BenchmarkDotNet.Extensions, and runs the Core, XAML,
and Graphics BDN benchmark suites on desktop (Windows).

Key implementation details:
- Sparse-clone of dotnet/maui with depth 1 (only needed directories)
- Patches Directory.Build.props to disable non-desktop TFMs so all
  builds (including BDN internal builds) work without mobile workloads
- Removes MAUI BDN PackageReference, injects BDN.Extensions ProjectRef
- Patches Program.cs with ManualConfig + PerfLabExporter
- Branch mapping: net11.0 to net11.0, net10.0 to net10.0
- All heavy work in test.py to keep correlation payload small
- Pipeline entries disabled until validated in CI

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move lifecycle logic (clone, patch, build, run, collect) from standalone
test.py into shared/bdndesktop.py BDNDesktopHelper class, following the
same pattern as AndroidInstrumentationHelper. Add BDNDESKTOP test type
to const.py and runner.py subparser routing.

test.py is now 16 lines, delegating to Runner(traits).run().

Tested locally: Graphics.Benchmarks ran successfully via runner path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Move clone, branch mapping, sparse checkout, and dependency build into
test.py (MAUI-specific orchestrator). BDNDesktopHelper now accepts
repo_dir, benchmark_projects, and disable_props as constructor params,
making it reusable for any repo's BDN desktop benchmarks.

Remove bdndesktop routing from runner.py and const.py since test.py
drives the helper directly with its own arg parsing.

Tested locally: Graphics.Benchmarks ran successfully via refactored path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@LoopedBard3 LoopedBard3 requested a review from Copilot March 18, 2026 22:26
@LoopedBard3 LoopedBard3 self-assigned this Mar 18, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new MAUI Desktop BenchmarkDotNet (BDN) scenario to the repo, including a reusable shared helper to patch/build/run external desktop benchmark suites and (optionally) collect/upload PerfLabExporter results.

Changes:

  • Introduces BDNDesktopHelper (shared/bdndesktop.py) to patch TFMs, inject PerfLabExporter, build, run, and collect BDN results from external repos.
  • Adds a new mauiDesktopBenchmarks scenario (pre/test/post scripts) plus a Helix project file to run MAUI desktop BDN suites.
  • Adds (currently disabled) pipeline job stubs for the new run kind in sdk-perf-jobs.yml.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 11 comments.

Show a summary per file
File Description
src/scenarios/shared/runner.py Whitespace-only change in argument parsing.
src/scenarios/shared/bdndesktop.py New shared helper for patching external repos and running/collecting BDN desktop benchmarks.
src/scenarios/mauiDesktopBenchmarks/test.py Clones dotnet/maui, patches props, builds dependencies, runs BDN suites via shared helper.
src/scenarios/mauiDesktopBenchmarks/pre.py Minimal pre-command script (logging only).
src/scenarios/mauiDesktopBenchmarks/post.py Cleans up MAUI repo checkout and combined report artifact.
eng/pipelines/sdk-perf-jobs.yml Adds new MAUI desktop BDN job entries, currently gated by if false.
eng/performance/maui_desktop_benchmarks.proj New Helix project definition for MAUI desktop BDN work item.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment thread src/scenarios/shared/bdndesktop.py Outdated
Comment thread src/scenarios/shared/bdndesktop.py
Comment on lines +344 to +347
basename = os.path.basename(report_file)
dest = os.path.join(upload_root, basename)
shutil.copy2(report_file, dest)
log.info(f' Copied {basename} to upload root')
Comment thread src/scenarios/mauiDesktopBenchmarks/test.py Outdated
Comment thread src/scenarios/mauiDesktopBenchmarks/post.py
Comment thread eng/pipelines/sdk-perf-jobs.yml
Comment thread src/scenarios/shared/runner.py Outdated
Comment thread src/scenarios/shared/bdndesktop.py Outdated
Comment on lines +162 to +169
# Add ProjectReference to BDN.Extensions
item_group = ET.SubElement(root, f'{ns}ItemGroup')
item_group.set('Label', 'PerfLabInjected')
proj_ref = ET.SubElement(item_group, f'{ns}ProjectReference')
proj_ref.set('Include', bdn_ext_rel)

tree.write(csproj_path, xml_declaration=True, encoding='utf-8')
log.info(f' Added ProjectReference: {bdn_ext_rel}')
Comment thread src/scenarios/shared/bdndesktop.py Outdated
@LoopedBard3 LoopedBard3 requested review from simonrozsival and removed request for simonrozsival March 23, 2026 20:32
LoopedBard3 and others added 15 commits March 23, 2026 14:38
…ty, semicolon handling

- Use performance.common.remove_directory() instead of shutil.rmtree for
  Windows long-path handling in test.py and post.py (C4, C5)
- Narrow BDN PackageReference removal to exact package names instead of
  prefix match to preserve optional subpackages (C1)
- Always emit trailing semicolon in patched Program.cs to avoid invalid
  C# when source pattern lacks semicolon (C2)
- Add whitespace tolerance to Directory.Build.props regex and log when
  a requested property has zero matches (C9)
- Harmonize report glob pattern to *perf-lab-report.json across
  collection and upload paths (C11)
- Remove whitespace-only change in runner.py (C8)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the if false guards from both the public (win-x64) and private
(win-x64-viper) MAUI Desktop BenchmarkDotNet pipeline entries.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Helix work items don't have git on PATH. Add _find_git() to check
common Windows install locations (Program Files\Git\cmd\git.exe).
If git is truly unavailable, fall back to downloading the GitHub
archive as a zip and extracting only the sparse checkout directories
plus root-level files (Directory.Build.props, NuGet.config, etc.).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Python's bundled SSL certificates don't include the CA certs trusted
by Helix machines, causing CERTIFICATE_VERIFY_FAILED. Use curl.exe
(built into Windows 10+/Server 2016+) which uses the Windows
certificate store instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Git sparse-checkout automatically includes files in parent directories
of checked-out paths. The zip fallback wasn't extracting files like
src/MultiTargeting.targets and src/PublicAPI.targets because they live
at the src/ level, outside the specific sparse checkout subdirectories.

Compute parent directories from the sparse checkout list and include
files directly in those parent dirs (non-recursively).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
XAML benchmarks on the net11.0 branch have a hardcoded net10.0 TFM
that causes NU1201 restore errors. Instead of failing the entire run,
track which suites built successfully and only run those. Exit with
error only if ALL suites fail to build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove ##[warning]/##[error] print statements since builds run inside
Helix, not directly in AzDO pipeline steps.

Add --iterationCount 15 and --warmupCount 3 to BDN runs. The default
adaptive algorithm was running up to 100 WorkloadActual iterations per
benchmark, causing the entire run to exceed the 4-hour Helix timeout
before completing even the Core suite.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align CLI args with the repo's RecommendedConfig.cs defaults:
  --warmupCount 1       (1 warmup is enough)
  --minIterationCount 15
  --maxIterationCount 20  (cap adaptive algorithm)
  --iterationTime 250     (250ms vs BDN default 500ms)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Patch Program.cs to parse --exclusion-filter using the existing
CommandLineOptions/ExclusionFilter from BDN.Extensions, stripping
it from args before passing to BenchmarkSwitcher.Run().

Exclude *MauiLoggerWithLoggerMinLevelErrorBenchmarker* by default in
the MAUI test.py — these emit millions of BindableProperty error log
lines per iteration, bloating output and contributing to timeouts.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This will be reverted after testing is validated.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@LoopedBard3
Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines will not run the associated pipelines, because the pull request was updated after the run command was issued. Review the pull request again and issue a new run command.

@LoopedBard3
Copy link
Copy Markdown
Member Author

/azp run

@azure-pipelines
Copy link
Copy Markdown

Azure Pipelines successfully started running 1 pipeline(s).

@LoopedBard3 LoopedBard3 marked this pull request as ready for review April 20, 2026 20:30
Copilot AI review requested due to automatic review settings April 20, 2026 20:30
@LoopedBard3 LoopedBard3 marked this pull request as draft April 20, 2026 20:31
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new MAUI “desktop BenchmarkDotNet” scenario to the performance scenarios infrastructure, including a shared helper to patch/build/run external-repo BDN projects and collect/upload PerfLab results.

Changes:

  • Introduces BDNDesktopHelper to patch external benchmark repos (TFM disabling, inject BenchmarkDotNet.Extensions, patch Program.cs to use PerfLabExporter + exclusion filter), then build/run and collect results.
  • Adds a new mauiDesktopBenchmarks scenario payload and a new Helix project (maui_desktop_benchmarks.proj) to run MAUI desktop BDN suites.
  • Updates pipeline jobs and makes ExclusionFilter public for external consumption.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/scenarios/shared/bdndesktop.py New shared helper to patch/build/run external desktop BDN benchmarks and collect/upload PerfLab reports.
src/scenarios/mauiDesktopBenchmarks/test.py MAUI-specific orchestration (clone/sparse checkout, patch props, build deps, run suites).
src/scenarios/mauiDesktopBenchmarks/pre.py Minimal pre-command stub for the scenario payload.
src/scenarios/mauiDesktopBenchmarks/post.py Cleanup of cloned MAUI repo and local combined report artifact.
src/harness/BenchmarkDotNet.Extensions/ExclusionFilter.cs Makes ExclusionFilter public for use by patched external Program.cs.
eng/pipelines/sdk-perf-jobs.yml Adds MAUI desktop BDN jobs, but also comments out most existing public jobs.
eng/performance/maui_desktop_benchmarks.proj New Helix project definition for the MAUI desktop BDN scenario work item.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +22 to 72
# # Scenario benchmarks
# - template: /eng/pipelines/templates/build-machine-matrix.yml
# parameters:
# jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
# buildMachines:
# - win-x64
# - ubuntu-x64
# isPublic: true
# jobParameters:
# runKind: scenarios
# projectFileName: scenarios.proj
# channels: # for public jobs we want to make sure that the PRs don't break any of the supported frameworks
# - main
# - 9.0
# - 8.0
# ${{ each parameter in parameters.jobParameters }}:
# ${{ parameter.key }}: ${{ parameter.value }}

# # MAUI scenario benchmarks
# - ${{ if false }}:
# - template: /eng/pipelines/templates/build-machine-matrix.yml
# parameters:
# jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
# buildMachines:
# - win-x64
# - ubuntu-x64
# isPublic: true
# jobParameters:
# runKind: maui_scenarios
# projectFileName: maui_scenarios.proj
# channels: # for public jobs we want to make sure that the PRs don't break any of the supported frameworks
# - main
# - 9.0
# - 8.0
# ${{ each parameter in parameters.jobParameters }}:
# ${{ parameter.key }}: ${{ parameter.value }}

# MAUI Desktop BenchmarkDotNet benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: scenarios
projectFileName: scenarios.proj
channels: # for public jobs we want to make sure that the PRs don't break any of the supported frameworks
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# MAUI scenario benchmarks
- ${{ if false }}:
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: maui_scenarios
projectFileName: maui_scenarios.proj
channels: # for public jobs we want to make sure that the PRs don't break any of the supported frameworks
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# Blazor scenario benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: blazor_scenarios
projectFileName: blazor_scenarios.proj
channels: # for public jobs we want to make sure that the PRs don't break any of the supported frameworks
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# SDK scenario benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-scenarios-job.yml
buildMachines:
#- win-x86
#- ubuntu-x64-1804 reenable under new machine on new ubuntu once lttng/events are available
isPublic: true
jobParameters:
runKind: sdk_scenarios
projectFileName: sdk_scenarios.proj
channels: # for public jobs we want to make sure that the PRs don't break any of the supported frameworks
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# micro benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- win-x86
isPublic: true
jobParameters:
runKind: micro
targetCsproj: src\benchmarks\micro\MicroBenchmarks.csproj
runCategories: 'runtime libraries'
channels:
- main
- 9.0
- 8.0

# Ubuntux64 Default and NativeAOT micro benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- ubuntu-x64
isPublic: true
jobParameters:
runKind: micro
targetCsproj: src\benchmarks\micro\MicroBenchmarks.csproj
runCategories: 'runtime libraries'
channels:
- main
# - nativeaot9.0 # Disable until I have time to properly fix the issues and can merge https://github.com/dotnet/performance/pull/4741
# - nativeaot8.0
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# ML.NET benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: mlnet
targetCsproj: src\benchmarks\real-world\Microsoft.ML.Benchmarks\Microsoft.ML.Benchmarks.csproj
runCategories: 'mldotnet'
channels:
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# F# benchmarks
- ${{ if false }}: # skipping, no useful benchmarks there currently
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: fsharp
targetCsproj: src\benchmarks\real-world\FSharp\FSharp.fsproj
runCategories: 'fsharp'
channels:
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: fsharpmicro
targetCsproj: src\benchmarks\micro-fsharp\MicrobenchmarksFSharp.fsproj
runCategories: 'FSharpMicro'
channels:
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# bepuphysics benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: bepuphysics
targetCsproj: src\benchmarks\real-world\bepuphysics2\DemoBenchmarks.csproj
runCategories: 'BepuPhysics'
runKind: maui_desktop_benchmarks
projectFileName: maui_desktop_benchmarks.proj
channels:
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# ImageSharp benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: imagesharp
targetCsproj: src\benchmarks\real-world\ImageSharp\ImageSharp.Benchmarks.csproj
runCategories: 'ImageSharp'
channels:
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# Akade.IndexedSet benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: akadeindexedset
targetCsproj: src\benchmarks\real-world\Akade.IndexedSet.Benchmarks\Akade.IndexedSet.Benchmarks.csproj
runCategories: 'AkadeIndexedSet'
channels:
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}

# Roslyn benchmarks
- template: /eng/pipelines/templates/build-machine-matrix.yml
parameters:
jobTemplate: /eng/pipelines/templates/run-performance-job.yml
buildMachines:
- win-x64
- ubuntu-x64
isPublic: true
jobParameters:
runKind: roslyn
targetCsproj: src\benchmarks\real-world\Roslyn\CompilerBenchmarks.csproj
runCategories: 'roslyn'
channels: # for Roslyn jobs we want to check .NET Core 3.1 and 5.0 only
- main
- 9.0
- 8.0
${{ each parameter in parameters.jobParameters }}:
${{ parameter.key }}: ${{ parameter.value }}
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

In the public jobs section, the existing scenario/micro/real-world jobs appear to have been commented out, leaving only the new MAUI desktop job active under runPublicJobs. This would effectively disable the rest of the public correctness coverage, which seems unrelated to adding a new MAUI desktop scenario. Please restore the original public job templates and add the MAUI desktop benchmarks as an additional job (or gate it independently) rather than replacing/commenting out the existing jobs.

Copilot uses AI. Check for mistakes.
Comment on lines +156 to +165
# Remove the primary BenchmarkDotNet PackageReference to avoid version conflicts.
# Only remove exact 'BenchmarkDotNet' to preserve optional subpackages
# (e.g. BenchmarkDotNet.Annotations, BenchmarkDotNet.Diagnostics.*).
bdn_packages_to_remove = {'BenchmarkDotNet', 'BenchmarkDotNet.Annotations'}
for item_group in root.findall(f'{ns}ItemGroup'):
for pkg_ref in item_group.findall(f'{ns}PackageReference'):
include = pkg_ref.get('Include', '')
if include in bdn_packages_to_remove:
item_group.remove(pkg_ref)
log.info(f' Removed PackageReference: {include}')
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

The comment says only the exact BenchmarkDotNet PackageReference is removed to preserve optional subpackages (example given: BenchmarkDotNet.Annotations), but the code also removes BenchmarkDotNet.Annotations. Either update the comment to reflect the actual removal set, or stop removing BenchmarkDotNet.Annotations if it should be preserved.

Copilot uses AI. Check for mistakes.
Comment on lines +167 to +173
# Add ProjectReference to BDN.Extensions
item_group = ET.SubElement(root, f'{ns}ItemGroup')
item_group.set('Label', 'PerfLabInjected')
proj_ref = ET.SubElement(item_group, f'{ns}ProjectReference')
proj_ref.set('Include', bdn_ext_rel)

tree.write(csproj_path, xml_declaration=True, encoding='utf-8')
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

_inject_bdn_extensions always appends a new ItemGroup + ProjectReference without checking whether the project has already been patched (e.g., by a previous run). Re-running the scenario locally (or a retry in the same checkout) can lead to duplicate ProjectReference entries. Consider making this patch idempotent by detecting an existing ProjectReference to the extensions project (or an ItemGroup with Label="PerfLabInjected") before adding a new one.

Copilot uses AI. Check for mistakes.
Comment on lines +376 to +379
basename = os.path.basename(report_file)
dest = os.path.join(upload_root, basename)
shutil.copy2(report_file, dest)
log.info(f' Copied {basename} to upload root')
Copy link

Copilot AI Apr 20, 2026

Choose a reason for hiding this comment

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

When copying individual *perf-lab-report.json files to HELIX_WORKITEM_UPLOAD_ROOT, the destination uses only os.path.basename(report_file). If multiple projects produce the same report filename, later copies will overwrite earlier ones and lose data. Consider either uploading only the combined report, or generating unique destination names (e.g., include suite name or a relative path hash/prefix).

Suggested change
basename = os.path.basename(report_file)
dest = os.path.join(upload_root, basename)
shutil.copy2(report_file, dest)
log.info(f' Copied {basename} to upload root')
relative_path = os.path.relpath(report_file, self.repo_dir)
unique_name = re.sub(r'[^A-Za-z0-9._-]+', '_', relative_path)
dest = os.path.join(upload_root, unique_name)
shutil.copy2(report_file, dest)
log.info(f' Copied {relative_path} to upload root as {unique_name}')

Copilot uses AI. Check for mistakes.
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.

2 participants