Support installing the ASP.NET Core shared runtime from KoreBuild

This commit is contained in:
Nate McMaster 2017-12-15 16:23:58 -08:00
Родитель 8d2e5b8587
Коммит 8d21533ddd
9 изменённых файлов: 212 добавлений и 70 удалений

Просмотреть файл

@ -380,7 +380,7 @@ function __install_shared_runtime($installScript, $installDir, [string]$arch, [s
Write-Verbose "Installing .NET Core runtime $version"
& $installScript `
-Channel $channel `
-SharedRuntime `
-Runtime 'dotnet' `
-Version $version `
-Architecture $arch `
-InstallDir $installDir `

69
files/KoreBuild/scripts/dotnet-install.ps1 поставляемый
Просмотреть файл

@ -34,8 +34,17 @@
Architecture of dotnet binaries to be installed.
Possible values are: <auto>, x64 and x86
.PARAMETER SharedRuntime
This parameter is obsolete and may be removed in a future version of this script.
The recommended alternative is '-Runtime dotnet'.
Default: false
Installs just the shared runtime bits, not the entire SDK
Installs just the shared runtime bits, not the entire SDK.
This is equivalent to specifying `-Runtime dotnet`.
.PARAMETER Runtime
Installs just a shared runtime, not the entire SDK.
Possible values:
- dotnet
- aspnetcore
.PARAMETER DryRun
If set it will not perform installation but instead display what command line to use to consistently install
currently requested version of dotnet cli. In example if you specify version 'latest' it will display a link
@ -71,6 +80,9 @@ param(
[string]$Version="Latest",
[string]$InstallDir="<auto>",
[string]$Architecture="<auto>",
[ValidateSet("dotnet", "aspnetcore", IgnoreCase = $false)]
[string]$Runtime,
[Obsolete("This parameter may be removed in a future version of this script. The recommended alternative is '-Runtime dotnet'.")]
[switch]$SharedRuntime,
[switch]$DryRun,
[switch]$NoPath,
@ -88,6 +100,10 @@ $ProgressPreference="SilentlyContinue"
$BinFolderRelativePath=""
if ($SharedRuntime -and (-not $Runtime)) {
$Runtime = "dotnet"
}
# example path with regex: shared/1.0.0-beta-12345/somepath
$VersionRegEx="/\d+\.\d+[^/]+/"
$OverrideNonVersionedFiles = !$SkipNonVersionedFiles
@ -231,9 +247,12 @@ function Get-Latest-Version-Info([string]$AzureFeed, [string]$Channel, [bool]$Co
Say-Invocation $MyInvocation
$VersionFileUrl = $null
if ($SharedRuntime) {
if ($Runtime -eq "dotnet") {
$VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.version"
}
elseif ($Runtime -eq "aspnetcore") {
$VersionFileUrl = "$UncachedFeed/Runtime/$Channel/latest.$Runtime.version"
}
else {
if ($Coherent) {
$VersionFileUrl = "$UncachedFeed/Sdk/$Channel/latest.coherent.version"
@ -278,8 +297,8 @@ function Get-Specific-Version-From-Version([string]$AzureFeed, [string]$Channel,
function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) {
Say-Invocation $MyInvocation
if ($SharedRuntime) {
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-runtime-$SpecificVersion-win-$CLIArchitecture.zip"
if ($Runtime) {
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/$Runtime-runtime-$SpecificVersion-win-$CLIArchitecture.zip"
}
else {
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-sdk-$SpecificVersion-win-$CLIArchitecture.zip"
@ -293,11 +312,14 @@ function Get-Download-Link([string]$AzureFeed, [string]$SpecificVersion, [string
function Get-LegacyDownload-Link([string]$AzureFeed, [string]$SpecificVersion, [string]$CLIArchitecture) {
Say-Invocation $MyInvocation
if ($SharedRuntime) {
if (-not $Runtime) {
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip"
}
elseif ($Runtime -eq "dotnet") {
$PayloadURL = "$AzureFeed/Runtime/$SpecificVersion/dotnet-win-$CLIArchitecture.$SpecificVersion.zip"
}
else {
$PayloadURL = "$AzureFeed/Sdk/$SpecificVersion/dotnet-dev-win-$CLIArchitecture.$SpecificVersion.zip"
return $null
}
Say-Verbose "Constructed legacy payload URL: $PayloadURL"
@ -466,7 +488,9 @@ $LegacyDownloadLink = Get-LegacyDownload-Link -AzureFeed $AzureFeed -SpecificVer
if ($DryRun) {
Say "Payload URLs:"
Say "Primary - $DownloadLink"
Say "Legacy - $LegacyDownloadLink"
if ($LegacyDownloadLink) {
Say "Legacy - $LegacyDownloadLink"
}
Say "Repeatable invocation: .\$($MyInvocation.Line)"
exit 0
}
@ -474,15 +498,22 @@ if ($DryRun) {
$InstallRoot = Resolve-Installation-Path $InstallDir
Say-Verbose "InstallRoot: $InstallRoot"
$dotnetPackageRelativePath = if ($SharedRuntime) { "shared\Microsoft.NETCore.App" } else { "sdk" }
if ($Runtime -eq "dotnet") {
$assetName = ".NET Core Runtime"
$dotnetPackageRelativePath = "shared\Microsoft.NETCore.App"
}
elseif ($Runtime -eq "aspnetcore") {
$assetName = "ASP.NET Core Runtime"
$dotnetPackageRelativePath = "shared\Microsoft.AspNetCore.All"
}
else {
$assetName = ".NET Core SDK"
$dotnetPackageRelativePath = "sdk"
}
$isAssetInstalled = Is-Dotnet-Package-Installed -InstallRoot $InstallRoot -RelativePathToPackage $dotnetPackageRelativePath -SpecificVersion $SpecificVersion
if ($isAssetInstalled) {
if ($SharedRuntime) {
Say ".NET Core Runtime version $SpecificVersion is already installed."
} else {
Say ".NET Core SDK version $SpecificVersion is already installed."
}
Say "$assetname version $SpecificVersion is already installed."
Prepend-Sdk-InstallRoot-To-Path -InstallRoot $InstallRoot -BinFolderRelativePath $BinFolderRelativePath
exit 0
}
@ -504,11 +535,13 @@ try {
}
catch {
Say "Cannot download: $DownloadLink"
$DownloadLink = $LegacyDownloadLink
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
Say-Verbose "Legacy zip path: $ZipPath"
Say "Downloading legacy link: $DownloadLink"
DownloadFile -Uri $DownloadLink -OutPath $ZipPath
if ($LegacyDownloadLink) {
$DownloadLink = $LegacyDownloadLink
$ZipPath = [System.IO.Path]::combine([System.IO.Path]::GetTempPath(), [System.IO.Path]::GetRandomFileName())
Say-Verbose "Legacy zip path: $ZipPath"
Say "Downloading legacy link: $DownloadLink"
DownloadFile -Uri $DownloadLink -OutPath $ZipPath
}
}
Say "Extracting zip from $DownloadLink"

68
files/KoreBuild/scripts/dotnet-install.sh поставляемый
Просмотреть файл

@ -39,6 +39,10 @@ if [ -t 1 ]; then
fi
fi
say_warning() {
printf "%b\n" "${yellow:-}dotnet_install: Warning: $1${normal:-}"
}
say_err() {
printf "%b\n" "${red:-}dotnet_install: Error: $1${normal:-}" >&2
}
@ -380,8 +384,10 @@ get_latest_version_info() {
local coherent="$4"
local version_file_url=null
if [ "$shared_runtime" = true ]; then
if [[ "$runtime" == "dotnet" ]]; then
version_file_url="$uncached_feed/Runtime/$channel/latest.version"
elif [ ! -z "$runtime" ]; then
version_file_url="$uncached_feed/Runtime/$channel/latest.$runtime.version"
else
if [ "$coherent" = true ]; then
version_file_url="$uncached_feed/Sdk/$channel/latest.coherent.version"
@ -447,8 +453,8 @@ construct_download_link() {
osname="$(get_current_os_name)" || return 1
local download_link=null
if [ "$shared_runtime" = true ]; then
download_link="$azure_feed/Runtime/$specific_version/dotnet-runtime-$specific_version-$osname-$normalized_architecture.tar.gz"
if [ ! -z "$runtime" ]; then
download_link="$azure_feed/Runtime/$specific_version/$runtime-runtime-$specific_version-$osname-$normalized_architecture.tar.gz"
else
download_link="$azure_feed/Sdk/$specific_version/dotnet-sdk-$specific_version-$osname-$normalized_architecture.tar.gz"
fi
@ -474,10 +480,12 @@ construct_legacy_download_link() {
distro_specific_osname="$(get_legacy_os_name)" || return 1
local legacy_download_link=null
if [ "$shared_runtime" = true ]; then
if [[ "$runtime" == "dotnet" ]]; then
legacy_download_link="$azure_feed/Runtime/$specific_version/dotnet-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz"
else
elif [ -z "$runtime" ]; then
legacy_download_link="$azure_feed/Sdk/$specific_version/dotnet-dev-$distro_specific_osname-$normalized_architecture.$specific_version.tar.gz"
else
return 1
fi
echo "$legacy_download_link"
@ -691,17 +699,23 @@ calculate_vars() {
install_dotnet() {
eval $invocation
local download_failed=false
local asset_name=''
local asset_relative_path=''
if [ "$shared_runtime" = true ]; then
if is_dotnet_package_installed "$install_root" "shared/Microsoft.NETCore.App" "$specific_version"; then
say ".NET Core Runtime version $specific_version is already installed."
return 0
fi
if [[ "$runtime" == "dotnet" ]]; then
asset_relative_path="shared/Microsoft.NETCore.App"
asset_name=".NET Core Runtime"
elif [[ "$runtime" == "aspnetcore" ]]; then
asset_relative_path="shared/Microsoft.AspNetCore.All"
asset_name="ASP.NET Core Runtime"
else
if is_dotnet_package_installed "$install_root" "sdk" "$specific_version"; then
say ".NET Core SDK version $specific_version is already installed."
return 0
fi
asset_relative_path="sdk"
asset_name=".NET Core SDK"
fi
if is_dotnet_package_installed "$install_root" "$asset_relative_path" "$specific_version"; then
say "$asset_name version $specific_version is already installed."
return 0
fi
mkdir -p "$install_root"
@ -744,7 +758,7 @@ azure_feed="https://dotnetcli.azureedge.net/dotnet"
uncached_feed="https://dotnetcli.blob.core.windows.net/dotnet"
feed_credential=""
verbose=false
shared_runtime=false
runtime=""
runtime_id=""
override_non_versioned_files=true
@ -769,7 +783,18 @@ do
architecture="$1"
;;
--shared-runtime|-[Ss]hared[Rr]untime)
shared_runtime=true
say_warning "The --shared-runtime flag is obsolete and may be removed in a future version of this script. The recommended usage is to specify '--runtime dotnet'."
if [ -z "$runtime" ]; then
runtime="dotnet"
fi
;;
--runtime|-[Rr]untime)
shift
runtime="$1"
if [[ "$runtime" != "dotnet" ]] && [[ "$runtime" != "aspnetcore" ]]; then
say_err "Unsupported value for --runtime: '$1'. Valid values are 'dotnet' and 'aspnetcore'."
exit 1
fi
;;
--dry-run|-[Dd]ry[Rr]un)
dry_run=true
@ -829,8 +854,11 @@ do
echo " -InstallDir"
echo " --architecture <ARCHITECTURE> Architecture of .NET Tools. Currently only x64 is supported."
echo " --arch,-Architecture,-Arch"
echo " --shared-runtime Installs just the shared runtime bits, not the entire SDK."
echo " -SharedRuntime"
echo " --runtime <RUNTIME> Installs a shared runtime only, without the SDK."
echo " -Runtime"
echo " Possible values:"
echo " - dotnet - the Microsoft.NETCore.App shared framework"
echo " - aspnetcore - the Microsoft.AspNetCore.All shared framework"
echo " --skip-non-versioned-files Skips non-versioned files if they already exist, such as the dotnet executable."
echo " -SkipNonVersionedFiles"
echo " --dry-run,-DryRun Do not perform installation. Display download link."
@ -843,6 +871,10 @@ do
echo " -RuntimeId"
echo " -?,--?,-h,--help,-Help Shows this help message"
echo ""
echo "Obsolete parameters:"
echo " --shared-runtime The recommended alternative is '--runtime dotnet'."
echo " -SharedRuntime Installs just the shared runtime bits, not the entire SDK."
echo ""
echo "Install Location:"
echo " Location is chosen in following order:"
echo " - --install-dir option"

Просмотреть файл

@ -20,7 +20,7 @@ __install_shared_runtime() {
"$__script_dir/dotnet-install.sh" \
--install-dir "$install_dir" \
--architecture x64 \
--shared-runtime \
--runtime 'dotnet' \
--skip-non-versioned-files \
--channel "$channel" \
--version "$version" \

Просмотреть файл

@ -27,7 +27,7 @@ namespace KoreBuild.Tasks
/// Supported metadata:
/// Channel: default is ''
/// Arch: default is 'x64'
/// SharedRuntime: default is 'false'
/// Runtime: default is ''
/// InstallDir: default is ''. When not specified <see cref="DotNetHome"/> and the location of the currently executing dotnet.exe process will be used to determine the install path.
/// </summary>
[Required]
@ -98,9 +98,10 @@ namespace KoreBuild.Tasks
arguments.Add("-InstallDir");
arguments.Add(installDir);
if (request.IsSharedRuntime)
if (!string.IsNullOrEmpty(request.RuntimeName))
{
arguments.Add("-SharedRuntime");
arguments.Add("-Runtime");
arguments.Add(request.RuntimeName);
}
arguments.Add("-Version");
@ -108,7 +109,7 @@ namespace KoreBuild.Tasks
var isFloatingVersion = request.Version.Equals("latest", StringComparison.OrdinalIgnoreCase)
|| request.Version.Equals("coherent", StringComparison.OrdinalIgnoreCase);
var assetName = $".NET Core { (request.IsSharedRuntime ? "runtime" : "sdk") } ({arch}) {request.Version}";
var assetName = $"{request.DisplayName} ({arch}) {request.Version}";
if (!string.IsNullOrEmpty(request.Channel))
{
@ -131,11 +132,7 @@ namespace KoreBuild.Tasks
arguments.Add(request.FeedCredential);
}
var expectedPath = request.IsSharedRuntime && !isFloatingVersion
? Path.Combine(installDir, "shared", "Microsoft.NETCore.App", request.Version, ".version")
: Path.Combine(installDir, "sdk", request.Version, "dotnet.dll");
if (File.Exists(expectedPath))
if (!isFloatingVersion && request.IsInstalled(installDir))
{
Log.LogMessage(MessageImportance.Normal, $"{assetName} is already installed. Skipping installation.");
continue;
@ -160,7 +157,7 @@ namespace KoreBuild.Tasks
EnableRaisingEvents = true,
})
{
Log.LogMessage(MessageImportance.Normal, $"Executing {process.StartInfo.FileName} {process.StartInfo.Arguments}");
Log.LogCommandLine(MessageImportance.Normal, $"Executing {process.StartInfo.FileName} {process.StartInfo.Arguments}");
var collectedOutput = new List<string>();
process.OutputDataReceived += (o, e) => collectedOutput.Add(e.Data ?? string.Empty);
@ -252,26 +249,45 @@ namespace KoreBuild.Tasks
private IEnumerable<DotNetAssetRequest> CreateAssetRequests()
{
var all = new List<DotNetAssetRequest>();
var requests = new List<DotNetAssetRequest>();
var dotnetRuntimes = new List<DotNetAssetRequest>();
var aspnetcoreRuntimes = new List<DotNetAssetRequest>();
foreach (var item in Assets)
{
var request = new DotNetAssetRequest(item.ItemSpec)
{
IsSharedRuntime = bool.TryParse(item.GetMetadata("SharedRuntime"), out var sharedRuntime) && sharedRuntime,
Channel = item.GetMetadata("Channel"),
InstallDir = item.GetMetadata("InstallDir"),
Arch = item.GetMetadata("Arch"),
// trimmed because dotnet-install.ps1/sh expect the feed not to have this
Feed = item.GetMetadata("Feed")?.TrimEnd(new[] { '/', '\\' }),
FeedCredential = item.GetMetadata("FeedCredential"),
};
DotNetAssetRequest request;
all.Add(request);
switch (item.GetMetadata("Runtime").ToLowerInvariant())
{
case "aspnetcore":
request = new DotNetAssetRequest.AspNetCoreRuntime(item.ItemSpec);
aspnetcoreRuntimes.Add(request);
break;
case "dotnet":
request = new DotNetAssetRequest.DotNetRuntime(item.ItemSpec);
dotnetRuntimes.Add(request);
break;
default:
request = new DotNetAssetRequest.DotNetSdk(item.ItemSpec);
requests.Add(request);
break;
}
request.Channel = item.GetMetadata("Channel");
request.InstallDir = item.GetMetadata("InstallDir");
request.Arch = item.GetMetadata("Arch");
// trimmed because dotnet-install.ps1/sh expect the feed not to have this
request.Feed = item.GetMetadata("Feed")?.TrimEnd(new[] { '/', '\\' });
request.FeedCredential = item.GetMetadata("FeedCredential");
}
// installs SDKs first, which often bundle a shared runtime...making the shared runtime download unnecessary.
return all.Where(r => !r.IsSharedRuntime)
.Concat(all.Where(r => r.IsSharedRuntime));
// A cheap attempt to reduce the number of things we download.
// dotnet-sdk.zip often bundles shared runtimes, making susquent downloads unnecessary.
// likewise, aspnetcore-runtime.zip bundles Microsoft.NETCore.App, so we can often skip the dotnet-runtime download
return requests
.Concat(aspnetcoreRuntimes)
.Concat(dotnetRuntimes);
}
}
}

Просмотреть файл

@ -2,10 +2,11 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
namespace KoreBuild.Tasks
{
internal class DotNetAssetRequest
internal abstract class DotNetAssetRequest
{
public DotNetAssetRequest(string version)
{
@ -13,11 +14,56 @@ namespace KoreBuild.Tasks
}
public string Version { get; }
public bool IsSharedRuntime { get; set; }
public abstract string RuntimeName { get; }
public abstract string DisplayName { get; }
public string Channel { get; set; }
public string InstallDir { get; set; }
public string Arch { get; set; }
public string Feed { get; set; }
public string FeedCredential { get; set; }
public abstract bool IsInstalled(string basePath);
public class DotNetSdk : DotNetAssetRequest
{
public DotNetSdk(string version) : base(version)
{
}
public override string RuntimeName { get; }
public override string DisplayName { get; } = ".NET Core SDK";
public override bool IsInstalled(string basePath)
=> File.Exists(Path.Combine(basePath, "sdk", Version, "dotnet.dll"));
}
public class DotNetRuntime : DotNetAssetRequest
{
public DotNetRuntime(string version) : base(version)
{
}
public override string RuntimeName { get; } = "dotnet";
public override string DisplayName { get; } = ".NET Core Runtime";
public override bool IsInstalled(string basePath)
=> File.Exists(Path.Combine(basePath, "shared", "Microsoft.NETCore.App", Version, ".version"));
}
public class AspNetCoreRuntime : DotNetAssetRequest
{
public AspNetCoreRuntime(string version) : base(version)
{
}
public override string RuntimeName { get; } = "aspnetcore";
public override string DisplayName { get; } = "ASP.NET Core Runtime";
public override bool IsInstalled(string basePath)
=> File.Exists(Path.Combine(basePath, "shared", "Microsoft.AspNetCore.All", Version, ".version"));
}
}
}

Просмотреть файл

@ -29,6 +29,21 @@
</PropertyGroup>
<ItemDefinitionGroup>
<!--
Specifies a required ASP.NET Core runtime.
Examples:
<AspNetCoreRuntime Include="2.1.0-preview1-1234" />
-->
<AspNetCoreRuntime>
<Arch>$(DefaultDotNetAssetArch)</Arch>
<Runtime>aspnetcore</Runtime>
<Channel></Channel>
<InstallDir></InstallDir>
<Feed>$(DefaultDotNetAssetFeed)</Feed>
<FeedCredential>$(DefaultDotNetAssetFeedCredential)</FeedCredential>
</AspNetCoreRuntime>
<!--
Specifies a required .NET Core runtime.
@ -40,7 +55,7 @@
-->
<DotNetCoreRuntime>
<Arch>$(DefaultDotNetAssetArch)</Arch>
<SharedRuntime>true</SharedRuntime>
<Runtime>dotnet</Runtime>
<Channel></Channel>
<InstallDir></InstallDir>
<Feed>$(DefaultDotNetAssetFeed)</Feed>
@ -55,7 +70,7 @@
-->
<DotNetCoreSdk>
<Arch>$(DefaultDotNetAssetArch)</Arch>
<SharedRuntime>false</SharedRuntime>
<Runtime></Runtime>
<Channel></Channel>
<InstallDir></InstallDir>
<Feed>$(DefaultDotNetAssetFeed)</Feed>

Просмотреть файл

@ -32,7 +32,7 @@ namespace KoreBuild.Tasks.Tests
var request = new TaskItem("1.0.5", new Hashtable
{
["SharedRuntime"] = "true",
["Runtime"] = "dotnet",
["InstallDir"] = path
});
@ -66,7 +66,7 @@ namespace KoreBuild.Tasks.Tests
var request = new TaskItem("999.999.999", new Hashtable
{
["SharedRuntime"] = "true",
["Runtime"] = "dotnet",
["InstallDir"] = path
});

Просмотреть файл

@ -138,7 +138,7 @@ namespace KoreBuild.Console.Commands
var args = ArgumentEscaper.EscapeAndConcatenate(new string[]
{
"-Channel", channel,
"-SharedRuntime",
"-Runtime", "dotnet",
"-Version", version,
"-Architecture", architecture,
"-InstallDir", installDir