Skip to content

fix(build): stable AssemblyVersion — cures the migration binding crash (#143) - #144

Merged
rbuergi merged 1 commit into
mainfrom
fix/stable-assemblyversion-143
Jul 1, 2026
Merged

rbuergi merged 1 commit into
mainfrom
fix/stable-assemblyversion-143

Conversation

@rbuergi

@rbuergi rbuergi commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Fixes #143.

Symptom

Space creation fails on prod: "database schema issue on the backend (sync_behavior column missing)". The memex-migration container CrashLoopBackOffs on startup:

Current DB version: 39
System.IO.FileNotFoundException: Could not load file or assembly
'MeshWeaver.Documentation, Version=3.0.0.280' — the system cannot find the file.

So the schema never advances past v39, the sync_behavior migration (PR #119) never applies, and Space creation fails. (The portals on the same ci.122 build run fine — only the migration image hit it.)

Root cause

Directory.Build.props set AssemblyVersion = $(_VersionNumeric).$(_BuildNumber), where _BuildNumber is seconds-since-midnight ÷ 2, evaluated per project at MSBuild time. AssemblyVersion is the runtime assembly-binding identity — it must be identical across every assembly in a coherent build. A time-based value drifts a few seconds between projects built in the same CI run, so Memex.Database.Migration was compiled against MeshWeaver.Documentation v3.0.0.280 while the packaged DLL carried a different 3.0.0.<other> → binding fails → crash before applying v40.

Fix

  • AssemblyVersion → stable $(_VersionNumeric).0 (3.0.0.0).
  • FileVersion keeps the per-build number (drives MSBuild's copy heuristic; does not participate in binding).

Safe against everything documented in that file: the self-updater keys on the image tag (ci.N), NodeType ABI identity uses the Graph MVID — neither uses AssemblyVersion. And it only ever bit CI: local builds already set _BuildNumber=0, so AssemblyVersion was already 3.0.0.0 locally — this makes CI match the already-correct local behavior.

Validation

dotnet build memex/aspire/Memex.Database.Migration -c Release -p:CIRun=true succeeds, and the generated AssemblyInfo for both the migration and MeshWeaver.Documentation now reads AssemblyVersion("3.0.0.0") (previously they drifted). After merge → CD rebuilds → the migration runs → v40 (sync_behavior) applies → Space creation works.

🤖 Generated with Claude Code

#143)

Space creation was failing on prod ("sync_behavior column missing", #143) because
the memex-migration container CrashLoopBackOff'd on startup:

    Current DB version: 39
    System.IO.FileNotFoundException: Could not load file or assembly
    'MeshWeaver.Documentation, Version=3.0.0.280' — the system cannot find the file.

Root cause: AssemblyVersion was `$(_VersionNumeric).$(_BuildNumber)` where
`_BuildNumber` is seconds-since-midnight/2, evaluated PER PROJECT at MSBuild time.
AssemblyVersion is the runtime assembly-BINDING identity, so it must be identical
across every assembly in a coherent build — but a time-based value drifts a few
seconds between projects built in the same CI run. Memex.Database.Migration was
compiled against MeshWeaver.Documentation v3.0.0.280 while the packaged DLL carried
a different 3.0.0.<other> → binding fails → the migration crashes before it can
apply the v40 (sync_behavior) migration → schema stuck at v39 → #143.

Fix: AssemblyVersion is now STABLE (`$(_VersionNumeric).0` = 3.0.0.0). FileVersion
keeps the per-build number (that + build timestamps drive MSBuild's
CopyToOutputDirectory heuristic; it does not participate in assembly binding).
Nothing depends on a time-based AssemblyVersion: the self-updater keys on the image
tag (ci.N) and NodeType ABI identity uses the Graph MVID.

Note this only ever bit CI: LOCAL builds already set `_BuildNumber=0`, so
AssemblyVersion was already 3.0.0.0 locally — the fix simply makes CI match the
already-correct local behavior.

Validated: `dotnet build Memex.Database.Migration -c Release -p:CIRun=true`
succeeds and the generated AssemblyInfo for both the migration and
MeshWeaver.Documentation now reads AssemblyVersion("3.0.0.0").

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

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 fixes a production migration startup crash caused by inconsistent AssemblyVersion values across projects within the same CI build, which broke runtime assembly binding and prevented database migrations from applying (leaving the schema stuck before the sync_behavior column migration).

Changes:

  • Makes AssemblyVersion stable across all assemblies ($(_VersionNumeric).0) to ensure consistent runtime binding identity.
  • Keeps per-build variability in FileVersion (and CI-only uniqueness in InformationalVersion) so build outputs still change between CI runs without affecting binding.

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

@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

1 275 tests  ±0   1 275 ✅ ±0   3m 50s ⏱️ -9s
   12 suites ±0       0 💤 ±0 
   12 files   ±0       0 ❌ ±0 

Results for commit 88306e0. ± Comparison against base commit 6943991.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

   12 files  ± 0     12 suites  ±0   6m 15s ⏱️ +40s
1 111 tests +19  1 108 ✅ +19  3 💤 ±0  0 ❌ ±0 
1 112 runs  +19  1 109 ✅ +19  3 💤 ±0  0 ❌ ±0 

Results for commit 88306e0. ± Comparison against base commit 6943991.

This pull request removes 12 and adds 31 tests. Note that renamed tests count towards both.
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/Analysis", expectedPrefix: "FutuRe/Analysis", expectedRemainder: null)
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/EuropeRe", expectedPrefix: "FutuRe/EuropeRe", expectedRemainder: null)
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/EuropeRe/LineOfBusiness", expectedPrefix: "FutuRe/EuropeRe/LineOfBusiness", expectedRemainder: null)
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/EuropeRe/Overview", expectedPrefix: "FutuRe/EuropeRe", expectedRemainder: "Overview")
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuRe_ShouldNotReturnNull
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_UnknownDeepPath_ShouldReturnNull
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ BareBlocks_AreDocumentationOnly
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ ExecutableCodeBlocks_AreExtractedFromMarkdown
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ KernelAddressPlaceholder_IsEmbeddedInRenderedHtml
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ KernelAddressPlaceholder_IsReplacedWithActualAddress
…
MeshWeaver.Hosting.Monolith.Test.FileSystemStreamProviderTests ‑ GetStreamAsync_ExistingFile_ReturnsStream
MeshWeaver.Hosting.Monolith.Test.FileSystemStreamProviderTests ‑ GetStreamAsync_NonExistentFile_ReturnsNull
MeshWeaver.Hosting.Monolith.Test.FileSystemStreamProviderTests ‑ ProviderType_ReturnsFileSystem
MeshWeaver.Hosting.Monolith.Test.FileSystemStreamProviderTests ‑ WriteStreamAsync_CreatesDirectory
MeshWeaver.Hosting.Monolith.Test.FileSystemStreamProviderTests ‑ WriteStreamAsync_CreatesFile
MeshWeaver.Hosting.Monolith.Test.LinkedInPullActionsTest ‑ LinkedInPullActions_CompilesAndRendersNoCredentialBranch
MeshWeaver.Hosting.Monolith.Test.MeshNodeLanguageServiceTest ‑ CheckSpeculative_AddsNuGetReferenceDirective_ResolvesAndCompiles
MeshWeaver.Hosting.Monolith.Test.MeshNodeLanguageServiceTest ‑ GetCompletions_AfterMemberAccessDot_ReturnsTypeMembers
MeshWeaver.Hosting.Monolith.Test.MeshNodeLanguageServiceTest ‑ GetHover_OnPropertyInsideRecord_ReturnsMarkdown
MeshWeaver.Hosting.Monolith.Test.NodeTypeReleaseGateTest ‑ CompileFailure_LeavesNoReleaseNode
…

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

927 tests  ±0   926 ✅ ±0   7m 7s ⏱️ -3s
 13 suites ±0     1 💤 ±0 
 13 files   ±0     0 ❌ ±0 

Results for commit 88306e0. ± Comparison against base commit 6943991.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

1 919 tests  +657   1 914 ✅ +652   7m 54s ⏱️ + 6m 2s
   13 suites +  1       5 💤 +  5 
   13 files   +  1       0 ❌ ±  0 

Results for commit 88306e0. ± Comparison against base commit 6943991.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Jul 1, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

   50 files  +  1     50 suites  +1   25m 7s ⏱️ + 6m 29s
5 232 tests +676  5 223 ✅ +671  9 💤 +5  0 ❌ ±0 
5 233 runs  +676  5 224 ✅ +671  9 💤 +5  0 ❌ ±0 

Results for commit 88306e0. ± Comparison against base commit 6943991.

This pull request removes 12 and adds 688 tests. Note that renamed tests count towards both.
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/Analysis", expectedPrefix: "FutuRe/Analysis", expectedRemainder: null)
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/EuropeRe", expectedPrefix: "FutuRe/EuropeRe", expectedRemainder: null)
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/EuropeRe/LineOfBusiness", expectedPrefix: "FutuRe/EuropeRe/LineOfBusiness", expectedRemainder: null)
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuReSubPaths_ShouldResolve(path: "FutuRe/EuropeRe/Overview", expectedPrefix: "FutuRe/EuropeRe", expectedRemainder: "Overview")
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_FutuRe_ShouldNotReturnNull
MeshWeaver.Persistence.Test.ApplicationPageResolutionTest ‑ ResolvePathAsync_UnknownDeepPath_ShouldReturnNull
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ BareBlocks_AreDocumentationOnly
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ ExecutableCodeBlocks_AreExtractedFromMarkdown
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ KernelAddressPlaceholder_IsEmbeddedInRenderedHtml
MeshWeaver.Persistence.Test.InteractiveMarkdownHelperTest ‑ KernelAddressPlaceholder_IsReplacedWithActualAddress
…
MeshWeaver.AI.Test.ActivityLogStreamTest ‑ Progress_Messages_Stream_Gradually_Not_Just_At_The_End
MeshWeaver.AI.Test.ActivityLogStreamTest ‑ Script_Failure_Flips_ActivityLog_Status_To_Failed
MeshWeaver.AI.Test.ActivityLogStreamTest ‑ Script_Log_Messages_Land_On_ActivityLog_Node
MeshWeaver.AI.Test.AgentChatClientDeadlockTest ‑ GetOrderedAgentsAsync_WithContextPath_ConcurrentCallers_DoNotDeadlock
MeshWeaver.AI.Test.AgentChatClientDeadlockTest ‑ GetOrderedAgentsAsync_WithContextPath_SingleCaller_ResolvesQuickly
MeshWeaver.AI.Test.AgentChatClientDeadlockTest ‑ GetOrderedAgentsAsync_WithMarkdownContext_DoesNotDeadlock
MeshWeaver.AI.Test.AgentChatClientTest ‑ AgentChatClient_Initialize_SurfacesPartitionAgents_NotNodeTypeNamespaceAgents
MeshWeaver.AI.Test.AgentChatClientTest ‑ AgentChatClient_Initialize_SurfacesPlatformAgentsForAnyContext
MeshWeaver.AI.Test.AgentChatClientUnitTest ‑ FindCyclicDelegations_Chain_ReturnsEmpty
MeshWeaver.AI.Test.AgentChatClientUnitTest ‑ FindCyclicDelegations_DelegationsWithNoMatchingTarget_ReturnsEmpty
…

♻️ This comment has been updated with latest results.

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.

Database schema issue on the backend (sync_behavior column missing) preventing Space creation

2 participants