Skip to content

Integrate dotnetup: .NET SDK Manager page + Doctor awareness#197

Open
Redth wants to merge 5 commits into
mainfrom
redth-dotnetup-doctor-integration
Open

Integrate dotnetup: .NET SDK Manager page + Doctor awareness#197
Redth wants to merge 5 commits into
mainfrom
redth-dotnetup-doctor-integration

Conversation

@Redth

@Redth Redth commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Why

Sherpa's Doctor already flags when .NET SDKs and workloads are out of date, but until now it stopped short of helping install or update SDKs because we were waiting on dotnetup (the new user-level .NET SDK/runtime manager from dotnet/sdk) to be ready. It's ready, so this PR wires dotnetup into Sherpa and adds a dedicated SDK Manager experience.

What

New ".NET SDK Manager" page (/dotnet-sdk) that drives dotnetup to install and track SDK channels, list installed components (SDKs, runtimes, ASP.NET Core runtimes), and keep them updated. The page bootstraps dotnetup on demand if it isn't present.

Read-only "what will change?" inspection before any mutating action:

  • Update preview (GetUpdatePreviewAsync / DotnetUpdateResolver) resolves each tracked channel against the official .NET release metadata and reports which channels have a newer version available, without running an install.
  • Project context (InspectProjectFolderAsync / GlobalJsonResolver) walks up to the nearest global.json the way the dotnet host does, derives the dotnetup channel, and reports whether an installed SDK satisfies it and whether it's already tracked. A native macOS folder picker (NSOpenPanel) lets the user point at any folder.

Doctor awareness so the Doctor page/CLI can surface dotnetup-managed state alongside the existing workload checks.

Native add-channel modal (AddChannelPage + AddChannelModal) replaces the earlier inline HTML dialog: native sheet chrome with a Blazor-hosted channel list, custom version input, and "tracking" badges for already-tracked channels.

Sidebar: the entry now lives in the Tools group and is named ".NET SDK Manager" in both the Blazor layout and the native macOS sidebar.

Supporting plumbing: dotnetup argument builder, output parser, downloader/bootstrapper, and runtime-identifier helper in MauiSherpa.Workloads, plus docs (docs/dotnet-sdk-management.md) and unit tests across the new services (parser, downloader, arguments, RID, global.json, update preview).

Notes for reviewers

  • This branch also forward-migrates to Shiny.Mediator 6.6.2 + MAUI Controls 10.0.60 (two commits), which were prerequisites; that migration also fixes the macOS window/cache serialization path.
  • The update-preview and project-context features are intentionally read-only. Installs/updates only happen on explicit user action.
  • Tracked-channel installs deliberately pass terminalMode: false because Terminal vs Isolation mode is a one-time global choice made by dotnetup init, not a per-channel setting.
  • UI was validated in both light and dark mode on the macOS head.

Testing

  • dotnet test tests/MauiSherpa.Workloads.Tests -> 120 passed.
  • macOS head builds clean (0 errors) and was exercised manually.

Redth and others added 5 commits June 24, 2026 21:40
Sherpa can now manage .NET SDK/runtime installs via dotnetup (the .NET
user-level toolchain manager), starting with the Doctor page.

Workloads (platform-agnostic, unit-tested):
- DotnetUp models, RID detection, download-URL + SHA-512 verification,
  `list --format Json` / `--info` parsing, and command/arg builders.

Core:
- IDotnetUpService/DotnetUpService: bootstrap (download+verify into
  ~/.dotnetup), exe resolution, info/list queries, ProcessRequest builders.
- DoctorService is dotnetup-aware: reconciles dotnetup-managed SDKs into the
  installed set (reads installRoot from `list --format Json`), makes the
  out-of-date `.NET SDK` check fixable (dotnetup-update-sdk), and adds a
  dotnetup presence check (install-dotnetup).

UI:
- Doctor.razor wires the new fix actions (bootstrap via OperationModal,
  dotnetup commands via ProcessModal).
- New /dotnet-sdk SDK Manager page + ".NET" nav section.

CLI:
- Optional, quiet dotnetup status check in DoctorCommand.

Fixes:
- Register IDotnetUpService in MacOSMauiProgram.cs. The native macOS head has
  its own DI container; without this, the shared Doctor/DotnetSdk pages threw
  on their required @Inject and the app exited before showing a window.

Docs:
- docs/dotnet-sdk-management.md; AGENTS.md interface table/overview.

Tests: 99 Workloads + 447 Core passing.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
PR #196 pinned Shiny.Mediator/AppSupport back to 6.1.1 to dodge a launch
crash: Dependabot #193 had bumped Core to 6.6.2 while the app heads still
referenced Shiny.Mediator.Maui 6.1.1, so at runtime Core loaded 6.6.2 while
the 6.1.1 Maui assembly called AddSingletonAsImplementedInterfaces (whose
signature changed in 6.6.2), throwing MissingMethodException inside
CreateMauiApp. The macOS backend swallowed it, leaving a live process with
no window and no log output.

Rather than pin down, migrate the whole solution forward to a single
consistent Shiny.Mediator 6.6.2:
- Core: restore Shiny.Mediator + Shiny.Mediator.AppSupport to 6.6.2
  (overriding #196's 6.1.1 pin).
- maccatalyst + macOS heads: Shiny.Mediator.Maui + Caching -> 6.6.2, which
  requires Microsoft.Maui.Controls >= 10.0.60, so bump Controls
  10.0.31/10.0.41 -> 10.0.60.
- LinuxGtk already on 6.6.2.

Verified: macOS head builds; clean startup (no MissingMethodException);
window renders (System Events reports 1 window, frontmost).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…N resolver)

Shiny.Mediator 6.6.x serializes the persistent cache via Shiny.Json, whose
DefaultJsonSerializer has an empty TypeInfoResolverChain unless source-gen
contexts are contributed. Without them it throws 'No JsonTypeInfo registered
for type ...' for every cached request/response type, breaking all [Cache]
handlers app-wide. Register the framework reflection resolver
(DefaultJsonTypeInfoResolver) via Shiny.Json.AddResolver(...) at startup in
both cache-using heads to restore plain serialization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The macOS head hides the Blazor sidebar and uses a native AppKit sidebar
(MacOSApp.cs). The dotnetup integration only added the Blazor nav link, so
the SDK Manager page was unreachable on macOS. Add a matching native '.NET'
section with an 'SDK Manager' item routing to /dotnet-sdk.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…nnel modal

Builds on the initial dotnetup integration with a redesigned .NET SDK Manager
page and two read-only inspection features so the user can see what an update
would change before running it.

- Update preview: GetUpdatePreviewAsync resolves each tracked channel against
  the official .NET release metadata and reports which have a newer version,
  without performing any install. Backed by a new DotnetUpdateResolver.
- Project context: InspectProjectFolderAsync walks up to the nearest global.json
  (like the dotnet host), derives the dotnetup channel, and reports whether an
  installed SDK satisfies it and whether it is already tracked. Backed by a new
  GlobalJsonResolver with unit tests. Adds a native folder picker (NSOpenPanel)
  for macOS.
- Add-channel flow converted to a native hybrid modal (AddChannelPage +
  AddChannelModal) instead of an inline HTML dialog, with a clean channel list,
  custom version input, and "tracking" badges.
- UI polish: card backgrounds/radii made consistent, badges turned into real
  chips, info note flattened to a single grey label, "Version | Type" selector
  recolored to the app accent, per-version cube icon, and macOS scrollbar gutter.
- Sidebar: SDK Manager moved into the Tools group and renamed ".NET SDK Manager"
  in both the Blazor layout and the native macOS sidebar.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

1 participant