Skip to content

Fix static web assets lock-race issue for E2E tests - #68504

Open
PureWeen with Copilot wants to merge 2 commits into
mainfrom
copilot/replace-static-assets-lock-race-fix
Open

Fix static web assets lock-race issue for E2E tests#68504
PureWeen with Copilot wants to merge 2 commits into
mainfrom
copilot/replace-static-assets-lock-race-fix

Conversation

Copilot AI commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Serialize the Components E2E trimmed app project-reference traversal so concurrent publishes cannot write the same static web asset compression intermediate.

This PR was created after two Windows CI failures demonstrated that multiple trimmed Blazor WebAssembly app publishes can concurrently traverse the same shared framework project and race while producing its Brotli-compressed static assets.

Failure being addressed

Build 1552169 failed in Windows local development validation while publishing the Components E2E test applications. GlobalizationWasmApp and Wasm.Performance.TestApp overlapped while both traversed Microsoft.AspNetCore.Components.WebAssembly.csproj.

Each traversal ran GeneratePublishCompressedStaticWebAssets for the same logical _framework/blazor.webassembly.js.map asset. Because the SDK derives the compressed output identity from the shared asset metadata, both invocations targeted the same file:

artifacts\obj\Microsoft.AspNetCore.Components.WebAssembly\Release\net11.0\compressed\publish\jpsg8p4gww-{0}-n92mzkaipp-n92mzkaipp.br

The Brotli tool opens that output with FileMode.Create and does not coordinate across separate MSBuild invocations, so one process failed when the other held the file open.

The previous mitigation in #68463 avoided the redundant Components.TestServer traversal, but it did not cover the direct trimmed app project references. Current-main build 1552404 reproduced the identical lock after #68463 merged, confirming the remaining ownership boundary.

Correction

When TestTrimmedApps=true, set BuildInParallel=false in Microsoft.AspNetCore.Components.E2ETests.csproj.

This serializes the Release/CI project-reference traversal that owns these trimmed app publishes, preventing two callers from entering the shared compression path simultaneously. Debug and ordinary local builds retain their existing parallel behavior.

The fix intentionally does not add retries, sleeps, disable compression, or globally serialize product builds. It is scoped to the test project and configuration that creates the duplicate writers.

Validation

Property evaluation confirmed:

  • Release/CI: TestTrimmedApps=true, BuildInParallel=false
  • Debug/local: TestTrimmedApps unset, BuildInParallel=true

A targeted Release build of Microsoft.AspNetCore.Components.E2ETests.csproj succeeded, and its binlog confirmed the E2E ResolveProjectReferences MSBuild task ran with BuildInParallel=False.

The replacement PR CI also passed the relevant Windows behavioral validation:

  • aspnetcore-ci
  • Windows local development validation
  • Windows x64/x86/arm64 build
  • Windows Server tests
  • Components E2E tests on CoreCLR and Mono
  • Both Helix subsets
  • Linux and macOS builds/tests
  • Quarantined test legs

Scope and limitations

This is a repository-owned workaround for the proven Components E2E publish topology. It does not make arbitrary concurrent SDK static web asset publishes safe; a systemic fix would belong in dotnet/sdk.

Local behavioral validation was performed on macOS, which cannot reproduce the same Windows file-sharing exception. The PR's passing Windows local development validation provides the platform-specific confirmation.

Prevent concurrent E2E trimmed app publishes from writing the same static web asset compression intermediates.

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

Co-authored-by: PureWeen <5375137+PureWeen@users.noreply.github.com>
Copilot AI requested a review from PureWeen August 13, 2026 20:37
@PureWeen
PureWeen marked this pull request as ready for review August 13, 2026 22:13
@PureWeen
PureWeen requested a review from a team as a code owner August 13, 2026 22:13
Copilot AI lite review requested due to automatic review settings August 13, 2026 22:13
@PureWeen PureWeen changed the title [WIP] Fix static web assets lock-race issue for E2E tests Fix static web assets lock-race issue for E2E tests Aug 13, 2026

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

This PR mitigates a Windows CI file-lock race in Components E2E trimmed app publishes by serializing project-reference traversal for the E2E test project when trimmed apps are being published.

Changes:

  • Disable parallel project-reference builds/publishes (BuildInParallel=false) when TestTrimmedApps=true to prevent concurrent writes to shared static web asset compression intermediates.
Show a summary per file
File Description
src/Components/test/E2ETest/Microsoft.AspNetCore.Components.E2ETests.csproj Serializes project-reference traversal for trimmed-app publish scenarios by setting BuildInParallel=false under TestTrimmedApps.

Review details

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 1/1 changed files
  • Comments generated: 0
  • Review effort level: Lite

<TestTrimmedApps Condition="'$(ContinuousIntegrationBuild)' == 'true'">true</TestTrimmedApps>
<TestTrimmedApps Condition="'$(Configuration)' == 'Release'">true</TestTrimmedApps>
<!-- The trimmed app publishes share project intermediate outputs, so their project references cannot run concurrently. -->
<BuildInParallel Condition="'$(TestTrimmedApps)' == 'true'">false</BuildInParallel>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does this increase CI time? Do we want to ensure that apps use separate intermediate directories?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why does it happen that a single app is published in parallel (more than once) for a single build?
Isn't the underlaying issue in msbuild not reusing existing build/project instance?
Possibly by passing different props?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@copilot assess and resolve please

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Assessed; I don’t think a code change is needed beyond fc00a63. This can increase only the Release/CI Components E2E trimmed-app preparation because those trimmed app project references now run serially; Debug/local and product builds keep their existing parallelism.

Separate intermediate directories would need to partition the referenced framework project intermediates, not just each app's PublishDir, because the collision is under artifacts\obj\Microsoft.AspNetCore.Components.WebAssembly\Release\net11.0\compressed\publish\.... That would be a broader and likely more expensive workaround.

This isn't one app intentionally being published twice. The E2E project publishes multiple trimmed apps in parallel, and those nested publishes each traverse Microsoft.AspNetCore.Components.WebAssembly with the same effective Configuration/TFM/static-web-asset identity. MSBuild doesn't coalesce those nested Publish traversals across the parallel project-reference invocations, so serializing at the E2E project owner is the smallest scoped fix.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants