Skip to content

fix(ci): kill the multi-arch publish CopyRefAssembly race (MSB3883) - #552

Merged
rbuergi merged 1 commit into
mainfrom
fix/multiarch-refasm-race
Jul 19, 2026
Merged

rbuergi merged 1 commit into
mainfrom
fix/multiarch-refasm-race

Conversation

@rbuergi

@rbuergi rbuergi commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

The flake

The portal-ai image build intermittently fails the continuous deploy with:

error MSB3883: Unexpected exception:  [.../MeshWeaver.Graph/MeshWeaver.Graph.csproj]
IOException: The process cannot access the file
'.../MeshWeaver.Graph/obj/Release/net10.0/ref/MeshWeaver.Graph.dll'
because it is being used by another process.  (CopyRefAssembly)

(e.g. CD run 29687305177). This is a build-time race, not a runtime one — no hub / observable / cached-instance involved.

Root cause

The CD/release/edge image builds publish per-RID via -p:ContainerRuntimeIdentifiers="linux-x64;linux-arm64", and the SDK builds the two RID legs concurrently. A reference assembly is RID-invariant, so its intermediate path has no rid segment — obj/<cfg>/<tfm>/ref/<Asm>.dll. Both RID legs' CopyRefAssembly target therefore write the same file and intermittently collide. It's non-deterministic because it only fails when the two legs happen to hit CopyRefAssembly for the same referenced library at the same instant.

The fix

Turn off reference-assembly production for the multi-arch publish only, in Directory.Build.props, gated on the global ContainerRuntimeIdentifiers being set (a global property, so it is seen by every project in the publish graph — including the referenced libraries that actually race).

Reference assemblies only accelerate incremental rebuilds; a from-clean CI container publish gains nothing from them — so this removes the one shared, contended output while keeping both RID legs parallel (no serialization, no retry, no slowdown). Normal dev builds and the Build and Test CI leave ContainerRuntimeIdentifiers empty, so ref assemblies and fast incremental builds are unaffected there. Covers main-cd, release-images, and edge-images from one place — no per-command drift.

Verification

Deterministically checked on MeshWeaver.Graph (the project that raced), via dotnet msbuild -getProperty:ProduceReferenceAssembly:

Context ProduceReferenceAssembly
normal build (no multi-arch prop) true (default — unchanged)
-p:ContainerRuntimeIdentifiers=linux-x64%3Blinux-arm64 (publish) false (racy artifact not produced)

No user-facing change → no What's New entry.

🤖 Generated with Claude Code

The continuous/release/edge image builds publish per-RID via -p:ContainerRuntimeIdentifiers="linux-x64;linux-arm64", and the SDK builds the two RID legs CONCURRENTLY. A reference assembly is RID-invariant, so its intermediate path has no rid segment (obj/<cfg>/<tfm>/ref/<Asm>.dll) — both legs' CopyRefAssembly target write that same file and intermittently collide: 'error MSB3883: ... MeshWeaver.Graph.dll ... being used by another process', failing the portal-ai image build (e.g. CD run 29687305177).

Root fix: turn off reference-assembly production for the multi-arch publish only (Directory.Build.props, gated on the global ContainerRuntimeIdentifiers being set — seen by every project in the publish graph, including the referenced libraries that race). Ref assemblies only accelerate INCREMENTAL rebuilds; a from-clean CI publish gains nothing, so this removes the one shared, contended output while keeping both RID legs parallel — no serialization, no retry. Normal dev + Build-and-Test CI leave ContainerRuntimeIdentifiers empty, so ref assemblies and fast incremental builds are unaffected there.

Verified via -getProperty on MeshWeaver.Graph (the project that raced): ProduceReferenceAssembly evaluates true with no multi-arch prop, false when ContainerRuntimeIdentifiers is set.

No user-facing change → no What's New entry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 19, 2026 12:58

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 addresses an intermittent CI/CD build-time flake in multi-arch container publishes where concurrent RID legs race on the same RID-invariant reference-assembly intermediate output (CopyRefAssembly → MSB3883). It does so by disabling reference-assembly generation only when ContainerRuntimeIdentifiers is set, preserving normal dev and non-container CI behavior.

Changes:

  • Conditionally disables ProduceReferenceAssembly when $(ContainerRuntimeIdentifiers) is non-empty to avoid concurrent writes to obj/<cfg>/<tfm>/ref/*.dll during multi-RID container publish.

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

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

   11 files  ±0     11 suites  ±0   4m 18s ⏱️ +2s
1 067 tests ±0  1 067 ✅ ±0  0 💤 ±0  0 ❌ ±0 
1 123 runs  ±0  1 123 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 3891d9f. ± Comparison against base commit bb5e825.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

792 tests  ±0   791 ✅ ±0   5m 43s ⏱️ +34s
 12 suites ±0     1 💤 ±0 
 12 files   ±0     0 ❌ ±0 

Results for commit 3891d9f. ± Comparison against base commit bb5e825.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

715 tests  ±0   611 ✅ ±0   5m 41s ⏱️ +22s
 10 suites ±0   104 💤 ±0 
 10 files   ±0     0 ❌ ±0 

Results for commit 3891d9f. ± Comparison against base commit bb5e825.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

2 227 tests  ±0   2 039 ✅ ±0   4m 36s ⏱️ -54s
   12 suites ±0     188 💤 ±0 
   12 files   ±0       0 ❌ ±0 

Results for commit 3891d9f. ± Comparison against base commit bb5e825.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

1 297 tests  ±0   1 293 ✅ ±0   5m 9s ⏱️ +13s
   11 suites ±0       4 💤 ±0 
   11 files   ±0       0 ❌ ±0 

Results for commit 3891d9f. ± Comparison against base commit bb5e825.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

904 tests  ±0   898 ✅ ±0   4m 45s ⏱️ +40s
  4 suites ±0     6 💤 ±0 
  4 files   ±0     0 ❌ ±0 

Results for commit 3891d9f. ± Comparison against base commit bb5e825.

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

   60 files  ±0     60 suites  ±0   30m 16s ⏱️ +59s
7 002 tests ±0  6 699 ✅ ±0  303 💤 ±0  0 ❌ ±0 
7 058 runs  ±0  6 755 ✅ ±0  303 💤 ±0  0 ❌ ±0 

Results for commit 3891d9f. ± Comparison against base commit bb5e825.

@rbuergi
rbuergi merged commit 1d57e82 into main Jul 19, 2026
16 checks passed
@rbuergi
rbuergi deleted the fix/multiarch-refasm-race branch August 5, 2026 10:45
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