Skip to content

Conversation

dsplaisted
Copy link
Member

We're not planning to merge this to main yet, but we want to start reviewing the code.

Context: dotnet/designs#339

dsplaisted and others added 30 commits August 14, 2025 22:57
Copilot prompt:

Implement the GetConfiguredInstallType method in #file:'DotnetInstaler.cs' .

This method should look in the PATH and resolve "dotnet" or "dotnet.exe", depending on the current OS.  If it is not found, the return value should be SdkInstallType.None.  If it is found in Program Files, the install type should be SdkInstallType.Admin.  If it is found in another folder, the install type should be SdkInsntallType.User.

However, the method should also check the value of DOTNET_ROOT environment variable.  For a user install, DOTNET_ROOT should be set to the folder where the dotnet executable is found.  For an admin install, DOTNET_ROOT should not be set, but if it is set to the install path under program files, that is OK.  If the DOTNET_ROOT value doesn't match the install location, the method should return SdkInstallType.Inconsistent.
Copilot prompt:

In #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaler.GetConfiguredInstallType':301-2793 ,  use #method:'Microsoft.DotNet.Cli.Utils.EnvironmentProvider.GetCommandPath':2399-2843 to search for dotnet on the path.
Copilot prompts:

Create a class to represent the contents of a global.json file, and create a corresponding JsonSerializerContext type.

Can you refer to https://learn.microsoft.com/en-us/dotnet/core/tools/global-json to update the schema you are using for the global.json file?  AllowPrerelease should be a booleann, and instead of Path there should be a Paths property which is an array of strings.
Copilot prompts:

Implement #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetDefaultDotnetInstallPath':2814-2986 .  It look for a global.json file starting in the specified directory and walking up the directory chain.  If it finds one, it should deserialize its contents using System.Text.Json APIs and #class:'Microsoft.DotNet.Tools.Bootstrapper.GlobalJsonContentsJsonContext':413-650 , and use that for the return value.

Sorry, I meant to ask you to implement #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetGlobalJsonInfo':4307-4411  instead of #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetDefaultDotnetInstallPath':2839-2947 .  Can you revert your changes and then implement #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetGlobalJsonInfo':4307-4411  using the instructions I previously provided?
Copilot prompts:

Can you remove the try catch block around reading the global.json file in #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.GetGlobalJsonInfo':3019-4216 ?  Also remove the convenience properties you added to GlobalJsonInfo for now.

OK, go ahead and add those convencience properties back.
Copilot prompt:

Implement the #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.ConfigureInstallType':4479-4606  method.  If the install type is user, remove any other folder with dotnet in it from the PATH and add the dotnetRoot to the PATH.  Also set the DOTNET_ROOT environment variable to dotnetRoot.

If the install type is Admin, unset DOTNET_ROOT, and add dotnetRoot to the path (removing any other dotnet folder from the path).

If the install type is None, unset DOTNET_ROOT and remove any dotnet folder from the path.

For any other install type, throw an ArgumentException.
Copilot prompt:

In #method:'Microsoft.DotNet.Tools.Bootstrapper.DotnetInstaller.ConfigureInstallType':4481-6459 what I meant by removing a folder from the path if it has dotnet in it was that you should check the contents of each folder and if it is a dotnet installation folder then it should be removed from the path.  A simple way to check if it's a dotnet installation folder is if it has a dotnet executable in it.
I renamed the InstallType as the Runtime installs would similarly hold the same properties.
@Copilot Copilot AI review requested due to automatic review settings September 24, 2025 21:46
Copy link
Contributor

This PR is targeting main, which is now for .NET 11-facing work. If you intended to target .NET 10, either retarget this PR to release/10.0.1xx or make sure you backport the change to release/10.0.1xx after merging. See #50394 for more details.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds the initial code for "dnup", a new .NET bootstrapper tool designed to facilitate installing and managing .NET SDKs. It introduces a comprehensive .NET installer system with archive-based installation, manifest management, version resolution, and command-line interface.

  • Adds a new dnup installer tool with command-line SDK installation functionality
  • Implements archive-based extraction and installation system with progress reporting
  • Provides version channel resolution (e.g., "latest", "lts", "preview", feature bands)

Reviewed Changes

Copilot reviewed 72 out of 72 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/Installer/dnup/dnup.csproj New project file for dnup bootstrapper tool targeting net10.0 with AOT publishing
src/Installer/dnup/Program.cs Main entry point for dnup application with command parsing
src/Installer/dnup/DotnetVersion.cs Comprehensive .NET version parsing and manipulation logic
src/Installer/dnup/ReleaseManifest.cs Release manifest handling for downloading and resolving .NET versions
src/Installer/dnup/Commands/Sdk/Install/SdkInstallCommand.cs SDK installation command implementation with interactive prompts
test/dnup.Tests/*.cs Unit tests for version parsing, manifest resolution, and installation logic

// Handle Preview channel - get the latest preview version
var productIndex = ProductCollection.GetAsync().GetAwaiter().GetResult();
return GetLatestPreviewVersion(productIndex, mode);
} // Parse the channel string into components
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a missing line break between the closing brace and the comment. This creates a syntax error. The comment should be on a separate line or removed if it's stale.

Suggested change
} // Parse the channel string into components
}
// Parse the channel string into components

Copilot uses AI. Check for mistakes.

}

return null; // No preview versions found
} /// <summary>
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a missing line break between the closing brace and the XML documentation comment. This creates a formatting issue that may cause problems.

Suggested change
} /// <summary>
}
/// <summary>

Copilot uses AI. Check for mistakes.

var manifest = new ReleaseManifest();

var version = manifest.GetLatestVersionForChannel("9.0.1xx", InstallMode.SDK);
Console.WriteLine($"Version found: {version ?? "null"}");
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using Console.WriteLine in unit tests is not recommended. Consider using the test framework's output mechanisms or removing these debug statements.

Copilot uses AI. Check for mistakes.

var manifest = new ReleaseManifest();
var version = manifest.GetLatestVersionForChannel("lts", InstallMode.SDK);

Console.WriteLine($"LTS Version found: {version ?? "null"}");
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using Console.WriteLine in unit tests is not recommended. Consider using the test framework's output mechanisms or removing these debug statements.

Copilot uses AI. Check for mistakes.

var manifest = new ReleaseManifest();
var version = manifest.GetLatestVersionForChannel("sts", InstallMode.SDK);

Console.WriteLine($"STS Version found: {version ?? "null"}");
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using Console.WriteLine in unit tests is not recommended. Consider using the test framework's output mechanisms or removing these debug statements.

Copilot uses AI. Check for mistakes.

var manifest = new ReleaseManifest();
var version = manifest.GetLatestVersionForChannel("preview", InstallMode.SDK);

Console.WriteLine($"Preview Version found: {version ?? "null"}");
Copy link
Preview

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] Using Console.WriteLine in unit tests is not recommended. Consider using the test framework's output mechanisms or removing these debug statements.

Copilot uses AI. Check for mistakes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants