feat: unify Windows and Linux Coder Desktop in a single repo#173
feat: unify Windows and Linux Coder Desktop in a single repo#173ibetitsmike wants to merge 10 commits into
Conversation
- Adopt platform-aware shared sources from coder-desktop-linux (runtime OS checks and WINDOWS conditional compilation preserve Windows behavior) - Multi-target Vpn, Vpn.Service, Tests.Vpn, Tests.Vpn.Service as net8.0;net8.0-windows; Vpn.DebugClient becomes net8.0 - Add NamedPipeServerTransport (Windows) implementing IRpcServerTransport, extracted from the previous ManagerRpc named pipe server logic - Add Directory.Build.props with EnableWindowsTargeting for non-Windows hosts - Add Linux projects to the solution plus Coder.Desktop.Linux.slnf filter - Enable NuGet lock files for new projects and regenerate affected locks - CI: keep Windows fmt/test/build jobs, add Linux test and publish jobs
- UnixSocketServerTransport: refuse to delete non-socket files at the configured socket path, and only assign the listener after successful bind/listen so a failed setup is retried - Centralize the default Unix socket path in a single constant - DebugClient: reuse UnixSocketClientTransport (honors CODER_DESKTOP_RPC_SOCKET_PATH) - Manager: fail fast when a signature signer is configured in a build without Authenticode support instead of silently skipping validation
On Linux the peer speaker's receive loop can observe the pipe closing during disposal and raise an error event before it is disposed itself, failing the test spuriously (~50% on some machines). Stop asserting on error events once shutdown begins.
Combining EnableWindowsTargeting with BuildWithNetFrameworkHostedCompiler (used by the Windows CI jobs) injects Microsoft.Net.Compilers.Toolset.Framework into every project, which breaks locked-mode restore against lock files generated without it. Windows hosts do not need EnableWindowsTargeting.
dotnet format fails to auto-discover the workspace now that the repo contains both Coder.Desktop.sln and Coder.Desktop.Linux.slnf.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d8796feb52
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| _logger.LogDebug( | ||
| "Skipping tunnel binary version validation: ProductVersion validation is only supported on Windows binaries"); |
There was a problem hiding this comment.
Validate the Linux tunnel binary before executing it
On the Linux path this skips the only version validator, and TunnelBinarySignatureSigner defaults to empty on Linux, so the validator set is empty before the service chmods and executes the downloaded /bin/coder-linux-* as root. Because the RPC socket is made writable by all local users and StartRequest.CoderUrl is client-controlled, an unprivileged user can point the root service at a fake HTTP Coder endpoint and supply an arbitrary tunnel binary; Linux needs a trusted signature/checksum or equivalent client restriction before execution.
Useful? React with 👍 / 👎.
| foreach (var arg in args) | ||
| { | ||
| if (arg.Equals("--minimized", StringComparison.OrdinalIgnoreCase) || | ||
| arg.Equals("--start-hidden", StringComparison.OrdinalIgnoreCase)) |
There was a problem hiding this comment.
Dispatch coder:// launch arguments to the URI handler
The Linux desktop entry launches /usr/bin/coder-desktop %u, so opening a workspace app passes the coder://... URL in desktop.Args; this loop only recognizes minimized flags, and a repo-wide search shows IUriHandler is never registered or invoked by App.Avalonia. As a result, protocol activations on Linux just open the tray window and silently drop the RDP/open-workspace request.
Useful? React with 👍 / 👎.
| rid='linux-arm64' | ||
| fi | ||
|
|
||
| local repo_root="${startdir}/.." |
There was a problem hiding this comment.
Include the repo source in the AUR build inputs
When the generated AUR archive is built with makepkg, only the files declared in source are available, and this PKGBUILD declares just the service and desktop assets. ${startdir}/.. will not contain App.Avalonia or Vpn.Service in a normal AUR checkout, so both dotnet publish commands fail unless the full repository happens to be checked out next to the PKGBUILD; add a source tarball/git source or package the full source tree.
Useful? React with 👍 / 👎.
The dotnet 8.0.4xx SDK formatter now enforces the .editorconfig CRLF line-ending rule that older SDK versions ignored, which made the fmt CI job fail even on unmodified files. Apply dotnet format output across the solution.
- Guard the DebugClient Unix socket path with OperatingSystem.IsLinux() to satisfy CA1416 - Suppress AVP1002 in App.Avalonia (DependencyObjectSelector registers generic AvaloniaProperty owners by design, ported from WinUI) - Set the SendMessageWriteError shutdown flag before injecting the write error, since the failed write can also tear down the receive loop
Merges the coder-desktop-linux Avalonia port back into this repo so one codebase builds and ships Coder Desktop for both Windows and Linux, sharing the VPN service, RPC protocol, and SDKs.
What changed
App.Avalonia(Avalonia UI),App.Shared(UI-agnostic ViewModels/services),App.Linux(Linux service impls),Vpn.Linux(Unix socket RPC transports),Packaging.Linux(deb/rpm/tar/AUR scripts),scripts/run-linux-dev.sh, and therelease-linux.yamlworkflow.Vpn.Service/*,MutagenSdk/MutagenClient.cs,Vpn.DebugClient): runtime OS checks plusWINDOWSconditional compilation preserve existing Windows behavior.Vpn,Vpn.Service,Tests.Vpn,Tests.Vpn.Serviceasnet8.0;net8.0-windows.ManagerRpcnow uses anIRpcServerTransportabstraction: named pipes (extracted toNamedPipeServerTransport) on Windows, Unix domain sockets on Linux.Coder.Desktop.Linux.slnf(excludes WinUIApp,Tests.App,Installer),Directory.Build.props(EnableWindowsTargetingon non-Windows hosts only), and NuGet lock files for the new projects.test-linuxandbuild-linuxjobs.fmteven for unmodified files.SpeakerTest.SendMessageWriteError(shutdown race, ~50% failure rate on Linux).Appand AvaloniaApp.Avalonia/App.Sharedremain separate; converging the Windows app ontoApp.Sharedis follow-up work.Validation
aws-linuxworkspace): locked-mode restore ofCoder.Desktop.Linux.slnf, Release build, all test projects green, format verification clean.CoderVpnServiceunder sudo, drove it viaVpn.DebugClientover the Unix socket. VPN started against https://dev.coder.com, downloaded the tunnel binary, and streamed live workspace/agent peer updates with successful P2P handshakes.aws-windows-desktopworkspace): full-solution restore,dotnet test -p:Platform=x64on the shared test projects, Release publish ofVpn.Service(net8.0-windows). The WinUI App publish and full fmt/locked-mode+NetFrameworkHostedCompiler restore fail identically on unmodifiedmainin that environment (SDK drift), so CI is authoritative there, and it passes.