Shrink the FwHeadless image and run ChorusMerge on .NET 10 - #2611
Conversation
…runtime ChorusMerge ships only a net8.0 build, so its runtimeconfig requests Microsoft.NETCore.App 8.0.0. Previously the FwHeadless image copied the whole .NET 8 shared framework (and fxr host) from a runtime:8.0 stage to satisfy that. Instead, set DOTNET_ROLL_FORWARD=Major in the chorusmerge wrapper so it rolls forward onto the .NET 10 shared framework already present in the aspnet:10.0 base image. Scoped to the wrapper so FwHeadless itself is unaffected. Drops the dotnet8 build stage and its two COPY lines. Verified: the image builds without the net8 runtime and the in-image chorusmerge smoke test performs a real 3-way FieldWorks merge on .NET 10. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The FixFwData and chorusmerge smoke tests previously ran in the final (shipped) stage, leaving build-only artifacts in the runtime image: the 1.47MB test-template-repo.zip fixture (COPYd then deleted in a later layer, so never reclaimed) plus the FixFwData smoke RUN's temp churn. Split the runtime contents into a `runtime` stage, run both smoke tests in a `smoketest` stage derived from it, and produce `final` from `runtime` with a 0-byte marker COPYd from `smoketest`. The marker forces buildkit to build (and therefore pass) the smoke tests before the image is produced, so they still gate the build — the shipped image just no longer carries their fixtures or churn. ~10MB smaller (990MB -> 980MB). Also moved `chmod +x FixFwData` into the runtime stage (it used to live in the smoke RUN); FixFwData is shelled out to at runtime by liblcm, so its exec bit must survive in the shipped image. python3 stays: the bundled Linux hg is a python3 script and needs it for Send/Receive. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The bundled Linux hg is a python3 script that loads native modules (zstd, etc.); a missing python3 or broken native asset would break every Send/Receive but wouldn't surface until runtime. Run `hg version` in the smoketest stage and assert its banner, so a broken Mercurial fails the build instead. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The SIL.Chorus.Mercurial build targets (CopyFiles) stage the runtimes/<rid>/native/Mercurial tree into the project's Mercurial/ folder, which ships to the image via the existing Content Include and is the copy the app actually uses (mercurial.ini fixup, hg exec bit, and Chorus's hg lookup all target /app/Mercurial). Publish was ALSO copying the same tree under runtimes/, so every image carried Mercurial twice. ExcludeAssets="native" on the package reference drops the runtimes/ native copy from publish while leaving the build targets (build assets) importing, so CopyFiles still stages Mercurial/. Removes ~108MB of duplicate linux-x64 Mercurial plus the never-used win Mercurial native tree: image 990MB -> 757MB. Smoke tests (hg version, chorusmerge, FixFwData) still pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A portable (no-RID) publish copies runtimes/ native assets for every RID (win, osx, android, ios, riscv64, s390x, ppc64le, ...), none of which a linux-x64 container can load. Publish RID-specific but framework-dependent (-r linux-x64 --no-self-contained, still relying on the base image's shared framework) so only linux-x64 natives (and unix managed fallbacks like System.Private.ServiceModel) ship, flattened into the app root. This was previously blocked by NETSDK1152: RID publish flattens the SIL.Chorus.Mercurial native tree into the output, colliding with the Content-copied Mercurial/. The prior commit's ExcludeAssets="native" removes that native copy, so the collision is gone. Image 757MB -> 618MB (372MB / 38% below the pre-cleanup 990MB). Verified: all three smoke tests pass, native libs (libe_sqlite3.so, libMono.Unix.so) and the unix ServiceModel fallback land at the app root, and FwHeadless boots through DI/config binding (fails only on absent runtime config, no assembly/native load errors). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
SIL.Chorus.Mercurial bundles its compiled extension modules (zstd et al.) for Python 3.8-3.13, but the runtime image has a single python3 (Debian's 3.12) and hg only ever loads the matching cpython ABI set. The other five versions were ~45MB of dead native code. Copy the published app in via a bind mount and, in the same layer, delete every Mercurial *.cpython-3*.so whose ABI tag doesn't match the live python3 — pruning during the copy so the space is actually reclaimed rather than hidden under a whiteout. Keyed to the running python3 so a future base-image Python bump keeps the correct set by construction. Upgrade the hg smoke test from `hg version` to `hg debuginstall`, which loads the extension modules and verifies the compression engines (zstd, zlib, ...); a mis-pruned ABI set now fails the build instead of surfacing at Send/Receive time. Image 618MB -> 570MB. All three smoke tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
No image built from the backend/ context compiles a test project — each Dockerfile (LexBoxApi, FwHeadless) builds a single app csproj via its ProjectReference graph, and the only Testing dependency (the test-template-repo.zip fixture) is already whitelisted. Yet the *.Tests projects' snapshot data (~20MB of *.verified.txt) dominated the ~30MB context, and because both Dockerfiles do `COPY . .`, any edit to a test snapshot invalidated the image build cache and forced a full rebuild + smoke tests. Excluding **/*.Tests cuts the context to ~6.5MB and decouples the image builds from test-data churn. FwHeadless still builds and all smoke tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reachedNext included review available in 59 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Team Run ID: 📒 Files selected for processing (4)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Is USER root needed in the smoketest stage? It inherits www-data from runtime, so dropping that line would make the three smoke tests run as the same user the app runs as and a file www-data cannot read or write would fail the build instead of production. If it was added intentionally, a comment saying so might be good.
we can remove .net 8 from fw-headless by making chorus merge roll forward major. I also worked on trimming down the docker image from 990MB to 570MB!
🤖 AI summary
Shrinks the FwHeadless Docker image from 990MB → 570MB (~42%) and drops the bundled second .NET runtime, plus trims the build context from ~30MB → ~6.5MB. Each change is its own commit and every image build is gated by the in-image smoke tests.
chorusmergewrapper now setsDOTNET_ROLL_FORWARD=Majorso it runs on the shared framework already in the base image, removing the bundled .NET 8 runtime.finalstage (into asmoketeststage gated by a marker COPY), so their fixtures and churn no longer ship.ExcludeAssets="native"onSIL.Chorus.Mercurialdrops theruntimes/.../Mercurialcopy that duplicated the Content-stagedMercurial/the app actually uses (~108MB, incl. the never-used Windows tree).-r linux-x64 --no-self-contained) — prunesruntimes/native assets for every other RID (win, osx, android, ios, …) while staying framework-dependent.python3ABI is kept, pruned during the copy so the space is reclaimed. The hg smoke test was upgraded fromhg versiontohg debuginstall(verifies the compression modules load).**/*.Testsexcluded from thebackend/context: no image builds a test project, and viaCOPY . .test-snapshot edits previously invalidated the image cache.Follow-up (not in this PR): the Mercurial double-ship and the six-Python bundling both originate in
SIL.Chorus.Mercurialpackaging and are worth an upstream issue atsillsdev/Mercurial4Chorus;ExcludeAssets="native"+ the module prune are the consumer-side workarounds.Test plan
docker buildofbackend/FwHeadless/Dockerfilesucceeds; the three build-time smoke tests gate it and pass:hg debuginstall(Mercurial + compression modules load), chorusmerge (real 3-way FieldWorks merge preserves both edits), FixFwData (publish co-located correctly).libe_sqlite3.so,libMono.Unix.so) and theunixSystem.Private.ServiceModel.dllfallback land at the app root; only the live-python3Mercurial modules remain.