fix(deploy): the image can never ship without the Blazor script #285
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/image-blazor-script-guard"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This makes sure the image always has
blazor.web.js, whatever order the restores run in, and makes the image build fail if the script is ever missing.Kagura isn't broken today. This is insurance against a failure that has already hit a sibling project.
What's in
src/Kagura.Server/Kagura.Server.csprojnow sets<RequiresAspNetWebAssets>true</RequiresAspNetWebAssets>, with a comment explaining why. On SDK 10.0.4xx (whatmcr.microsoft.com/dotnet/sdk:10.0carries now, 10.0.402 locally),Microsoft.NET.Sdk.Web.ProjectSystem.targetsonly sets this property when the project's own.razorContent items are visible at restore time. Only then does it restoreMicrosoft.AspNetCore.App.Internal.Assets, the pack that carriesblazor.web.js. The Dockerfile's first restore runs on the project files alone, so no.razorfiles are visible at that point. Setting the property explicitly removes the dependency on restore order.deploy/Dockerfilenow runsRUN test -f /app/publish/wwwroot/_framework/blazor.web.jsright after thedotnet publishstep. Without the script, the app renders but nothing on it responds. The access gate also turns the missing asset into a redirect instead of a 404, so nothing shows up as an error. With the check, CI's image job fails at build time instead.This is the same failure Shikigami's image hit. Its Dockerfile has the same restore-from-project-files layer, but it publishes with
--no-restore, so it shipped without the script. Kagura survives only because itsdotnet publishrestores again once the source is copied in, and that second restore pulls the pack. Adding one--no-restorewould bring the same silent failure here. The Dockerfile is otherwise unchanged.Verified
dotnet build src/Kagura.Server/Kagura.Server.csproj -m:1 -nodeReuse:falsefinished with 0 warnings and 0 errors.podman build -f deploy/Dockerfile -t kagura-guard-check --build-arg APP_VERSION=0.0.0-guard.0 .on the currentsdk:10.0(10.0.402) succeeded, so the new guard step passed./app/wwwroot/_framework/blazor.web.js(with its.brand.gzversions) is in the runtime image. The image was removed afterwards.🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagura.BlazorAdapter - 89.7%
Kagura.Domain - 94.8%
D04ADFED3A21D401C2764A1D17367E35BEB556CBB3B4B0B74__NonSlugChars_0
Kagura.Infrastructure - 97.7%
n
n
on
ng
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ArtifactTimestampRegex_2
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__ProjectRoute_0
C689CA5BBE6D1849B2CA79581BBB07D40636D85790C0E51A9__TabQuery_1
Kagura.Kernel - 90%
Kagura.Server - 81.5%
Kagura.UseCases - 95.5%
🔮 fufu~ Jibril reviewed your code!
Deploy-insurance PRs are my favorite kind of treat — nothing looks broken, everything works, and the only way to know if the umbrella actually opens is to stand in the rain~ ♡ So I stood in the rain. Mechanically.
Verdict: ✅ Looks good to me~
🔬 What I verified (with real probes, not vibes~)
The property name and mechanism, against the SDK itself. In
Microsoft.NET.Sdk.Web.ProjectSystem/targets(sandbox SDK 10.0.401, same 10.0.4xx band assdk:10.0):RequiresAspNetWebAssetsis set totrueonly when'$(RequiresAspNetWebAssets)' == ''and the project's own@(Content)includes a.razor— exactly what the csproj comment claims. The explicit setting wins the== ''guard, so it's authoritative regardless of restore order. The comment is not just plausible, it's quotation-accurate. Oh? Oh! This is wonderful~Mutation probe — I deleted your fix and reproduced the silent failure. Removed the property, replicated the image's first restore layer (Server's
.razorfiles invisible —findconfirmed 0 visible), restored, then published with--no-restoreand full source present (Shikigami's exact move). Result: build green,blazor.web.jsmissing,wwwroot/_framework/absent entirely. The app would render and nothing would respond — precisely the corpse you described. And your guardRUN test -f /app/publish/wwwroot/_framework/blazor.web.jsfails exactly there. The guard is load-bearing, not decoration~Fix probe — same hostile geometry, property restored. With the
.razorfiles still hidden at restore time,Microsoft.AspNetCore.App.Internal.Assets >= 10.0.12is in the restore graph, and a--no-restorepublish producesblazor.web.js(+.br/.gz, plusblazor.server.js) at exactlywwwroot/_framework/blazor.web.js— the guard's path is character-exact, no fingerprinting surprises.Sibling consistency:
Kagura.Serveris the onlyMicrosoft.NET.Sdk.Webproject in the repo (src/ and external/ both checked), and there's exactly one Dockerfile, publishing exactly this project. The property couldn't belong anywhere else~💡 Little ideas (non-blocking~)
docker-publish.ymldoesn't trigger onpull_request(push main/tags +workflow_dispatchonly), andci.ymlnever runsdotnet publish. So a PR that regressed this would first exercise the guard at the post-merge main build. The workflow already supports dispatching a branch build on demand — if you want pre-merge proof on this exact tree, aworkflow_dispatchrun of this branch would do it. Optional~✅ What I liked~
Directory.Build.props.Fufu~ an umbrella verified by standing in the rain. Approved~ ♡
Automated review by Jibril · 2026-10-18
CI: green for head SHA
de5812ab· Mutation probes: 2 run, 0 survived (mutant killed by the guard; fix verified under hostile restore geometry) · Local suite: skipped (CI green)