Upgrade projects to .NET 10 and implement automatic prerequisites check/installation and PATH registration
Build and Test / build (push) Failing after 41s

This commit is contained in:
Marek Novák
2026-07-01 02:10:35 +02:00
parent 74f7a1ae06
commit b1a4c10dd2
7 changed files with 227 additions and 7 deletions
+1 -1
View File
@@ -10,7 +10,7 @@ jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: container:
image: mcr.microsoft.com/dotnet/sdk:8.0 image: mcr.microsoft.com/dotnet/sdk:10.0
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v3 uses: actions/checkout@v3
+10
View File
@@ -36,6 +36,16 @@ namespace NixWslWrapper.Cli
string user = Environment.GetEnvironmentVariable("NIX_WSL_USER") ?? "root"; string user = Environment.GetEnvironmentVariable("NIX_WSL_USER") ?? "root";
string profile = Environment.GetEnvironmentVariable("NIX_WSL_PROFILE") ?? "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh"; string profile = Environment.GetEnvironmentVariable("NIX_WSL_PROFILE") ?? "/nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh";
try
{
PrerequisiteManager.EnsurePrerequisites(distro, user, profile);
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[bold red]Prerequisite Check Failed:[/] {ex.Message}");
return 1;
}
WslTarget target; WslTarget target;
try try
{ {
@@ -11,7 +11,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AssemblyName>nix</AssemblyName> <AssemblyName>nix</AssemblyName>
@@ -0,0 +1,210 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Spectre.Console;
namespace NixWslWrapper.Cli
{
public class PrerequisiteManager
{
public static void EnsurePrerequisites(string distro, string user, string profilePath)
{
EnsurePathRegistered();
EnsureWslAndDistro(distro);
EnsureNix(distro, user, profilePath);
}
private static void EnsurePathRegistered()
{
try
{
string currentExeDir = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule?.FileName) ?? AppContext.BaseDirectory;
currentExeDir = Path.GetFullPath(currentExeDir).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
string? userPath = Environment.GetEnvironmentVariable("PATH", EnvironmentVariableTarget.User);
var paths = (userPath ?? "")
.Split(';', StringSplitOptions.RemoveEmptyEntries)
.Select(p => Path.GetFullPath(p.Trim()).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar))
.ToList();
if (!paths.Any(p => string.Equals(p, currentExeDir, StringComparison.OrdinalIgnoreCase)))
{
string newPath = string.IsNullOrWhiteSpace(userPath)
? currentExeDir
: userPath.TrimEnd(';') + ";" + currentExeDir;
Environment.SetEnvironmentVariable("PATH", newPath, EnvironmentVariableTarget.User);
var pathPanel = new Panel(new Markup(
$"[bold yellow]PATH Updated:[/] Added [green]\"{currentExeDir}\"[/] to your Windows User PATH.\n" +
"Please [bold]restart your terminal, MCP servers, or IDE[/] for changes to take effect."
))
{
Border = BoxBorder.Rounded,
Padding = new Padding(1, 1, 1, 1),
Header = new PanelHeader("PATH Auto-Registration")
};
AnsiConsole.Write(pathPanel.BorderColor(Color.Yellow));
AnsiConsole.WriteLine();
}
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[yellow]Warning: Could not automatically register directory to PATH: {ex.Message}[/]");
}
}
private static void EnsureWslAndDistro(string distro)
{
// 1. Check if wsl.exe exists
bool wslExists = false;
try
{
var checkWsl = new ProcessStartInfo("wsl.exe", "--status")
{
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
};
using var p = Process.Start(checkWsl);
p?.WaitForExit(3000);
wslExists = p != null;
}
catch
{
wslExists = false;
}
if (!wslExists)
{
var wslPanel = new Panel(new Markup(
$"[bold red]WSL Not Found:[/] WSL (Windows Subsystem for Linux) is not installed.\n" +
$"Triggering automatic installation of WSL and the [green]{distro}[/] distribution.\n\n" +
"[bold yellow]Please approve the administrator UAC prompt that appears.[/]"
))
{
Border = BoxBorder.Double,
Header = new PanelHeader("WSL Auto-Installation")
};
AnsiConsole.Write(wslPanel.BorderColor(Color.Red));
try
{
var installPsi = new ProcessStartInfo("wsl.exe", $"--install -d {distro}")
{
UseShellExecute = true,
Verb = "runas" // Elevates to Administrator
};
using var p = Process.Start(installPsi);
p?.WaitForExit();
}
catch (Exception ex)
{
AnsiConsole.MarkupLine($"[bold red]Failed to start WSL installation:[/] {ex.Message}");
throw new InvalidOperationException("WSL is required to run this wrapper.", ex);
}
}
// 2. Check if the specific distro is installed
bool distroInstalled = false;
try
{
var checkDistro = new ProcessStartInfo("wsl.exe", $"-d {distro} -u root -- echo check")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using var p = Process.Start(checkDistro);
p?.WaitForExit(4000);
distroInstalled = p?.ExitCode == 0;
}
catch
{
distroInstalled = false;
}
if (!distroInstalled)
{
AnsiConsole.MarkupLine($"[yellow]WSL Distro [green]'{distro}'[/] is not registered. Installing it now...[/]");
try
{
var distroPsi = new ProcessStartInfo("wsl.exe", $"--install -d {distro}")
{
UseShellExecute = true,
Verb = "runas"
};
using var p = Process.Start(distroPsi);
p?.WaitForExit();
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to automatically install WSL distribution '{distro}': {ex.Message}", ex);
}
}
}
private static void EnsureNix(string distro, string user, string profilePath)
{
bool nixInstalled = false;
try
{
var checkNix = new ProcessStartInfo("wsl.exe", $"-d {distro} -u {user} -- sh -c \"command -v nix\"")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
using var p = Process.Start(checkNix);
p?.WaitForExit(4000);
nixInstalled = p?.ExitCode == 0;
}
catch
{
nixInstalled = false;
}
if (!nixInstalled)
{
var nixPanel = new Panel(new Markup(
$"[bold yellow]Nix Engine Not Found:[/] Nix is not installed inside the [green]'{distro}'[/] distribution.\n" +
"Triggering automatic installation using the official Determinate Nix installer.\n\n" +
"[grey]This may take a few minutes. Please wait...[/]"
))
{
Border = BoxBorder.Rounded,
Header = new PanelHeader("Nix Auto-Installation")
};
AnsiConsole.Write(nixPanel.BorderColor(Color.Yellow));
try
{
string installCmd = "curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install --no-confirm";
var nixPsi = new ProcessStartInfo("wsl.exe", $"-d {distro} -u root -- sh -c \"{installCmd}\"")
{
UseShellExecute = false,
RedirectStandardOutput = false,
RedirectStandardError = false,
CreateNoWindow = false
};
using var p = Process.Start(nixPsi);
p?.WaitForExit();
if (p?.ExitCode != 0)
{
throw new InvalidOperationException($"Nix installer exited with non-zero code: {p?.ExitCode}");
}
AnsiConsole.MarkupLine("[green]✔ Nix installed successfully inside WSL![/]");
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to automatically install Nix inside WSL distro: {ex.Message}", ex);
}
}
}
}
}
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
@@ -1,11 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\NixWslWrapper.Core\NixWslWrapper.Core.csproj" /> <ProjectReference Include="..\NixWslWrapper.Core\NixWslWrapper.Core.csproj" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
</PropertyGroup> </PropertyGroup>
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>