Conversation
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>
There was a problem hiding this comment.
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
mauiDesktopBenchmarksscenario (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.
| 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') |
| # 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}') |
…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>
…hmarks" This reverts commit 42e0736.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/azp run |
|
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. |
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
There was a problem hiding this comment.
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
BDNDesktopHelperto patch external benchmark repos (TFM disabling, injectBenchmarkDotNet.Extensions, patchProgram.csto usePerfLabExporter+ exclusion filter), then build/run and collect results. - Adds a new
mauiDesktopBenchmarksscenario payload and a new Helix project (maui_desktop_benchmarks.proj) to run MAUI desktop BDN suites. - Updates pipeline jobs and makes
ExclusionFilterpublic 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.
| # # 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 }} |
There was a problem hiding this comment.
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.
| # 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}') |
There was a problem hiding this comment.
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.
| # 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') |
There was a problem hiding this comment.
_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.
| 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') |
There was a problem hiding this comment.
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).
| 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}') |
No description provided.