From 56c1b658bb8ef80f91d8ff0f4466cb6702316916 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 25 May 2026 18:11:46 +0000 Subject: [PATCH] Vendor Bootsharp build pipeline: one script, one doc, no stash dependency MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the scattered build prose (CLAUDE.md disagreed with BOOTSHARP-BUILD.md on which Bootsharp branch is current — neither said `feat/spec`) with a single PowerShell script that runs the full rebuild end-to-end. Every fresh agent session was burning hours rediscovering this; that stops here. What changed: - scripts/build-bootsharp.ps1: 11-step pipeline (sanity-check, reset, apply patches/*.patch in order, bump alpha, pack core + FileSystem, purge NuGet cache, XML-edit Directory.Packages.props pins, dotnet publish Motely.Wasm, run Node smoke tests, summarize). `-WhatIf` walks every step without executing. Path/tool checks downgrade to warnings under -WhatIf so a fresh agent can dry-run on a machine without the toolchain. - patches/02-publish-fixes.patch: renamed from bootsharp-fixes-vs-6edaa2c.patch (content byte-identical, three-commit series unchanged). Script applies it. - patches/01-projectability.patch.PLACEHOLDER: surfaces the missing piece — the projectability fix currently lives only as a stash on the maintainer's Windows machine. One-time export command is in the placeholder; replace with the real patch and the script picks it up automatically. - BOOTSHARP-BUILD.md: rewritten as sole source of truth. TL;DR points at the script; troubleshooting table maps actual error strings to causes/fixes. - CLAUDE.md: build-pipeline section collapsed to a 5-line pointer at the script. All `@D:/bootsharp/...` ambient-context @-refs removed (they only resolve on the maintainer's machine and prevented remote agents from reading them anyway). Everything else in CLAUDE.md kept. --- BOOTSHARP-BUILD.md | 161 ++++++----- CLAUDE.md | 85 +----- patches/01-projectability.patch.PLACEHOLDER | 39 +++ .../02-publish-fixes.patch | 0 scripts/build-bootsharp.ps1 | 273 ++++++++++++++++++ 5 files changed, 399 insertions(+), 159 deletions(-) create mode 100644 patches/01-projectability.patch.PLACEHOLDER rename bootsharp-fixes-vs-6edaa2c.patch => patches/02-publish-fixes.patch (100%) create mode 100644 scripts/build-bootsharp.ps1 diff --git a/BOOTSHARP-BUILD.md b/BOOTSHARP-BUILD.md index f2511a83..27cf1a4c 100644 --- a/BOOTSHARP-BUILD.md +++ b/BOOTSHARP-BUILD.md @@ -1,117 +1,120 @@ -# Bootsharp Local Build Process +# Bootsharp local build pipeline -Run these steps IN ORDER every time Elringus pushes upstream changes or you need a fresh local build. +This is the **only** doc for rebuilding Bootsharp locally. If anything else (CLAUDE.md, agent memory, a comment somewhere) disagrees, this file wins — open a PR to fix the other. ---- - -## 1. D:\bootsharp (core package) - -Elringus **force-pushes** `feat/overload`. Never merge. Never stash. Always reset hard. +## TL;DR ```powershell -git -C D:\bootsharp fetch -git -C D:\bootsharp reset --hard origin/feat/overload - -# Reapply the projectability patch (GlobalType.cs + TypeInspector.cs) -# Check label first — stash index shifts if GitHub Desktop adds entries: -git -C D:\bootsharp stash list -git -C D:\bootsharp stash apply stash@{N} -# Look for: "On feat/overload: !!GitHub_Desktop" +pwsh ./scripts/build-bootsharp.ps1 ``` -Bump version in `D:\bootsharp\src\cs\Directory.Build.props`: -```xml -0.8.0-alpha.NNN -``` +That's the build. The script does everything: resets Bootsharp to upstream, applies the patch series under `patches/`, bumps the alpha, packs core + Bootsharp.FileSystem to their local NuGet feeds, bumps the pins in `Directory.Packages.props`, publishes `Motely.Wasm`, and runs the Node smoke tests. Green or red. -Build JS then pack C#: -```powershell -npm --prefix D:\bootsharp\src\js run build -bash D:\bootsharp\src\cs\.scripts\pack.sh # outputs to D:\bootsharp\src\cs\.nuget\ -``` +Run `pwsh ./scripts/build-bootsharp.ps1 -WhatIf` first if you want to see every command without executing. -Optional E2E (slow, catches regressions in the generator): -```powershell -npm --prefix D:\bootsharp\src\js run compile-test -npm --prefix D:\bootsharp\src\js run test -``` +## What the script does (11 steps) -> **The patch** skips non-projectable interop members (ref structs, byref T&, delegates, -> bare IEnumerable) and drops imported interfaces that have any such member. -> Lives in `Common/Global/GlobalType.cs` and `Common/Inspection/TypeInspector.cs`. +1. **Sanity-check tooling** — git, dotnet, node, npm, bash all on PATH. +2. **Reset `D:\bootsharp` to `origin/feat/spec`** — `fetch --all --prune` then `reset --hard`. Force-pushed upstream, never merge. Refuses to continue if tracked-file changes remain. +3. **Apply `patches/*.patch` in lexical order** — `git apply --check` then `git apply`. Hard failure if a patch doesn't apply — that means it's stale vs. upstream and needs hand-rebasing (which is also the cue to send Elringus a PR). +4. **Bump `` in `D:\bootsharp\src\cs\Directory.Build.props`** — increments the NNN in `0.8.0-alpha.NNN`. Override with `-AlphaBumpMode none` or `-AlphaBumpMode `. +5. **Build JS, then pack C#** — `npm --prefix src/js run build`, then `bash src/cs/.scripts/pack.sh`. Output lands in `D:\bootsharp\src\cs\.nuget`. +6. **Pack Bootsharp.FileSystem** — `dotnet pack D:\extra\bootsharp\cs -c Release -o D:\extra\bootsharp\cs\.nuget`. Version is auto-generated from the current timestamp (`yyyy.MM.dd.HHmm`). +7. **Purge the NuGet user cache** for the new alpha + new FileSystem timestamp, so the consumer restore doesn't serve a stale entry. +8. **Bump pins in `Directory.Packages.props`** — XML-edit (preserves formatting) of `Bootsharp`, `Bootsharp.Common`, `Bootsharp.Inject` → new alpha and `Bootsharp.FileSystem` → new timestamp. +9. **`dotnet publish Motely.Wasm -c Release`** — produces `motely-wasm/dist`. +10. **Smoke** — `node Motely.Wasm/motely.test.mjs` and `node Motely.Wasm/getctx-wasm.test.mjs`. Skip with `-SkipSmoke`. +11. **Summary** — versions, feed paths, `RESULT: PASS`. ---- +## Branch and feed setup (one-time) -## 2. D:\extra\bootsharp (Bootsharp.FileSystem — $100/mo sponsor package) +| Repo | Local path | Branch | Local feed | +|---|---|---|---| +| Bootsharp core | `D:\bootsharp` | `feat/spec` (force-pushed) | `D:\bootsharp\src\cs\.nuget` | +| Bootsharp.FileSystem (sponsor) | `D:\extra\bootsharp` | — (timestamp-versioned) | `D:\extra\bootsharp\cs\.nuget` | -Pack to local NuGet only. **Do NOT run `publish.sh`** — that pushes to the rewaffle remote feed (Elringus's job). +Register both feeds in your **user-level** `NuGet.Config` (`%APPDATA%\NuGet\NuGet.Config` on Windows). The repo's `nuget.config` deliberately omits `` so these merge in: -```powershell -dotnet pack D:\extra\bootsharp\cs --configuration Release --output D:\extra\bootsharp\cs\.nuget +```xml + + + + + + ``` -Version is auto-generated from the current timestamp (`yyyy.MM.dd.HHmm`). -Check the exact filename produced — you'll need it for the next step: +Override the paths if your checkouts live elsewhere: + ```powershell -ls D:\extra\bootsharp\cs\.nuget\Bootsharp.FileSystem.*.nupkg +pwsh ./scripts/build-bootsharp.ps1 ` + -BootsharpRoot C:\src\bootsharp ` + -BootsharpFsRoot C:\src\bootsharp-filesystem ``` -It resolves `Bootsharp.Common Version="*-*"` (floating) → picks up the alpha you just packed. +## Patch series ---- +The series lives under `patches/` and is the canonical record of every Bootsharp delta Motely needs that hasn't landed upstream yet. Two files today: -## 3. x:\JammySeedFinder\src\MotelyJAML — update pins +### `patches/01-projectability.patch` -Edit `Directory.Packages.props` with the new versions: -```xml - - - - -``` +Status today: **not yet vendored** — exists as a placeholder (`patches/01-projectability.patch.PLACEHOLDER`) until the maintainer exports the local stash. Until that's done, `dotnet publish Motely.Wasm` will fail when the inspector hits a non-projectable interop member. + +Touches: `src/cs/Bootsharp.Common/Global/GlobalType.cs`, `src/cs/Bootsharp.Common/Inspection/TypeInspector.cs`. + +Effect: skips non-projectable interop members (ref structs, byref `T&`, delegates, bare `IEnumerable`) and drops imported interfaces that have any such member. ---- +Smallest test it must pass: `dotnet publish Motely.Wasm -c Release` succeeds. Failure mode without it: the publish-time inspector throws on Motely's `MotelySingleSearchContext` and friends. -## 4. Build Motely.Wasm +One-time export (run on the machine that has the stash): ```powershell -dotnet publish x:\JammySeedFinder\src\MotelyJAML\Motely.Wasm -c Release +cd D:\bootsharp +git stash list # find "On feat/spec: !!GitHub_Desktop" +git stash show -p stash@{N} ` + > X:\JammySeedFinder\src\MotelyJAML\patches\01-projectability.patch +# then delete patches/01-projectability.patch.PLACEHOLDER ``` -Success looks like: -``` -Bootsharp ES module published at x:\JammySeedFinder\src\MotelyJAML\..\motely-wasm\dist -``` +### `patches/02-publish-fixes.patch` ---- +Three-commit series against `Bootsharp.Publish`. Without it the package doesn't even compile against Motely's surface. -## 5. Verify +- **Commit 1** — `TypeDeclarationGenerator.cs`: migrate to the post-`6edaa2c` `SolutionInspection.Surfaces` / `.Types` split. Members now live on `InstanceMeta` (the surface), not `InstancedMeta` (the type). +- **Commit 2** — `InstanceGenerator.cs`: qualify the runtime root with `global::Bootsharp.*` everywhere in the emit template (otherwise the generated wrapper namespace `Bootsharp.Generated.Imports.Bootsharp.FileSystem` shadows the root); rename `JSImported` → `JSProxy` to match the runtime API. +- **Commit 3** — `SurfaceInspector.cs`: unwrap `Task` before instance inspection. Mirrors `SerializedInspector`. Without it the inspector recurses into `Task`'s public methods and emits invalid `JSConfiguredTaskAwaitable\`1` proxies. -```powershell -node x:\JammySeedFinder\src\MotelyJAML\Motely.Wasm\motely.test.mjs -node x:\JammySeedFinder\src\MotelyJAML\Motely.Wasm\pack-consumer-smoke.mjs -``` +Smallest tests it must pass: -Both must exit clean. +- `dotnet build` on `D:\bootsharp\src\cs\Bootsharp.Publish` succeeds (commit 1 unblocks compile). +- The Bootsharp E2E suite (`npm --prefix src/js run compile-test`) emits no class containing a backtick in its name (commit 3). +- `dotnet publish Motely.Wasm -c Release` succeeds and `node Motely.Wasm/motely.test.mjs` exits 0 (commit 2). ---- +## Troubleshooting -## NuGet cache gotcha +| Error you'll actually see | Cause | Fix | +|---|---|---| +| `CS0234: 'JSImported' does not exist in the namespace 'Bootsharp.Generated.Imports.Bootsharp'` | `patches/02-publish-fixes.patch` not applied | Re-run script; check step 3 log for the `--check` failure | +| Generated emit contains `JSConfiguredTaskAwaitable\`1` | `patches/02` partial apply (commit 3 missing) | Re-apply the whole series (delete `D:\bootsharp` working changes and re-run) | +| `Bootsharp.Common` resolves to a stale alpha | NuGet cache hit | Re-run the script (step 7 purges); or manually `Remove-Item -Recurse $env:USERPROFILE\.nuget\packages\bootsharp*` | +| `NETSDK1083: The specified RuntimeIdentifier 'browser-wasm' is not recognized` | Missing wasm-tools workload | `dotnet workload install wasm-tools` | +| `node motely.test.mjs` prints `{}` instead of populated data | Bootsharp marshaling regression (see CLAUDE.md "Interop debugging rules") | Assert shape, not just "didn't throw"; check that every `[Export]`-ed type in `Program.cs` is projectable | +| The publish-time Bootsharp inspector throws on a `ref struct` / delegate / bare `IEnumerable` | `patches/01-projectability.patch` not yet vendored | Export the stash (see § Patch series) | +| `Bootsharp.FileSystem` package not found at restore | `D:\extra\bootsharp\cs\.nuget` not registered as a feed | Add it to the user-level `NuGet.Config` (see § Branch and feed setup) | -If you reuse the same version number, NuGet serves the cached old package. Purge it: -```powershell -Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp\0.8.0-alpha.NNN" -Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.common\0.8.0-alpha.NNN" -Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.inject\0.8.0-alpha.NNN" -``` +## Upstreaming ---- +The maintainer sponsors Elringus at the $100 tier. When `patches/02-publish-fixes.patch` rebases cleanly against `feat/spec` HEAD and the smoke tests pass, send Elringus a PR for the three commits — the patch file's commit messages and author trailers are already in the right shape (`git am patches/02-publish-fixes.patch` will replay them). Same for `01-projectability.patch` once it's vendored. -## Local NuGet feed locations +When a patch lands upstream, delete the file from `patches/`. The script applies whatever's there — none means none. -| Package | Feed path | -|---|---| -| Bootsharp.* (core) | `D:\bootsharp\src\cs\.nuget\` | -| Bootsharp.FileSystem | `D:\extra\bootsharp\cs\.nuget\` | +## NuGet cache gotcha (already handled by step 7) -Both are registered in the user-level `NuGet.Config`. +Reusing a version number you've already restored once (e.g., you re-ran the script with `-AlphaBumpMode none`) makes NuGet serve the cached old package. The script's step 7 purges these eagerly, but if you ever hit the symptom in a manual run: + +```powershell +Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp\" +Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.common\" +Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.inject\" +Remove-Item -Recurse -Force "$env:USERPROFILE\.nuget\packages\bootsharp.filesystem\" +``` diff --git a/CLAUDE.md b/CLAUDE.md index ef17ad0b..95db18f3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -59,94 +59,19 @@ CDN (unpkg/jsdelivr) updates after `npm publish`. - **PRNG changes invalidate every saved seed.** `MotelySingleSearchContext.*.cs` and `MotelyVectorSearchContext.*.cs` carry stream generation; any output change here breaks reproducibility against Balatro. `Motely.Tests` will catch it — run the suite before committing. - **Generated artifacts come from the generator.** Do not hand-edit `jaml.schema.json` or `jaml-schema.cs` — they are emitted by `Motely.CLI/MotelyJAML.schema.generator.cs`. Do not hand-edit anything under `Motely.Wasm/obj/` (Bootsharp output) or `motely-wasm/` (Bootsharp publish root, gitignored). -## Bootsharp source and docs +## Bootsharp local build -motely-wasm builds against Bootsharp pinned in `Directory.Packages.props` (`Bootsharp`, `Bootsharp.Common`, `Bootsharp.Inject` — all the same version; sponsor `Bootsharp.FileSystem` is versioned separately). Read these files directly — do not rely on public Bootsharp docs: +Build pipeline — branch, patch series, version pins, troubleshooting — is documented in `BOOTSHARP-BUILD.md` and automated as one PowerShell script: -### Building Bootsharp locally - -Source: `D:\bootsharp`. Branch sets the interop ABI: `feat/raw-interop` = NativeAOT-LLVM raw C-ABI (alpha.31x); older alphas use `[JSImport]`/`[JSExport]`. - -**Updating to the latest push — it is NOT `git pull`.** Elringus force-pushes / rebases `feat/delegates`, so the remote history is rewritten under the same commit message (e.g. "implement delegates support" gets a new hash each push). A `git pull` sees "diverged" and would make a merge commit. Instead: - -``` -cd D:/bootsharp && git fetch --all --prune && git reset --hard origin/feat/delegates +```powershell +pwsh ./scripts/build-bootsharp.ps1 ``` -This discards the local pointer and lands directly on his rewritten commit — linear, no merge commit. (Working tree is normally clean here, so nothing is lost.) - -Repack (from `D:\bootsharp\AGENTS.md`, in order): - -1. Once: `bash src/cs/.scripts/llvm.sh` (downloads NativeAOT-LLVM to `src/cs/.llvm`). -2. `cd src/js && npm run build`. -3. Bump `` in `src/cs/Directory.Build.props` (only if sources changed). -4. `cd src/cs && bash .scripts/pack.sh` (packs to `src/cs/.nuget`). - -**Then rebuild the sponsor FileSystem extension** — `Bootsharp.FileSystem` pins `Bootsharp.Common` as `*-*` (floats to local latest), so whenever you repack `Bootsharp.Common` you must repack FileSystem against it or the consumer restores a FileSystem built against a stale Common: - -5. `dotnet pack D:/extra/bootsharp/cs/Bootsharp.FileSystem/Bootsharp.FileSystem.csproj -c Release -o D:/extra/bootsharp/cs/.nuget` (packs the C# NuGet to the extra feed). `D:/extra/bootsharp/scripts/package.sh` is the separate JS-side build — it bundles the TypeScript and runs `npm publish` of `@rewaffle/bootsharp-file-system` to the GitHub registry; it is not part of the local C# NuGet loop. - -`Bootsharp.FileSystem` has no ``; it stamps a build-time timestamp `yyyy.MM.dd.HHmm` (NuGet normalizes to e.g. `2026.5.22.1237`). Read the actual emitted version from the pack log — that's the pin to use below. - -Local feeds are user-level (`%APPDATA%\NuGet\NuGet.Config`), not committed: `bootsharp-local` → `D:\bootsharp\src\cs\.nuget`; `Bootsharp.FileSystem` feed → `D:\extra\bootsharp\cs\.nuget`. - -Consume here: bump all three `Bootsharp*` versions in `Directory.Packages.props` together, **and** bump `Bootsharp.FileSystem` to the timestamp from step 5 (it tracks the same Common, just versioned separately). Validate with `dotnet publish Motely.Wasm -c Release` then `node Motely.Wasm/motely.test.mjs` (`RESULT: PASS`) — Bootsharp's own E2E suite passing does not prove Motely's types generate valid bindings. - -**Docs:** -@D:/bootsharp/docs/guide/index.md -@D:/bootsharp/docs/guide/getting-started.md -@D:/bootsharp/docs/guide/build-config.md -@D:/bootsharp/docs/guide/sideloading.md -@D:/bootsharp/docs/guide/serialization.md -@D:/bootsharp/docs/guide/interop-modules.md -@D:/bootsharp/docs/guide/interop-instances.md -@D:/bootsharp/docs/guide/llvm.md -@D:/bootsharp/docs/guide/declarations.md -@D:/bootsharp/docs/guide/preferences.md -@D:/bootsharp/docs/guide/extensions/dependency-injection.md -@D:/bootsharp/docs/guide/extensions/file-system.md - -**JS source:** -@D:/bootsharp/src/js/src/exports.mts -@D:/bootsharp/src/js/src/boot.mts -@D:/bootsharp/src/js/src/index.mts - -**C# publish source:** -@D:/bootsharp/src/cs/Bootsharp.Publish/ - -**Sample — minimal (canonical NativeAOT-LLVM boot, no framework):** -@D:/bootsharp/samples/minimal/README.md -@D:/bootsharp/samples/minimal/cs/Minimal.csproj -@D:/bootsharp/samples/minimal/cs/Program.cs -@D:/bootsharp/samples/minimal/main.mjs -@D:/bootsharp/samples/minimal/index.html - -**Sample — react (Vite + React app consuming Bootsharp ESM package):** -@D:/bootsharp/samples/react/README.md -@D:/bootsharp/samples/react/package.json -@D:/bootsharp/samples/react/vite.config.ts -@D:/bootsharp/samples/react/tsconfig.json -@D:/bootsharp/samples/react/index.html -@D:/bootsharp/samples/react/src/main.tsx -@D:/bootsharp/samples/react/src/computer.tsx -@D:/bootsharp/samples/react/src/donut.tsx -@D:/bootsharp/samples/react/backend/package.json -@D:/bootsharp/samples/react/backend/Backend.WASM/Backend.WASM.csproj -@D:/bootsharp/samples/react/backend/Backend.WASM/Program.cs -@D:/bootsharp/samples/react/backend/Backend/Backend.csproj -@D:/bootsharp/samples/react/backend/Backend/IComputer.cs -@D:/bootsharp/samples/react/backend/Backend.Prime/Backend.Prime.csproj -@D:/bootsharp/samples/react/backend/Backend.Prime/IPrimeUI.cs -@D:/bootsharp/samples/react/backend/Backend.Prime/Options.cs -@D:/bootsharp/samples/react/backend/Backend.Prime/Prime.cs - -**Local patch vs upstream:** -@X:/JammySeedFinder/src/MotelyJAML/bootsharp-fixes-vs-6edaa2c.patch +That's the build. Resets `D:\bootsharp` to upstream, applies `patches/*.patch`, packs core + Bootsharp.FileSystem, bumps pins in `Directory.Packages.props`, publishes `Motely.Wasm`, runs smoke tests. If it doesn't run green, read `BOOTSHARP-BUILD.md` § Troubleshooting before improvising. Never duplicate build prose here — the script and `BOOTSHARP-BUILD.md` are the source of truth. ## Sponsor-gated features - **`Bootsharp.FileSystem`** — The file system extension (`PickRoot`, `MountRoot`, `UnmountRoot`, `ReadTextFile`, `WriteTextFile`, `OnFileChanges`) is exclusive to [Bootsharp sponsors](https://github.com/sponsors/elringus). The NuGet package (`Bootsharp.FileSystem`) and its sample repo are not publicly available on NuGet or GitHub. - @D:/bootsharp/docs/guide/extensions/file-system.md ## Things that look weird but aren't diff --git a/patches/01-projectability.patch.PLACEHOLDER b/patches/01-projectability.patch.PLACEHOLDER new file mode 100644 index 00000000..ed67fdb1 --- /dev/null +++ b/patches/01-projectability.patch.PLACEHOLDER @@ -0,0 +1,39 @@ +PLACEHOLDER — this is not a real patch yet. + +The "projectability patch" currently lives only as a stash on the maintainer's +Windows machine. It touches `Common/Global/GlobalType.cs` and +`Common/Inspection/TypeInspector.cs` in Bootsharp core, and: + + Skips non-projectable interop members (ref structs, byref T&, delegates, + bare IEnumerable) and drops imported interfaces that have any such + member. + +Without it, `dotnet publish Motely.Wasm -c Release` fails when the inspector +walks Motely's interop surface (Span-bearing search-context methods, +delegate-shaped JS proxies, etc.). + +== One-time export == + +On the Windows machine that holds the stash, run: + + cd D:\bootsharp + git stash list + # find the entry "On feat/spec: !!GitHub_Desktop" + git stash show -p stash@{N} > X:\JammySeedFinder\src\MotelyJAML\patches\01-projectability.patch + +Then delete THIS .PLACEHOLDER file. `scripts/build-bootsharp.ps1` will pick +the real `01-projectability.patch` up automatically (it sorts `*.patch` +lexically and applies the series in order). + +== If you delete this file without exporting == + +The script's patch step is a no-op (it applies whatever `*.patch` files +exist in this directory, none = nothing to apply). Bootsharp core will +build, but `dotnet publish Motely.Wasm` will fail in the publish step +when the inspector hits a non-projectable member. + +== If the patch becomes obsolete == + +If Elringus lands these fixes on `feat/spec` HEAD, just delete the +exported patch file. No code change needed — the script applies whatever +is in `patches/`, none means none. diff --git a/bootsharp-fixes-vs-6edaa2c.patch b/patches/02-publish-fixes.patch similarity index 100% rename from bootsharp-fixes-vs-6edaa2c.patch rename to patches/02-publish-fixes.patch diff --git a/scripts/build-bootsharp.ps1 b/scripts/build-bootsharp.ps1 new file mode 100644 index 00000000..3f410ec0 --- /dev/null +++ b/scripts/build-bootsharp.ps1 @@ -0,0 +1,273 @@ +#!/usr/bin/env pwsh +<# +.SYNOPSIS + End-to-end Bootsharp + Bootsharp.FileSystem rebuild and Motely.Wasm publish. + +.DESCRIPTION + Single source of truth for the local Bootsharp pipeline. Resets D:\bootsharp + to origin/feat/spec, applies the vendored patch series under patches/, bumps + the alpha version, packs Bootsharp core and Bootsharp.FileSystem to their + local NuGet feeds, bumps the pins in Directory.Packages.props, publishes + Motely.Wasm, and runs the two Node smoke tests. + + See BOOTSHARP-BUILD.md for the prose explanation of every step. + +.PARAMETER BootsharpRoot + Path to the Bootsharp core checkout. Default D:\bootsharp. + +.PARAMETER BootsharpFsRoot + Path to the Bootsharp.FileSystem (sponsor) checkout. Default D:\extra\bootsharp. + +.PARAMETER Branch + Bootsharp upstream branch to reset to. Default feat/spec. + +.PARAMETER AlphaBumpMode + How to bump in Bootsharp's Directory.Build.props: + auto increment the NNN in 0.8.0-alpha.NNN (default) + none leave as-is + use literally (e.g. 0.8.0-alpha.400) + +.PARAMETER SkipSmoke + Skip the Node smoke tests at the end (motely.test.mjs + getctx-wasm.test.mjs). + +.PARAMETER WhatIf + Print every command without executing. +#> +[CmdletBinding()] +param( + [string] $BootsharpRoot = 'D:\bootsharp', + [string] $BootsharpFsRoot = 'D:\extra\bootsharp', + [string] $Branch = 'feat/spec', + [string] $AlphaBumpMode = 'auto', + [switch] $SkipSmoke, + [switch] $WhatIf +) + +$ErrorActionPreference = 'Stop' +$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot '..')).Path + +function Step ([string] $msg) { + Write-Host '' + Write-Host "==> $msg" -ForegroundColor Cyan +} + +function Run ([scriptblock] $block, [string] $label) { + if ($label) { Write-Host " $label" -ForegroundColor DarkGray } + Write-Host " $block" -ForegroundColor DarkGray + if (-not $WhatIf) { + & $block + if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { + throw "Command failed (exit $LASTEXITCODE): $block" + } + } +} + +# ── 1. Sanity-check tooling ────────────────────────────────────────────────── +Step '1/11 Sanity-check tooling' +$tools = @{ + git = 'git --version' + dotnet = 'dotnet --version' + node = 'node --version' + npm = 'npm --version' + bash = 'bash --version' # Bootsharp pack.sh needs a POSIX shell +} +$missing = @() +foreach ($name in $tools.Keys) { + if (-not (Get-Command $name -ErrorAction SilentlyContinue)) { $missing += $name } +} +if ($missing.Count -gt 0) { + $msg = @" +Missing required tool(s): $($missing -join ', ') + Install hints: + git https://git-scm.com/ + dotnet .NET 10 SDK with: dotnet workload install wasm-tools + node Node 22 LTS (>=20.6.0 required) + bash Git for Windows ships Git Bash; WSL also works +"@ + if ($WhatIf) { Write-Host $msg -ForegroundColor Yellow } + else { throw $msg } +} else { + Write-Host ' OK' -ForegroundColor Green +} + +# ── 2. Reset Bootsharp core ────────────────────────────────────────────────── +Step "2/11 Reset $BootsharpRoot to origin/$Branch" +if (-not (Test-Path $BootsharpRoot)) { + $msg = "BootsharpRoot does not exist: $BootsharpRoot" + if ($WhatIf) { Write-Host " $msg" -ForegroundColor Yellow } + else { throw $msg } +} +Run { git -C $BootsharpRoot fetch --all --prune } +Run { git -C $BootsharpRoot reset --hard "origin/$Branch" } + +if (-not $WhatIf) { + $dirty = git -C $BootsharpRoot status --porcelain --untracked-files=no + if ($dirty) { + throw "Bootsharp working tree has tracked-file changes after reset:`n$dirty" + } +} + +# ── 3. Apply patch series ──────────────────────────────────────────────────── +Step '3/11 Apply patches/*.patch (in lexical order)' +$patchDir = Join-Path $RepoRoot 'patches' +$patches = @() +if (Test-Path $patchDir) { + $patches = Get-ChildItem -Path $patchDir -Filter '*.patch' -File | + Sort-Object Name +} +if ($patches.Count -eq 0) { + Write-Host ' (no patches to apply)' -ForegroundColor Yellow +} else { + foreach ($p in $patches) { + Write-Host " -> $($p.Name)" -ForegroundColor DarkGray + Run { git -C $BootsharpRoot apply --check $p.FullName } "check $($p.Name)" + Run { git -C $BootsharpRoot apply $p.FullName } "apply $($p.Name)" + } +} + +# Surface the placeholder so a fresh agent doesn't think the series is complete. +$placeholder = Join-Path $patchDir '01-projectability.patch.PLACEHOLDER' +if (Test-Path $placeholder) { + Write-Host '' + Write-Host ' NOTE: patches/01-projectability.patch.PLACEHOLDER exists.' -ForegroundColor Yellow + Write-Host ' The projectability fix has NOT been vendored. Motely.Wasm publish' -ForegroundColor Yellow + Write-Host ' will fail until the maintainer exports the stash. See the file.' -ForegroundColor Yellow +} + +# ── 4. Bump in Bootsharp ─────────────────────────────────────────── +Step '4/11 Bump in Bootsharp/src/cs/Directory.Build.props' +$bsProps = Join-Path $BootsharpRoot 'src/cs/Directory.Build.props' +$bsPropsMissing = -not (Test-Path $bsProps) +if ($bsPropsMissing) { + if (-not $WhatIf) { throw "Not found: $bsProps" } + Write-Host " (skipped: $bsProps not found)" -ForegroundColor Yellow +} + +$newAlphaVersion = $null +if ($bsPropsMissing) { + $newAlphaVersion = '' +} elseif ($AlphaBumpMode -eq 'none') { + $newAlphaVersion = ([xml](Get-Content $bsProps -Raw)).Project.PropertyGroup.Version + Write-Host " leaving version unchanged: $newAlphaVersion" -ForegroundColor DarkGray +} elseif ($AlphaBumpMode -eq 'auto') { + $content = Get-Content $bsProps -Raw + if ($content -notmatch '(?0\.8\.0-alpha\.(?\d+))') { + throw "Couldn't find 0.8.0-alpha.NNN in $bsProps. Pass -AlphaBumpMode explicitly." + } + $newN = [int]$Matches['n'] + 1 + $newAlphaVersion = "0.8.0-alpha.$newN" + Write-Host " $($Matches['v']) -> $newAlphaVersion" -ForegroundColor DarkGray + if (-not $WhatIf) { + ($content -replace '0\.8\.0-alpha\.\d+', "$newAlphaVersion") | + Set-Content $bsProps -NoNewline + } +} else { + $newAlphaVersion = $AlphaBumpMode + Write-Host " setting version literally: $newAlphaVersion" -ForegroundColor DarkGray + if (-not $WhatIf) { + (Get-Content $bsProps -Raw) ` + -replace '[^<]+', "$newAlphaVersion" | + Set-Content $bsProps -NoNewline + } +} + +# ── 5. Build JS, then pack C# ──────────────────────────────────────────────── +Step '5/11 npm run build (Bootsharp JS) + pack.sh (Bootsharp C#)' +Run { npm --prefix (Join-Path $BootsharpRoot 'src/js') run build } +Run { bash (Join-Path $BootsharpRoot 'src/cs/.scripts/pack.sh') } + +# ── 6. Pack Bootsharp.FileSystem ───────────────────────────────────────────── +Step '6/11 dotnet pack Bootsharp.FileSystem' +$fsCs = Join-Path $BootsharpFsRoot 'cs' +$fsNuget = Join-Path $fsCs '.nuget' +if (-not (Test-Path $fsCs)) { + if (-not $WhatIf) { throw "Not found: $fsCs" } + Write-Host " (skipped: $fsCs not found)" -ForegroundColor Yellow +} else { + Run { dotnet pack $fsCs --configuration Release --output $fsNuget } +} + +$newFsVersion = $null +if (-not $WhatIf) { + $fsPkg = Get-ChildItem -Path $fsNuget -Filter 'Bootsharp.FileSystem.*.nupkg' -File | + Sort-Object LastWriteTime -Descending | + Select-Object -First 1 + if (-not $fsPkg) { throw "No Bootsharp.FileSystem nupkg produced in $fsNuget" } + if ($fsPkg.BaseName -notmatch '^Bootsharp\.FileSystem\.(?.+)$') { + throw "Cannot parse version from $($fsPkg.Name)" + } + $newFsVersion = $Matches['v'] + Write-Host " packed: $($fsPkg.Name) (version $newFsVersion)" -ForegroundColor DarkGray +} + +# ── 7. Purge NuGet cache ───────────────────────────────────────────────────── +Step '7/11 Purge NuGet user cache for these versions' +if (-not $WhatIf) { + $cacheRoot = Join-Path $env:USERPROFILE '.nuget/packages' + foreach ($pkg in 'bootsharp', 'bootsharp.common', 'bootsharp.inject') { + $p = Join-Path $cacheRoot "$pkg/$newAlphaVersion" + if (Test-Path $p) { + Write-Host " rm $p" -ForegroundColor DarkGray + Remove-Item -Recurse -Force -LiteralPath $p + } + } + if ($newFsVersion) { + $p = Join-Path $cacheRoot "bootsharp.filesystem/$newFsVersion" + if (Test-Path $p) { + Write-Host " rm $p" -ForegroundColor DarkGray + Remove-Item -Recurse -Force -LiteralPath $p + } + } +} else { + Write-Host ' (would purge bootsharp / .common / .inject / .filesystem at the new versions)' -ForegroundColor DarkGray +} + +# ── 8. Bump pins in Directory.Packages.props ───────────────────────────────── +Step '8/11 Bump pins in Directory.Packages.props' +$pkgProps = Join-Path $RepoRoot 'Directory.Packages.props' +if (-not (Test-Path $pkgProps)) { throw "Not found: $pkgProps" } + +if (-not $WhatIf) { + [xml]$xml = Get-Content $pkgProps -Raw + $changed = @() + foreach ($pv in $xml.Project.ItemGroup.PackageVersion) { + switch ($pv.Include) { + 'Bootsharp' { if ($pv.Version -ne $newAlphaVersion) { $changed += "$($pv.Include): $($pv.Version) -> $newAlphaVersion"; $pv.Version = $newAlphaVersion } } + 'Bootsharp.Common' { if ($pv.Version -ne $newAlphaVersion) { $changed += "$($pv.Include): $($pv.Version) -> $newAlphaVersion"; $pv.Version = $newAlphaVersion } } + 'Bootsharp.Inject' { if ($pv.Version -ne $newAlphaVersion) { $changed += "$($pv.Include): $($pv.Version) -> $newAlphaVersion"; $pv.Version = $newAlphaVersion } } + 'Bootsharp.FileSystem' { if ($newFsVersion -and $pv.Version -ne $newFsVersion) { $changed += "$($pv.Include): $($pv.Version) -> $newFsVersion"; $pv.Version = $newFsVersion } } + } + } + $xml.Save($pkgProps) + if ($changed.Count -eq 0) { + Write-Host ' (no changes — already current)' -ForegroundColor DarkGray + } else { + foreach ($line in $changed) { Write-Host " $line" -ForegroundColor DarkGray } + } +} else { + Write-Host " (would set Bootsharp/.Common/.Inject -> $newAlphaVersion, .FileSystem -> )" -ForegroundColor DarkGray +} + +# ── 9. Publish Motely.Wasm ─────────────────────────────────────────────────── +Step '9/11 dotnet publish Motely.Wasm -c Release' +Run { dotnet publish (Join-Path $RepoRoot 'Motely.Wasm') -c Release } + +# ── 10. Smoke ───────────────────────────────────────────────────────────────── +Step '10/11 Smoke (Node)' +if ($SkipSmoke) { + Write-Host ' -SkipSmoke: skipped' -ForegroundColor Yellow +} else { + Run { node (Join-Path $RepoRoot 'Motely.Wasm/motely.test.mjs') } + Run { node (Join-Path $RepoRoot 'Motely.Wasm/getctx-wasm.test.mjs') } +} + +# ── 11. Summary ────────────────────────────────────────────────────────────── +Step '11/11 Summary' +Write-Host " Bootsharp core version : $newAlphaVersion" +if ($newFsVersion) { Write-Host " Bootsharp.FileSystem : $newFsVersion" } +Write-Host " Core feed : $(Join-Path $BootsharpRoot 'src/cs/.nuget')" +Write-Host " FileSystem feed : $fsNuget" +Write-Host " Motely.Wasm publish : $(Join-Path $RepoRoot 'motely-wasm/dist')" +if (-not $SkipSmoke -and -not $WhatIf) { + Write-Host ' RESULT: PASS' -ForegroundColor Green +}