diff --git a/eng/pipelines/templates/stages/source-build-stages.yml b/eng/pipelines/templates/stages/source-build-stages.yml
index a149ecc9eef..83eae0a477a 100644
--- a/eng/pipelines/templates/stages/source-build-stages.yml
+++ b/eng/pipelines/templates/stages/source-build-stages.yml
@@ -121,6 +121,8 @@ stages:
withPreviousSDK: false # 🚫
disableSigning: true # ✅
createSourceArtifacts: false # 🚫
+ ${{ if in(parameters.scope, 'lite') }}:
+ extraProperties: /p:DotNetSkipTestsRequiringMicrosoftArtifacts=true
- ${{ if containsValue(parameters.verifications, 'source-build-stage2') }}:
@@ -136,6 +138,8 @@ stages:
disableSigning: true # ✅
createSourceArtifacts: false # 🚫
reuseBuildArtifactsFrom: 'SB_{0}_Online_MsftSdk_x64'
+ ${{ if in(parameters.scope, 'lite') }}:
+ extraProperties: /p:DotNetSkipTestsRequiringMicrosoftArtifacts=true
### Additional legs for full build ###
- ${{ if in(parameters.scope, 'full') }}:
diff --git a/src/arcade/Arcade.slnx b/src/arcade/Arcade.slnx
index a4c51eaafd6..337ee9c2279 100644
--- a/src/arcade/Arcade.slnx
+++ b/src/arcade/Arcade.slnx
@@ -29,6 +29,7 @@
+
diff --git a/src/arcade/eng/Version.Details.xml b/src/arcade/eng/Version.Details.xml
index 8e4ff3e2e9b..1a9d65f0b49 100644
--- a/src/arcade/eng/Version.Details.xml
+++ b/src/arcade/eng/Version.Details.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/src/arcade/eng/common/SetupNugetSources.ps1 b/src/arcade/eng/common/SetupNugetSources.ps1
index 9445c314325..fc8d618014e 100644
--- a/src/arcade/eng/common/SetupNugetSources.ps1
+++ b/src/arcade/eng/common/SetupNugetSources.ps1
@@ -7,7 +7,7 @@
# See example call for this script below.
#
# - task: PowerShell@2
-# displayName: Setup Private Feeds Credentials
+# displayName: Setup internal Feeds Credentials
# condition: eq(variables['Agent.OS'], 'Windows_NT')
# inputs:
# filePath: $(System.DefaultWorkingDirectory)/eng/common/SetupNugetSources.ps1
@@ -34,19 +34,28 @@ Set-StrictMode -Version 2.0
. $PSScriptRoot\tools.ps1
+# Adds or enables the package source with the given name
+function AddOrEnablePackageSource($sources, $disabledPackageSources, $SourceName, $SourceEndPoint, $creds, $Username, $pwd) {
+ if ($disabledPackageSources -eq $null -or -not (EnableInternalPackageSource -DisabledPackageSources $disabledPackageSources -Creds $creds -PackageSourceName $SourceName)) {
+ AddPackageSource -Sources $sources -SourceName $SourceName -SourceEndPoint $SourceEndPoint -Creds $creds -Username $userName -pwd $Password
+ }
+}
+
# Add source entry to PackageSources
function AddPackageSource($sources, $SourceName, $SourceEndPoint, $creds, $Username, $pwd) {
$packageSource = $sources.SelectSingleNode("add[@key='$SourceName']")
if ($packageSource -eq $null)
{
+ Write-Host "Adding package source $SourceName"
+
$packageSource = $doc.CreateElement("add")
$packageSource.SetAttribute("key", $SourceName)
$packageSource.SetAttribute("value", $SourceEndPoint)
$sources.AppendChild($packageSource) | Out-Null
}
else {
- Write-Host "Package source $SourceName already present."
+ Write-Host "Package source $SourceName already present and enabled."
}
AddCredential -Creds $creds -Source $SourceName -Username $Username -pwd $pwd
@@ -59,6 +68,8 @@ function AddCredential($creds, $source, $username, $pwd) {
return;
}
+ Write-Host "Inserting credential for feed: " $source
+
# Looks for credential configuration for the given SourceName. Create it if none is found.
$sourceElement = $creds.SelectSingleNode($Source)
if ($sourceElement -eq $null)
@@ -91,24 +102,27 @@ function AddCredential($creds, $source, $username, $pwd) {
$passwordElement.SetAttribute("value", $pwd)
}
-function InsertMaestroPrivateFeedCredentials($Sources, $Creds, $Username, $pwd) {
- $maestroPrivateSources = $Sources.SelectNodes("add[contains(@key,'darc-int')]")
-
- Write-Host "Inserting credentials for $($maestroPrivateSources.Count) Maestro's private feeds."
-
- ForEach ($PackageSource in $maestroPrivateSources) {
- Write-Host "`tInserting credential for Maestro's feed:" $PackageSource.Key
- AddCredential -Creds $creds -Source $PackageSource.Key -Username $Username -pwd $pwd
+# Enable all darc-int package sources.
+function EnableMaestroInternalPackageSources($DisabledPackageSources, $Creds) {
+ $maestroInternalSources = $DisabledPackageSources.SelectNodes("add[contains(@key,'darc-int')]")
+ ForEach ($DisabledPackageSource in $maestroInternalSources) {
+ EnableInternalPackageSource -DisabledPackageSources $DisabledPackageSources -Creds $Creds -PackageSourceName $DisabledPackageSource.key
}
}
-function EnablePrivatePackageSources($DisabledPackageSources) {
- $maestroPrivateSources = $DisabledPackageSources.SelectNodes("add[contains(@key,'darc-int')]")
- ForEach ($DisabledPackageSource in $maestroPrivateSources) {
- Write-Host "`tEnsuring private source '$($DisabledPackageSource.key)' is enabled by deleting it from disabledPackageSource"
+# Enables an internal package source by name, if found. Returns true if the package source was found and enabled, false otherwise.
+function EnableInternalPackageSource($DisabledPackageSources, $Creds, $PackageSourceName) {
+ $DisabledPackageSource = $DisabledPackageSources.SelectSingleNode("add[@key='$PackageSourceName']")
+ if ($DisabledPackageSource) {
+ Write-Host "Enabling internal source '$($DisabledPackageSource.key)'."
+
# Due to https://github.com/NuGet/Home/issues/10291, we must actually remove the disabled entries
$DisabledPackageSources.RemoveChild($DisabledPackageSource)
+
+ AddCredential -Creds $creds -Source $DisabledPackageSource.Key -Username $userName -pwd $Password
+ return $true
}
+ return $false
}
if (!(Test-Path $ConfigFile -PathType Leaf)) {
@@ -121,15 +135,17 @@ $doc = New-Object System.Xml.XmlDocument
$filename = (Get-Item $ConfigFile).FullName
$doc.Load($filename)
-# Get reference to or create one if none exist already
+# Get reference to - fail if none exist
$sources = $doc.DocumentElement.SelectSingleNode("packageSources")
if ($sources -eq $null) {
- $sources = $doc.CreateElement("packageSources")
- $doc.DocumentElement.AppendChild($sources) | Out-Null
+ Write-PipelineTelemetryError -Category 'Build' -Message "Eng/common/SetupNugetSources.ps1 returned a non-zero exit code. NuGet config file must contain a packageSources section: $ConfigFile"
+ ExitWithExitCode 1
}
$creds = $null
+$feedSuffix = "v3/index.json"
if ($Password) {
+ $feedSuffix = "v2"
# Looks for a node. Create it if none is found.
$creds = $doc.DocumentElement.SelectSingleNode("packageSourceCredentials")
if ($creds -eq $null) {
@@ -138,33 +154,22 @@ if ($Password) {
}
}
+$userName = "dn-bot"
+
# Check for disabledPackageSources; we'll enable any darc-int ones we find there
$disabledSources = $doc.DocumentElement.SelectSingleNode("disabledPackageSources")
if ($disabledSources -ne $null) {
Write-Host "Checking for any darc-int disabled package sources in the disabledPackageSources node"
- EnablePrivatePackageSources -DisabledPackageSources $disabledSources
-}
-
-$userName = "dn-bot"
-
-# Insert credential nodes for Maestro's private feeds
-InsertMaestroPrivateFeedCredentials -Sources $sources -Creds $creds -Username $userName -pwd $Password
-
-# 3.1 uses a different feed url format so it's handled differently here
-$dotnet31Source = $sources.SelectSingleNode("add[@key='dotnet3.1']")
-if ($dotnet31Source -ne $null) {
- AddPackageSource -Sources $sources -SourceName "dotnet3.1-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal/nuget/v2" -Creds $creds -Username $userName -pwd $Password
- AddPackageSource -Sources $sources -SourceName "dotnet3.1-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/_packaging/dotnet3.1-internal-transport/nuget/v2" -Creds $creds -Username $userName -pwd $Password
+ EnableMaestroInternalPackageSources -DisabledPackageSources $disabledSources -Creds $creds
}
-
$dotnetVersions = @('5','6','7','8','9','10')
foreach ($dotnetVersion in $dotnetVersions) {
$feedPrefix = "dotnet" + $dotnetVersion;
$dotnetSource = $sources.SelectSingleNode("add[@key='$feedPrefix']")
if ($dotnetSource -ne $null) {
- AddPackageSource -Sources $sources -SourceName "$feedPrefix-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal/nuget/v2" -Creds $creds -Username $userName -pwd $Password
- AddPackageSource -Sources $sources -SourceName "$feedPrefix-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal-transport/nuget/v2" -Creds $creds -Username $userName -pwd $Password
+ AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "$feedPrefix-internal" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal/nuget/$feedSuffix" -Creds $creds -Username $userName -pwd $Password
+ AddOrEnablePackageSource -Sources $sources -DisabledPackageSources $disabledSources -SourceName "$feedPrefix-internal-transport" -SourceEndPoint "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$feedPrefix-internal-transport/nuget/$feedSuffix" -Creds $creds -Username $userName -pwd $Password
}
}
diff --git a/src/arcade/eng/common/SetupNugetSources.sh b/src/arcade/eng/common/SetupNugetSources.sh
index ddf4efc81a4..dd2564aef01 100755
--- a/src/arcade/eng/common/SetupNugetSources.sh
+++ b/src/arcade/eng/common/SetupNugetSources.sh
@@ -52,78 +52,126 @@ if [[ `uname -s` == "Darwin" ]]; then
TB=''
fi
-# Ensure there is a ... section.
-grep -i "" $ConfigFile
-if [ "$?" != "0" ]; then
- echo "Adding ... section."
- ConfigNodeHeader=""
- PackageSourcesTemplate="${TB}${NL}${TB}"
+# Enables an internal package source by name, if found. Returns 0 if found and enabled, 1 if not found.
+EnableInternalPackageSource() {
+ local PackageSourceName="$1"
+
+ # Check if disabledPackageSources section exists
+ grep -i "" "$ConfigFile" > /dev/null
+ if [ "$?" != "0" ]; then
+ return 1 # No disabled sources section
+ fi
+
+ # Check if this source name is disabled
+ grep -i " /dev/null
+ if [ "$?" == "0" ]; then
+ echo "Enabling internal source '$PackageSourceName'."
+ # Remove the disabled entry
+ local OldDisableValue=""
+ local NewDisableValue=""
+ sed -i.bak "s|$OldDisableValue|$NewDisableValue|" "$ConfigFile"
+
+ # Add the source name to PackageSources for credential handling
+ PackageSources+=("$PackageSourceName")
+ return 0 # Found and enabled
+ fi
+
+ return 1 # Not found in disabled sources
+}
+
+# Add source entry to PackageSources
+AddPackageSource() {
+ local SourceName="$1"
+ local SourceEndPoint="$2"
+
+ # Check if source already exists
+ grep -i " /dev/null
+ if [ "$?" == "0" ]; then
+ echo "Package source $SourceName already present and enabled."
+ PackageSources+=("$SourceName")
+ return
+ fi
+
+ echo "Adding package source $SourceName"
+ PackageSourcesNodeFooter=""
+ PackageSourceTemplate="${TB}"
+
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" "$ConfigFile"
+ PackageSources+=("$SourceName")
+}
+
+# Adds or enables the package source with the given name
+AddOrEnablePackageSource() {
+ local SourceName="$1"
+ local SourceEndPoint="$2"
+
+ # Try to enable if disabled, if not found then add new source
+ EnableInternalPackageSource "$SourceName"
+ if [ "$?" != "0" ]; then
+ AddPackageSource "$SourceName" "$SourceEndPoint"
+ fi
+}
- sed -i.bak "s|$ConfigNodeHeader|$ConfigNodeHeader${NL}$PackageSourcesTemplate|" $ConfigFile
-fi
+# Enable all darc-int package sources
+EnableMaestroInternalPackageSources() {
+ # Check if disabledPackageSources section exists
+ grep -i "" "$ConfigFile" > /dev/null
+ if [ "$?" != "0" ]; then
+ return # No disabled sources section
+ fi
+
+ # Find all darc-int disabled sources
+ local DisabledDarcIntSources=()
+ DisabledDarcIntSources+=$(grep -oh '"darc-int-[^"]*" value="true"' "$ConfigFile" | tr -d '"')
+
+ for DisabledSourceName in ${DisabledDarcIntSources[@]} ; do
+ if [[ $DisabledSourceName == darc-int* ]]; then
+ EnableInternalPackageSource "$DisabledSourceName"
+ fi
+ done
+}
-# Ensure there is a ... section.
-grep -i "" $ConfigFile
+# Ensure there is a ... section.
+grep -i "" $ConfigFile
if [ "$?" != "0" ]; then
- echo "Adding ... section."
-
- PackageSourcesNodeFooter=""
- PackageSourceCredentialsTemplate="${TB}${NL}${TB}"
-
- sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourcesNodeFooter${NL}$PackageSourceCredentialsTemplate|" $ConfigFile
+ Write-PipelineTelemetryError -Category 'Build' "Error: Eng/common/SetupNugetSources.sh returned a non-zero exit code. NuGet config file must contain a packageSources section: $ConfigFile"
+ ExitWithExitCode 1
fi
PackageSources=()
-# Ensure dotnet3.1-internal and dotnet3.1-internal-transport are in the packageSources if the public dotnet3.1 feeds are present
-grep -i "... section.
+ grep -i "" $ConfigFile
if [ "$?" != "0" ]; then
- echo "Adding dotnet3.1-internal to the packageSources."
- PackageSourcesNodeFooter=""
- PackageSourceTemplate="${TB}"
+ echo "Adding ... section."
- sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
- fi
- PackageSources+=('dotnet3.1-internal')
-
- grep -i "" $ConfigFile
- if [ "$?" != "0" ]; then
- echo "Adding dotnet3.1-internal-transport to the packageSources."
PackageSourcesNodeFooter=""
- PackageSourceTemplate="${TB}"
+ PackageSourceCredentialsTemplate="${TB}${NL}${TB}"
- sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
+ sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourcesNodeFooter${NL}$PackageSourceCredentialsTemplate|" $ConfigFile
fi
- PackageSources+=('dotnet3.1-internal-transport')
+fi
+
+# Check for disabledPackageSources; we'll enable any darc-int ones we find there
+grep -i "" $ConfigFile > /dev/null
+if [ "$?" == "0" ]; then
+ echo "Checking for any darc-int disabled package sources in the disabledPackageSources node"
+ EnableMaestroInternalPackageSources
fi
DotNetVersions=('5' '6' '7' '8' '9' '10')
for DotNetVersion in ${DotNetVersions[@]} ; do
FeedPrefix="dotnet${DotNetVersion}";
- grep -i " /dev/null
if [ "$?" == "0" ]; then
- grep -i ""
-
- sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
- fi
- PackageSources+=("$FeedPrefix-internal")
-
- grep -i "" $ConfigFile
- if [ "$?" != "0" ]; then
- echo "Adding $FeedPrefix-internal-transport to the packageSources."
- PackageSourcesNodeFooter=""
- PackageSourceTemplate="${TB}"
-
- sed -i.bak "s|$PackageSourcesNodeFooter|$PackageSourceTemplate${NL}$PackageSourcesNodeFooter|" $ConfigFile
- fi
- PackageSources+=("$FeedPrefix-internal-transport")
+ AddOrEnablePackageSource "$FeedPrefix-internal" "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$FeedPrefix-internal/nuget/$FeedSuffix"
+ AddOrEnablePackageSource "$FeedPrefix-internal-transport" "https://pkgs.dev.azure.com/dnceng/internal/_packaging/$FeedPrefix-internal-transport/nuget/$FeedSuffix"
fi
done
@@ -139,29 +187,12 @@ if [ "$CredToken" ]; then
# Check if there is no existing credential for this FeedName
grep -i "<$FeedName>" $ConfigFile
if [ "$?" != "0" ]; then
- echo "Adding credentials for $FeedName."
+ echo " Inserting credential for feed: $FeedName"
PackageSourceCredentialsNodeFooter=""
- NewCredential="${TB}${TB}<$FeedName>${NL}${NL}${NL}$FeedName>"
+ NewCredential="${TB}${TB}<$FeedName>${NL}${TB}${NL}${TB}${TB}${NL}${TB}${TB}$FeedName>"
sed -i.bak "s|$PackageSourceCredentialsNodeFooter|$NewCredential${NL}$PackageSourceCredentialsNodeFooter|" $ConfigFile
fi
done
fi
-
-# Re-enable any entries in disabledPackageSources where the feed name contains darc-int
-grep -i "" $ConfigFile
-if [ "$?" == "0" ]; then
- DisabledDarcIntSources=()
- echo "Re-enabling any disabled \"darc-int\" package sources in $ConfigFile"
- DisabledDarcIntSources+=$(grep -oh '"darc-int-[^"]*" value="true"' $ConfigFile | tr -d '"')
- for DisabledSourceName in ${DisabledDarcIntSources[@]} ; do
- if [[ $DisabledSourceName == darc-int* ]]
- then
- OldDisableValue=""
- NewDisableValue=""
- sed -i.bak "s|$OldDisableValue|$NewDisableValue|" $ConfigFile
- echo "Neutralized disablePackageSources entry for '$DisabledSourceName'"
- fi
- done
-fi
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/BoundaryConditionTests.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/BoundaryConditionTests.cs
new file mode 100644
index 00000000000..96366159bed
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/BoundaryConditionTests.cs
@@ -0,0 +1,186 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using FluentAssertions;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ public class BoundaryConditionTests : IClassFixture, IDisposable
+ {
+ private readonly ScriptRunner _scriptRunner;
+ private readonly string _testOutputDirectory;
+
+ public BoundaryConditionTests(SetupNugetSourcesFixture fixture)
+ {
+ _testOutputDirectory = Path.Combine(Path.GetTempPath(), "SetupNugetSourcesTests", Guid.NewGuid().ToString());
+ Directory.CreateDirectory(_testOutputDirectory);
+ _scriptRunner = fixture.ScriptRunner;
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (Directory.Exists(_testOutputDirectory))
+ {
+ Directory.Delete(_testOutputDirectory, true);
+ }
+ }
+ catch { }
+ }
+
+ [Fact]
+ public async Task EmptyConfiguration_FailsWithoutPackageSourcesSection()
+ {
+ // Arrange
+ var originalConfig = @"
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(1, "Script should fail when packageSources section is missing");
+
+ // Check both output and error for the message (scripts may write to stdout instead of stderr)
+ var errorMessage = string.IsNullOrEmpty(result.error) ? result.output : result.error;
+ errorMessage.Should().Contain("packageSources section", "should report missing packageSources section error");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Config should remain unchanged when script fails
+ modifiedConfig.Should().BeEquivalentTo(originalConfig, "config should not be modified when script fails");
+ }
+
+ [Fact]
+ public async Task ConfigWithoutPackageSourcesSection_FailsWithoutPackageSourcesSection()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(1, "Script should fail when packageSources section is missing");
+ // Check both output and error for the message (scripts may write to stdout instead of stderr)
+ var errorMessage = string.IsNullOrEmpty(result.error) ? result.output : result.error;
+ errorMessage.Should().Contain("packageSources section", "should report missing packageSources section error");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Config should remain unchanged when script fails
+ modifiedConfig.Should().BeEquivalentTo(originalConfig, "config should not be modified when script fails");
+ }
+
+ [Fact]
+ public async Task ConfigWithMissingDisabledPackageSourcesSection_StillAddsInternalFeeds()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should still add internal feeds
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal");
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport");
+ }
+
+ [Fact]
+ public async Task NonExistentConfigFile_ReturnsError()
+ {
+ // Arrange
+ var nonExistentPath = Path.Combine(_testOutputDirectory, "nonexistent.config");
+ // Act
+ var result = await _scriptRunner.RunScript(nonExistentPath);
+
+ // Assert
+ result.exitCode.Should().Be(1, "should return error code for nonexistent file");
+ // Check both output and error for the message (scripts may write to stdout instead of stderr)
+ var errorMessage = string.IsNullOrEmpty(result.error) ? result.output : result.error;
+ errorMessage.Should().Contain("Couldn't find the NuGet config file", "should report missing file error");
+ }
+
+ [Fact]
+ public async Task ConfigWithOnlyDisabledSources_FailsWithoutPackageSourcesSection()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(1, "Script should fail when packageSources section is missing");
+ // Check both output and error for the message (scripts may write to stdout instead of stderr)
+ var errorMessage = string.IsNullOrEmpty(result.error) ? result.output : result.error;
+ errorMessage.Should().Contain("packageSources section", "should report missing packageSources section error");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Config should remain unchanged when script fails
+ modifiedConfig.Should().BeEquivalentTo(originalConfig, "config should not be modified when script fails");
+ }
+
+ [Fact]
+ public async Task ConfigWithEmptyPackageSourcesSection_HandlesCorrectly()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should enable darc-int feeds but not add any dotnet internal feeds since no dotnet feeds exist
+ modifiedConfig.ShouldNotBeDisabled("darc-int-dotnet-roslyn-12345", "should enable darc-int feed");
+ modifiedConfig.GetPackageSourceCount().Should().Be(0, "should not add dotnet internal feeds without dotnet public feeds");
+ }
+ }
+}
+
+
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/CredentialHandlingTests.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/CredentialHandlingTests.cs
new file mode 100644
index 00000000000..a9cf811728b
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/CredentialHandlingTests.cs
@@ -0,0 +1,215 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using FluentAssertions;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ public class CredentialHandlingTests : IClassFixture, IDisposable
+ {
+ private readonly ScriptRunner _scriptRunner;
+ private readonly string _testOutputDirectory;
+
+ public CredentialHandlingTests(SetupNugetSourcesFixture fixture)
+ {
+ _testOutputDirectory = Path.Combine(Path.GetTempPath(), "SetupNugetSourcesTests", Guid.NewGuid().ToString());
+ Directory.CreateDirectory(_testOutputDirectory);
+ _scriptRunner = fixture.ScriptRunner;
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (Directory.Exists(_testOutputDirectory))
+ {
+ Directory.Delete(_testOutputDirectory, true);
+ }
+ }
+ catch { }
+ }
+
+ [Fact]
+ public async Task ConfigWithCredentialProvided_AddsCredentialsForInternalFeeds()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ var testCredential = "Placeholder";
+ // Act
+ var result = await _scriptRunner.RunScript(configPath, testCredential);
+
+ // Assert
+ result.exitCode.Should().Be(0, "script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should add internal feeds
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal");
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport");
+
+ // Should add credentials for internal feeds
+ modifiedConfig.ShouldContainCredentials("dotnet6-internal", "dn-bot", "should add credentials for internal feed");
+ modifiedConfig.ShouldContainCredentials("dotnet6-internal-transport", "dn-bot", "should add credentials for transport feed");
+
+ // Should use v2 endpoints when credentials are provided
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal/nuget/v2",
+ "should use v2 endpoint when credentials provided");
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-transport/nuget/v2",
+ "should use v2 endpoint when credentials provided");
+ }
+
+ [Fact]
+ public async Task ConfigWithNoCredential_DoesNotAddCredentials()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act - No credential provided
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should add internal feeds
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal");
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport");
+
+ // Should NOT add credentials
+ modifiedConfig.ShouldNotContainCredentials("dotnet6-internal", "should not add credentials without credential");
+ modifiedConfig.ShouldNotContainCredentials("dotnet6-internal-transport", "should not add credentials without credential");
+
+ // Should use v3 endpoints when no credentials are provided
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal/nuget/v3/index.json",
+ "should use v3 endpoint when no credentials provided");
+ }
+
+ [Fact]
+ public async Task ConfigWithExistingCredentials_PreservesAndAddsNew()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ var testCredential = "Placeholder";
+ // Act
+ var result = await _scriptRunner.RunScript(configPath, testCredential);
+
+ // Assert
+ result.exitCode.Should().Be(0, "script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should preserve existing credentials
+ modifiedConfig.ShouldContainCredentials("existing-private", "existing-user", "should preserve existing credentials");
+
+ // Should add new credentials for internal feeds
+ modifiedConfig.ShouldContainCredentials("dotnet6-internal", "dn-bot", "should add credentials for new internal feed");
+ modifiedConfig.ShouldContainCredentials("dotnet6-internal-transport", "dn-bot", "should add credentials for new transport feed");
+ }
+
+ [Fact]
+ public async Task ConfigWithDarcIntFeeds_AddsCredentialsForEnabledFeeds()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ var testCredential = "Placeholder";
+ // Act
+ var result = await _scriptRunner.RunScript(configPath, testCredential);
+
+ // Assert
+ result.exitCode.Should().Be(0, "script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should enable the darc-int feed
+ modifiedConfig.ShouldNotBeDisabled("darc-int-dotnet-roslyn-12345", "darc-int feed should be enabled");
+
+ // Should add credentials for enabled darc-int feed
+ modifiedConfig.ShouldContainCredentials("darc-int-dotnet-roslyn-12345", "dn-bot", "should add credentials for enabled darc-int feed");
+
+ // Should add credentials for new internal feeds
+ modifiedConfig.ShouldContainCredentials("dotnet6-internal", "dn-bot", "should add credentials for internal feed");
+ modifiedConfig.ShouldContainCredentials("dotnet6-internal-transport", "dn-bot", "should add credentials for transport feed");
+ }
+
+ [Fact]
+ public async Task ConfigWithNoCredentialButExistingCredentials_DoesNotRemoveExistingCredentials()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act - No credential provided
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should preserve existing credentials
+ modifiedConfig.ShouldContainCredentials("dotnet6-internal", "dn-bot", "should preserve existing credentials");
+
+ // Should not add credentials for new feeds without credential
+ modifiedConfig.ShouldNotContainCredentials("dotnet6-internal-transport", "should not add credentials without credential");
+ }
+ }
+}
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/FeedEnablingTests.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/FeedEnablingTests.cs
new file mode 100644
index 00000000000..7af694a1db8
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/FeedEnablingTests.cs
@@ -0,0 +1,179 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using FluentAssertions;
+using Xunit;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ public class FeedEnablingTests : IClassFixture, IDisposable
+ {
+ private readonly ScriptRunner _scriptRunner;
+ private readonly string _testOutputDirectory;
+
+ public FeedEnablingTests(SetupNugetSourcesFixture fixture)
+ {
+ _testOutputDirectory = Path.Combine(Path.GetTempPath(), "SetupNugetSourcesTests", Guid.NewGuid().ToString());
+ Directory.CreateDirectory(_testOutputDirectory);
+ _scriptRunner = fixture.ScriptRunner;
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (Directory.Exists(_testOutputDirectory))
+ {
+ Directory.Delete(_testOutputDirectory, true);
+ }
+ }
+ catch { }
+ }
+
+ [Fact]
+ public async Task ConfigWithDisabledDarcIntFeeds_EnablesFeeds()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Darc-int feeds should no longer be disabled
+ modifiedConfig.ShouldNotBeDisabled("darc-int-dotnet-roslyn-12345", "darc-int feed should be enabled");
+ modifiedConfig.ShouldNotBeDisabled("darc-int-dotnet-runtime-67890", "darc-int feed should be enabled");
+
+ // Should also add internal feeds for dotnet6
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal/nuget/v3/index.json",
+ "should add dotnet6-internal feed");
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-transport/nuget/v3/index.json",
+ "should add dotnet6-internal-transport feed");
+ }
+
+ [Fact]
+ public async Task ConfigWithMixedDisabledFeeds_OnlyEnablesDarcIntFeeds()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Darc-int feeds should be enabled
+ modifiedConfig.ShouldNotBeDisabled("darc-int-dotnet-roslyn-12345", "darc-int feed should be enabled");
+ modifiedConfig.ShouldNotBeDisabled("darc-int-dotnet-runtime-67890", "darc-int feed should be enabled");
+
+ // Non-darc-int feeds should remain disabled
+ modifiedConfig.ShouldBeDisabled("some-other-feed", "non-darc-int feed should remain disabled");
+ modifiedConfig.ShouldBeDisabled("another-disabled-feed", "non-darc-int feed should remain disabled");
+ }
+
+ [Fact]
+ public async Task ConfigWithDisabledInternalFeed_EnablesExistingInsteadOfAdding()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // The dotnet6-internal feed should be enabled (removed from disabled sources)
+ modifiedConfig.ShouldNotBeDisabled("dotnet6-internal", "internal feed should be enabled");
+
+ // Should still add the transport feed
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-transport/nuget/v3/index.json",
+ "should add transport feed");
+
+ // Should have 4 package sources (original 3, with dotnet6-internal enabled + transport added)
+ modifiedConfig.GetPackageSourceCount().Should().Be(4, "should enable existing feed and add transport feed");
+ }
+
+ [Fact]
+ public async Task ConfigWithNoDisabledSources_StillAddsInternalFeeds()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should add internal feeds even without disabled sources section
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal/nuget/v3/index.json",
+ "should add dotnet6-internal feed");
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-transport/nuget/v3/index.json",
+ "should add dotnet6-internal-transport feed");
+ }
+ }
+}
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/InternalFeedAdditionTests.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/InternalFeedAdditionTests.cs
new file mode 100644
index 00000000000..ca42421c401
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/InternalFeedAdditionTests.cs
@@ -0,0 +1,149 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using FluentAssertions;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ public class InternalFeedAdditionTests : IClassFixture, IDisposable
+ {
+ private readonly ScriptRunner _scriptRunner;
+ private readonly string _testOutputDirectory;
+
+ public InternalFeedAdditionTests(SetupNugetSourcesFixture fixture)
+ {
+ _testOutputDirectory = Path.Combine(Path.GetTempPath(), "SetupNugetSourcesTests", Guid.NewGuid().ToString());
+ Directory.CreateDirectory(_testOutputDirectory);
+ _scriptRunner = fixture.ScriptRunner;
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (Directory.Exists(_testOutputDirectory))
+ {
+ Directory.Delete(_testOutputDirectory, true);
+ }
+ }
+ catch { }
+ }
+
+ [Theory]
+ [InlineData("dotnet5")]
+ [InlineData("dotnet6")]
+ [InlineData("dotnet7")]
+ [InlineData("dotnet8")]
+ [InlineData("dotnet9")]
+ [InlineData("dotnet10")]
+ public async Task ConfigWithSpecificDotNetVersion_AddsCorrespondingInternalFeeds(string dotnetVersion)
+ {
+ // Arrange
+ var originalConfig = $@"
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ modifiedConfig.ShouldContainPackageSource($"{dotnetVersion}-internal",
+ $"https://pkgs.dev.azure.com/dnceng/internal/_packaging/{dotnetVersion}-internal/nuget/v3/index.json",
+ $"should add {dotnetVersion}-internal feed");
+ modifiedConfig.ShouldContainPackageSource($"{dotnetVersion}-internal-transport",
+ $"https://pkgs.dev.azure.com/dnceng/internal/_packaging/{dotnetVersion}-internal-transport/nuget/v3/index.json",
+ $"should add {dotnetVersion}-internal-transport feed");
+ }
+
+ [Fact]
+ public async Task ConfigWithMultipleDotNetVersions_AddsAllInternalFeeds()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should add internal feeds for all versions
+ var versions = new[] { "dotnet5", "dotnet6", "dotnet7", "dotnet8", "dotnet9", "dotnet10" };
+ foreach (var version in versions)
+ {
+ modifiedConfig.ShouldContainPackageSource($"{version}-internal",
+ $"https://pkgs.dev.azure.com/dnceng/internal/_packaging/{version}-internal/nuget/v3/index.json",
+ $"should add {version}-internal feed");
+ modifiedConfig.ShouldContainPackageSource($"{version}-internal-transport",
+ $"https://pkgs.dev.azure.com/dnceng/internal/_packaging/{version}-internal-transport/nuget/v3/index.json",
+ $"should add {version}-internal-transport feed");
+ }
+
+ // Original count (7 sources) + 12 internal sources = 19 total
+ modifiedConfig.GetPackageSourceCount().Should().Be(19, "should have all original sources plus internal feeds");
+ }
+
+ [Fact]
+ public async Task ConfigWithExistingInternalFeed_DoesNotDuplicate()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+
+ // Should still contain the dotnet6-internal feed (only once)
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal/nuget/v3/index.json",
+ "existing internal feed should be preserved");
+
+ // Should add the missing transport feed
+ modifiedConfig.ShouldContainPackageSource("dotnet6-internal-transport",
+ "https://pkgs.dev.azure.com/dnceng/internal/_packaging/dotnet6-internal-transport/nuget/v3/index.json",
+ "should add missing transport feed");
+
+ // Should have 4 total sources (3 original + 1 added transport)
+ modifiedConfig.GetPackageSourceCount().Should().Be(4, "should not duplicate existing sources");
+ }
+ }
+}
+
+
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/Microsoft.DotNet.SetupNugetSources.Tests.csproj b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/Microsoft.DotNet.SetupNugetSources.Tests.csproj
new file mode 100644
index 00000000000..83d868c3bdc
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/Microsoft.DotNet.SetupNugetSources.Tests.csproj
@@ -0,0 +1,25 @@
+
+
+
+ $(NetToolCurrent)
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/NoChangeScenarioTests.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/NoChangeScenarioTests.cs
new file mode 100644
index 00000000000..632511d3441
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/NoChangeScenarioTests.cs
@@ -0,0 +1,86 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Threading.Tasks;
+using FluentAssertions;
+using Microsoft.DotNet.XUnitExtensions;
+using Xunit;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ public class NoChangeScenarioTests : IClassFixture, IDisposable
+ {
+ private readonly ScriptRunner _scriptRunner;
+ private readonly string _testOutputDirectory;
+
+ public NoChangeScenarioTests(SetupNugetSourcesFixture fixture)
+ {
+ _testOutputDirectory = Path.Combine(Path.GetTempPath(), "SetupNugetSourcesTests", Guid.NewGuid().ToString());
+ Directory.CreateDirectory(_testOutputDirectory);
+ _scriptRunner = fixture.ScriptRunner;
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (Directory.Exists(_testOutputDirectory))
+ {
+ Directory.Delete(_testOutputDirectory, true);
+ }
+ }
+ catch { }
+ }
+
+
+
+ [Fact]
+ public async Task BasicConfig_NoChanges()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+ modifiedConfig.ShouldBeSemanticallySame(originalConfig, "basic config with no special feeds should not be modified");
+ }
+
+ [Fact]
+ public async Task ConfigWithNonDotNetFeeds_NoChanges()
+ {
+ // Arrange
+ var originalConfig = @"
+
+
+
+
+
+
+";
+ var configPath = Path.Combine(_testOutputDirectory, "nuget.config");
+ await Task.Run(() => File.WriteAllText(configPath, originalConfig));
+ // Act
+ var result = await _scriptRunner.RunScript(configPath);
+
+ // Assert
+ result.exitCode.Should().Be(0, "Script should succeed, but got error: {result.error}");
+ var modifiedConfig = await Task.Run(() => File.ReadAllText(configPath));
+ modifiedConfig.ShouldBeSemanticallySame(originalConfig, "config with non-dotnet feeds should not be modified");
+ }
+ }
+}
+
+
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/NuGetConfigAssertions.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/NuGetConfigAssertions.cs
new file mode 100644
index 00000000000..0bd0f5b5dfd
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/NuGetConfigAssertions.cs
@@ -0,0 +1,190 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using System.Xml;
+using System.Xml.Linq;
+using FluentAssertions;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ public static class NuGetConfigAssertions
+ {
+ ///
+ /// Compares two NuGet.config files for semantic equality, ignoring whitespace differences
+ ///
+ public static void ShouldBeSemanticallySame(this string actualContent, string expectedContent, string because = "")
+ {
+ var actualNormalized = NormalizeXml(actualContent);
+ var expectedNormalized = NormalizeXml(expectedContent);
+
+ actualNormalized.Should().Be(expectedNormalized, because);
+ }
+
+ ///
+ /// Asserts that the config contains a package source with the specified key
+ ///
+ public static void ShouldContainPackageSource(this string configContent, string key, string value = null, string because = "")
+ {
+ var doc = XDocument.Parse(configContent);
+ var packageSources = doc.Root?.Element("packageSources");
+ packageSources.Should().NotBeNull($"packageSources section should exist {because}");
+
+ var source = packageSources.Elements("add").FirstOrDefault(e => e.Attribute("key")?.Value == key);
+ source.Should().NotBeNull($"package source '{key}' should exist {because}");
+
+ if (value != null)
+ {
+ source.Attribute("value")?.Value.Should().Be(value, $"package source '{key}' should have the correct value {because}");
+ }
+ }
+
+ ///
+ /// Asserts that the config does not contain a package source with the specified key
+ ///
+ public static void ShouldNotContainPackageSource(this string configContent, string key, string because = "")
+ {
+ var doc = XDocument.Parse(configContent);
+ var packageSources = doc.Root?.Element("packageSources");
+
+ if (packageSources != null)
+ {
+ var source = packageSources.Elements("add").FirstOrDefault(e => e.Attribute("key")?.Value == key);
+ source.Should().BeNull($"package source '{key}' should not exist {because}");
+ }
+ }
+
+ ///
+ /// Asserts that the config contains credentials for the specified source
+ ///
+ public static void ShouldContainCredentials(this string configContent, string sourceName, string username = null, string because = "")
+ {
+ var doc = XDocument.Parse(configContent);
+ var credentials = doc.Root?.Element("packageSourceCredentials");
+ credentials.Should().NotBeNull($"packageSourceCredentials section should exist {because}");
+
+ var sourceCredentials = credentials.Element(sourceName);
+ sourceCredentials.Should().NotBeNull($"credentials for '{sourceName}' should exist {because}");
+
+ if (username != null)
+ {
+ var usernameElement = sourceCredentials.Elements("add").FirstOrDefault(e => e.Attribute("key")?.Value == "Username");
+ usernameElement.Should().NotBeNull($"username credential should exist for '{sourceName}' {because}");
+ usernameElement.Attribute("value")?.Value.Should().Be(username, $"username should match for '{sourceName}' {because}");
+ }
+
+ var passwordElement = sourceCredentials.Elements("add").FirstOrDefault(e => e.Attribute("key")?.Value == "ClearTextPassword");
+ passwordElement.Should().NotBeNull($"password credential should exist for '{sourceName}' {because}");
+ }
+
+ ///
+ /// Asserts that the config does not contain credentials for the specified source
+ ///
+ public static void ShouldNotContainCredentials(this string configContent, string sourceName, string because = "")
+ {
+ var doc = XDocument.Parse(configContent);
+ var credentials = doc.Root?.Element("packageSourceCredentials");
+
+ if (credentials != null)
+ {
+ var sourceCredentials = credentials.Element(sourceName);
+ sourceCredentials.Should().BeNull($"credentials for '{sourceName}' should not exist {because}");
+ }
+ }
+
+ ///
+ /// Asserts that a source is not in the disabled sources list
+ ///
+ public static void ShouldNotBeDisabled(this string configContent, string sourceName, string because = "")
+ {
+ var doc = XDocument.Parse(configContent);
+ var disabledSources = doc.Root?.Element("disabledPackageSources");
+
+ if (disabledSources != null)
+ {
+ var disabledSource = disabledSources.Elements("add").FirstOrDefault(e => e.Attribute("key")?.Value == sourceName);
+ disabledSource.Should().BeNull($"source '{sourceName}' should not be disabled {because}");
+ }
+ }
+
+ ///
+ /// Asserts that a source is in the disabled sources list
+ ///
+ public static void ShouldBeDisabled(this string configContent, string sourceName, string because = "")
+ {
+ var doc = XDocument.Parse(configContent);
+ var disabledSources = doc.Root?.Element("disabledPackageSources");
+ disabledSources.Should().NotBeNull($"disabledPackageSources section should exist {because}");
+
+ var disabledSource = disabledSources.Elements("add").FirstOrDefault(e => e.Attribute("key")?.Value == sourceName);
+ disabledSource.Should().NotBeNull($"source '{sourceName}' should be disabled {because}");
+ }
+
+ ///
+ /// Counts the number of package sources in the config
+ ///
+ public static int GetPackageSourceCount(this string configContent)
+ {
+ var doc = XDocument.Parse(configContent);
+ var packageSources = doc.Root?.Element("packageSources");
+ return packageSources?.Elements("add").Count() ?? 0;
+ }
+
+ ///
+ /// Normalizes XML content for comparison by removing whitespace differences and sorting elements consistently
+ ///
+ private static string NormalizeXml(string xmlContent)
+ {
+ var doc = XDocument.Parse(xmlContent);
+
+ // Sort package sources by key for consistent comparison
+ var packageSources = doc.Root?.Element("packageSources");
+ if (packageSources != null)
+ {
+ var sortedSources = packageSources.Elements("add")
+ .OrderBy(e => e.Attribute("key")?.Value)
+ .ToList();
+ packageSources.RemoveAll();
+ foreach (var source in sortedSources)
+ {
+ packageSources.Add(source);
+ }
+ }
+
+ // Sort disabled sources by key
+ var disabledSources = doc.Root?.Element("disabledPackageSources");
+ if (disabledSources != null)
+ {
+ var sortedDisabled = disabledSources.Elements("add")
+ .OrderBy(e => e.Attribute("key")?.Value)
+ .ToList();
+ disabledSources.RemoveAll();
+ foreach (var source in sortedDisabled)
+ {
+ disabledSources.Add(source);
+ }
+ }
+
+ // Sort credentials by source name
+ var credentials = doc.Root?.Element("packageSourceCredentials");
+ if (credentials != null)
+ {
+ var sortedCredentials = credentials.Elements()
+ .OrderBy(e => e.Name.LocalName)
+ .ToList();
+ credentials.RemoveAll();
+ foreach (var cred in sortedCredentials)
+ {
+ credentials.Add(cred);
+ }
+ }
+
+ return doc.ToString(SaveOptions.DisableFormatting);
+ }
+ }
+}
+
+
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/ScriptRunner.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/ScriptRunner.cs
new file mode 100644
index 00000000000..37dd8cb9d37
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/ScriptRunner.cs
@@ -0,0 +1,125 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ public enum ScriptType
+ {
+ PowerShell,
+ Shell
+ }
+
+ public class ScriptRunner
+ {
+ private readonly string _repoRoot;
+
+ public ScriptRunner(string repoRoot)
+ {
+ _repoRoot = repoRoot ?? throw new ArgumentNullException(nameof(repoRoot));
+ }
+
+ public async Task<(int exitCode, string output, string error)> RunPowerShellScript(string configFilePath, string password = null)
+ {
+ var scriptPath = Path.Combine(_repoRoot, "eng", "common", "SetupNugetSources.ps1");
+ var arguments = $"-ExecutionPolicy Bypass -File \"{scriptPath}\" -ConfigFile \"{configFilePath}\"";
+
+ if (!string.IsNullOrEmpty(password))
+ {
+ arguments += $" -Password \"{password}\"";
+ }
+
+ return await RunProcess("powershell.exe", arguments, _repoRoot);
+ }
+
+ public async Task<(int exitCode, string output, string error)> RunShellScript(string configFilePath, string credToken = null)
+ {
+ var scriptPath = Path.Combine(_repoRoot, "eng", "common", "SetupNugetSources.sh");
+
+ // Make script executable if on Unix
+ if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ await RunProcess("chmod", $"+x \"{scriptPath}\"", _repoRoot);
+ }
+
+ var arguments = $"\"{scriptPath}\" \"{configFilePath}\"";
+ if (!string.IsNullOrEmpty(credToken))
+ {
+ arguments += $" \"{credToken}\"";
+ }
+
+ var shell = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "bash.exe" : "/bin/bash";
+ return await RunProcess(shell, arguments, _repoRoot);
+ }
+
+ private async Task<(int exitCode, string output, string error)> RunProcess(string fileName, string arguments, string workingDirectory = null)
+ {
+ var process = new Process
+ {
+ StartInfo = new ProcessStartInfo
+ {
+ FileName = fileName,
+ Arguments = arguments,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ CreateNoWindow = true,
+ WorkingDirectory = workingDirectory ?? Directory.GetCurrentDirectory()
+ }
+ };
+
+ var outputBuilder = new StringBuilder();
+ var errorBuilder = new StringBuilder();
+
+ process.OutputDataReceived += (sender, e) =>
+ {
+ if (e.Data != null)
+ {
+ outputBuilder.AppendLine(e.Data);
+ }
+ };
+
+ process.ErrorDataReceived += (sender, e) =>
+ {
+ if (e.Data != null)
+ {
+ errorBuilder.AppendLine(e.Data);
+ }
+ };
+
+ process.Start();
+ process.BeginOutputReadLine();
+ process.BeginErrorReadLine();
+
+ await Task.Run(() => process.WaitForExit());
+
+ return (process.ExitCode, outputBuilder.ToString(), errorBuilder.ToString());
+ }
+
+ public async Task<(int exitCode, string output, string error)> RunScript(string configFilePath, string credential = null)
+ {
+ var scriptType = GetPlatformAppropriateScriptType();
+ switch (scriptType)
+ {
+ case ScriptType.PowerShell:
+ return await RunPowerShellScript(configFilePath, credential);
+ case ScriptType.Shell:
+ return await RunShellScript(configFilePath, credential);
+ default:
+ throw new ArgumentException($"Unsupported script type: {scriptType}");
+ }
+ }
+
+ public static ScriptType GetPlatformAppropriateScriptType()
+ {
+ return RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ScriptType.PowerShell : ScriptType.Shell;
+ }
+ }
+}
+
diff --git a/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/SetupNugetSourcesFixture.cs b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/SetupNugetSourcesFixture.cs
new file mode 100644
index 00000000000..7e25ccd1b88
--- /dev/null
+++ b/src/arcade/src/Microsoft.DotNet.SetupNugetSources.Tests/SetupNugetSourcesFixture.cs
@@ -0,0 +1,65 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.IO;
+
+namespace Microsoft.DotNet.SetupNugetSources.Tests
+{
+ ///
+ /// xUnit fixture that prepares a temporary repository root containing the
+ /// scaffolded files (global.json + eng/common scripts) copied from the
+ /// build output's RepoScaffold directory. Shared per test class.
+ ///
+ public class SetupNugetSourcesFixture : IDisposable
+ {
+ public string RepoRoot { get; }
+ public ScriptRunner ScriptRunner { get; }
+
+ public SetupNugetSourcesFixture()
+ {
+ var scaffoldRoot = Path.Combine(AppContext.BaseDirectory, "RepoScaffold");
+ if (!Directory.Exists(scaffoldRoot))
+ {
+ throw new InvalidOperationException($"Expected scaffold directory not found: {scaffoldRoot}");
+ }
+
+ RepoRoot = Path.Combine(Path.GetTempPath(), "SetupNugetSourcesTestRepo", Guid.NewGuid().ToString());
+ CopyDirectory(scaffoldRoot, RepoRoot);
+
+ ScriptRunner = new ScriptRunner(RepoRoot);
+ }
+
+ private static void CopyDirectory(string sourceDir, string destinationDir)
+ {
+ foreach (var dir in Directory.GetDirectories(sourceDir, "*", SearchOption.AllDirectories))
+ {
+ var relative = Path.GetRelativePath(sourceDir, dir);
+ Directory.CreateDirectory(Path.Combine(destinationDir, relative));
+ }
+
+ foreach (var file in Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories))
+ {
+ var relative = Path.GetRelativePath(sourceDir, file);
+ var destPath = Path.Combine(destinationDir, relative);
+ Directory.CreateDirectory(Path.GetDirectoryName(destPath)!);
+ File.Copy(file, destPath, overwrite: true);
+ }
+ }
+
+ public void Dispose()
+ {
+ try
+ {
+ if (Directory.Exists(RepoRoot))
+ {
+ Directory.Delete(RepoRoot, recursive: true);
+ }
+ }
+ catch
+ {
+ // Best effort cleanup.
+ }
+ }
+ }
+}
diff --git a/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs b/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs
index 3b4cd8581ea..03672d1c263 100644
--- a/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs
+++ b/src/arcade/src/Microsoft.DotNet.SignTool.Tests/SignToolTests.cs
@@ -480,7 +480,9 @@ private void ValidateProducedRpmContent(
string layout = Path.Combine(tempDir, "layout");
Directory.CreateDirectory(layout);
- ZipData.ExtractRpmPayloadContents(log: null, rpmPackage, layout);
+ var fakeBuildEngine = new FakeBuildEngine(_output);
+ var fakeLog = new TaskLoggingHelper(fakeBuildEngine, "TestLog");
+ ZipData.ExtractRpmPayloadContents(fakeLog, rpmPackage, layout);
// Checks:
// Expected files are present
diff --git a/src/aspnetcore/eng/Version.Details.props b/src/aspnetcore/eng/Version.Details.props
index ffe9c35f973..06e740a8cae 100644
--- a/src/aspnetcore/eng/Version.Details.props
+++ b/src/aspnetcore/eng/Version.Details.props
@@ -6,98 +6,98 @@ This file should be imported by eng/Versions.props
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-beta.25507.103
- 10.0.0-beta.25507.103
- 10.0.0-beta.25507.103
- 10.0.0-beta.25507.103
- 10.0.0-beta.25507.103
- 10.0.0-beta.25507.103
- 10.0.0-beta.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 3.2.0-preview.25507.103
- 7.0.0-rc.803
- 7.0.0-rc.803
- 7.0.0-rc.803
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
- 10.0.0-rtm.25507.103
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 3.2.0-preview.25509.106
+ 7.0.0-rc.1006
+ 7.0.0-rc.1006
+ 7.0.0-rc.1006
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.1064.13.0-3.24613.74.13.0-3.24613.7
diff --git a/src/aspnetcore/eng/Version.Details.xml b/src/aspnetcore/eng/Version.Details.xml
index 0f0a7ebe0bf..cc99cb2648b 100644
--- a/src/aspnetcore/eng/Version.Details.xml
+++ b/src/aspnetcore/eng/Version.Details.xml
@@ -8,333 +8,333 @@
See https://github.com/dotnet/arcade/blob/master/Documentation/Darc.md for instructions on using darc.
-->
-
+
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
@@ -358,37 +358,37 @@
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aachttps://github.com/dotnet/extensions
@@ -440,17 +440,17 @@
https://github.com/dotnet/msbuildd1cce8d7cc03c23a4f1bad8e9240714fd9d199a3
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
diff --git a/src/aspnetcore/global.json b/src/aspnetcore/global.json
index c4cb92a9a95..abf6225284d 100644
--- a/src/aspnetcore/global.json
+++ b/src/aspnetcore/global.json
@@ -27,9 +27,9 @@
"jdk": "latest"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25507.103",
- "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25507.103",
- "Microsoft.DotNet.SharedFramework.Sdk": "10.0.0-beta.25507.103",
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25509.106",
+ "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25509.106",
+ "Microsoft.DotNet.SharedFramework.Sdk": "10.0.0-beta.25509.106",
"Microsoft.Build.NoTargets": "3.7.0",
"Microsoft.Build.Traversal": "3.4.0",
"Microsoft.WixToolset.Sdk": "5.0.2-dotnet.2737382"
diff --git a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs
index a8161054279..7ce2a54419b 100644
--- a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs
+++ b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSource.cs
@@ -20,8 +20,8 @@ internal class RazorComponentEndpointDataSource<[DynamicallyAccessedMembers(Comp
private readonly object _lock = new();
private readonly List> _conventions = [];
private readonly List> _finallyConventions = [];
+ private readonly List> _componentApplicationBuilderActions = [];
private readonly RazorComponentDataSourceOptions _options = new();
- private readonly ComponentApplicationBuilder _builder;
private readonly IEndpointRouteBuilder _endpointRouteBuilder;
private readonly ResourceCollectionResolver _resourceCollectionResolver;
private readonly RenderModeEndpointProvider[] _renderModeEndpointProviders;
@@ -32,33 +32,29 @@ internal class RazorComponentEndpointDataSource<[DynamicallyAccessedMembers(Comp
private IChangeToken _changeToken;
private IDisposable? _disposableChangeToken; // THREADING: protected by _lock
- public Func SetDisposableChangeTokenAction = disposableChangeToken => disposableChangeToken;
-
// Internal for testing.
- internal ComponentApplicationBuilder Builder => _builder;
internal List> Conventions => _conventions;
+ internal List> ComponentApplicationBuilderActions => _componentApplicationBuilderActions;
+ internal CancellationTokenSource ChangeTokenSource => _cancellationTokenSource;
public RazorComponentEndpointDataSource(
- ComponentApplicationBuilder builder,
IEnumerable renderModeEndpointProviders,
IEndpointRouteBuilder endpointRouteBuilder,
RazorComponentEndpointFactory factory,
HotReloadService? hotReloadService = null)
{
- _builder = builder;
_endpointRouteBuilder = endpointRouteBuilder;
_resourceCollectionResolver = new ResourceCollectionResolver(endpointRouteBuilder);
_renderModeEndpointProviders = renderModeEndpointProviders.ToArray();
_factory = factory;
_hotReloadService = hotReloadService;
- HotReloadService.ClearCacheEvent += OnHotReloadClearCache;
DefaultBuilder = new RazorComponentsEndpointConventionBuilder(
_lock,
- builder,
endpointRouteBuilder,
_options,
_conventions,
- _finallyConventions);
+ _finallyConventions,
+ _componentApplicationBuilderActions);
_cancellationTokenSource = new CancellationTokenSource();
_changeToken = new CancellationChangeToken(_cancellationTokenSource.Token);
@@ -106,8 +102,20 @@ private void UpdateEndpoints()
lock (_lock)
{
+ _disposableChangeToken?.Dispose();
+ _disposableChangeToken = null;
+
var endpoints = new List();
- var context = _builder.Build();
+
+ var componentApplicationBuilder = new ComponentApplicationBuilder();
+
+ foreach (var action in ComponentApplicationBuilderActions)
+ {
+ action?.Invoke(componentApplicationBuilder);
+ }
+
+ var context = componentApplicationBuilder.Build();
+
var configuredRenderModesMetadata = new ConfiguredRenderModesMetadata(
[.. Options.ConfiguredRenderModes]);
@@ -168,8 +176,7 @@ private void UpdateEndpoints()
oldCancellationTokenSource?.Dispose();
if (_hotReloadService is { MetadataUpdateSupported: true })
{
- _disposableChangeToken?.Dispose();
- _disposableChangeToken = SetDisposableChangeTokenAction(ChangeToken.OnChange(_hotReloadService.GetChangeToken, UpdateEndpoints));
+ _disposableChangeToken = ChangeToken.OnChange(_hotReloadService.GetChangeToken, UpdateEndpoints);
}
}
}
@@ -195,15 +202,6 @@ private void AddBlazorWebEndpoints(List endpoints)
}
}
- public void OnHotReloadClearCache(Type[]? types)
- {
- lock (_lock)
- {
- _disposableChangeToken?.Dispose();
- _disposableChangeToken = null;
- }
- }
-
public override IChangeToken GetChangeToken()
{
Initialize();
diff --git a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSourceFactory.cs b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSourceFactory.cs
index 84327f3f6d5..a8f178a4fc2 100644
--- a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSourceFactory.cs
+++ b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentEndpointDataSourceFactory.cs
@@ -17,9 +17,14 @@ internal class RazorComponentEndpointDataSourceFactory(
{
public RazorComponentEndpointDataSource CreateDataSource<[DynamicallyAccessedMembers(Component)] TRootComponent>(IEndpointRouteBuilder endpoints)
{
- var builder = ComponentApplicationBuilder.GetBuilder() ??
- DefaultRazorComponentApplication.Instance.GetBuilder();
+ var dataSource = new RazorComponentEndpointDataSource(providers, endpoints, factory, hotReloadService);
- return new RazorComponentEndpointDataSource(builder, providers, endpoints, factory, hotReloadService);
+ dataSource.ComponentApplicationBuilderActions.Add(builder =>
+ {
+ var assembly = typeof(TRootComponent).Assembly;
+ IRazorComponentApplication.GetBuilderForAssembly(builder, assembly);
+ });
+
+ return dataSource;
}
}
diff --git a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilder.cs b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilder.cs
index 04b1daa9e95..46808fbfdfb 100644
--- a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilder.cs
+++ b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilder.cs
@@ -18,27 +18,25 @@ public sealed class RazorComponentsEndpointConventionBuilder : IEndpointConventi
private readonly RazorComponentDataSourceOptions _options;
private readonly List> _conventions;
private readonly List> _finallyConventions;
+ private readonly List> _componentApplicationBuilderActions;
internal RazorComponentsEndpointConventionBuilder(
object @lock,
- ComponentApplicationBuilder builder,
IEndpointRouteBuilder endpointRouteBuilder,
RazorComponentDataSourceOptions options,
List> conventions,
- List> finallyConventions)
+ List> finallyConventions,
+ List> componentApplicationBuilderActions)
{
_lock = @lock;
- ApplicationBuilder = builder;
EndpointRouteBuilder = endpointRouteBuilder;
_options = options;
_conventions = conventions;
_finallyConventions = finallyConventions;
+ _componentApplicationBuilderActions = componentApplicationBuilderActions;
}
- ///
- /// Gets the that is used to build the endpoints.
- ///
- internal ComponentApplicationBuilder ApplicationBuilder { get; }
+ internal List> ComponentApplicationBuilderActions => _componentApplicationBuilderActions;
internal string? ManifestPath { get => _options.ManifestPath; set => _options.ManifestPath = value; }
diff --git a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilderExtensions.cs b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilderExtensions.cs
index fd0a6aec0c4..7cc4fa4dc76 100644
--- a/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilderExtensions.cs
+++ b/src/aspnetcore/src/Components/Endpoints/src/Builder/RazorComponentsEndpointConventionBuilderExtensions.cs
@@ -30,7 +30,7 @@ public static RazorComponentsEndpointConventionBuilder AddAdditionalAssemblies(
foreach (var assembly in assemblies)
{
- builder.ApplicationBuilder.AddAssembly(assembly);
+ builder.ComponentApplicationBuilderActions.Add(b => b.AddAssembly(assembly));
}
return builder;
}
diff --git a/src/aspnetcore/src/Components/Endpoints/test/Builder/RazorComponentsEndpointConventionBuilderExtensionsTest.cs b/src/aspnetcore/src/Components/Endpoints/test/Builder/RazorComponentsEndpointConventionBuilderExtensionsTest.cs
index 70fa780fcba..e1a5116ee0b 100644
--- a/src/aspnetcore/src/Components/Endpoints/test/Builder/RazorComponentsEndpointConventionBuilderExtensionsTest.cs
+++ b/src/aspnetcore/src/Components/Endpoints/test/Builder/RazorComponentsEndpointConventionBuilderExtensionsTest.cs
@@ -245,7 +245,7 @@ public void MapRazorComponents_CanAddConventions_ToBlazorWebEndpoints(string fra
private RazorComponentsEndpointConventionBuilder CreateRazorComponentsAppBuilder(IEndpointRouteBuilder endpointBuilder)
{
var builder = endpointBuilder.MapRazorComponents();
- builder.ApplicationBuilder.AddLibrary(new AssemblyComponentLibraryDescriptor(
+ builder.ComponentApplicationBuilderActions.Add(b => b.AddLibrary(new AssemblyComponentLibraryDescriptor(
"App",
[new PageComponentBuilder {
PageType = typeof(App),
@@ -253,7 +253,7 @@ [new PageComponentBuilder {
AssemblyName = "App",
}],
[]
- ));
+ )));
return builder;
}
diff --git a/src/aspnetcore/src/Components/Endpoints/test/HotReloadServiceTests.cs b/src/aspnetcore/src/Components/Endpoints/test/HotReloadServiceTests.cs
index 011056c2e7c..a8e2280d77e 100644
--- a/src/aspnetcore/src/Components/Endpoints/test/HotReloadServiceTests.cs
+++ b/src/aspnetcore/src/Components/Endpoints/test/HotReloadServiceTests.cs
@@ -23,9 +23,8 @@ public class HotReloadServiceTests
public void UpdatesEndpointsWhenHotReloadChangeTokenTriggered()
{
// Arrange
- var builder = CreateBuilder(typeof(ServerComponent));
var services = CreateServices(typeof(MockEndpointProvider));
- var endpointDataSource = CreateDataSource(builder, services);
+ var endpointDataSource = CreateDataSource(services, ConfigureServerComponentBuilder);
var invoked = false;
// Act
@@ -41,9 +40,8 @@ public void UpdatesEndpointsWhenHotReloadChangeTokenTriggered()
public void AddNewEndpointWhenDataSourceChanges()
{
// Arrange
- var builder = CreateBuilder(typeof(ServerComponent));
var services = CreateServices(typeof(MockEndpointProvider));
- var endpointDataSource = CreateDataSource(builder, services);
+ var endpointDataSource = CreateDataSource(services, ConfigureServerComponentBuilder);
// Assert - 1
var endpoint = Assert.IsType(
@@ -52,15 +50,17 @@ public void AddNewEndpointWhenDataSourceChanges()
Assert.Equal("/server", endpoint.RoutePattern.RawText);
// Act - 2
- endpointDataSource.Builder.Pages.AddFromLibraryInfo("TestAssembly2", new[]
- {
- new PageComponentBuilder
+ endpointDataSource.ComponentApplicationBuilderActions.Add(
+ b => b.Pages.AddFromLibraryInfo("TestAssembly2", new[]
{
- AssemblyName = "TestAssembly2",
- PageType = typeof(StaticComponent),
- RouteTemplates = new List { "/app/test" }
- }
- });
+ new PageComponentBuilder
+ {
+ AssemblyName = "TestAssembly2",
+ PageType = typeof(StaticComponent),
+ RouteTemplates = new List { "/app/test" }
+ }
+ }));
+
HotReloadService.UpdateApplication(null);
// Assert - 2
@@ -76,9 +76,8 @@ public void AddNewEndpointWhenDataSourceChanges()
public void RemovesEndpointWhenDataSourceChanges()
{
// Arrange
- var builder = CreateBuilder(typeof(ServerComponent));
var services = CreateServices(typeof(MockEndpointProvider));
- var endpointDataSource = CreateDataSource(builder, services);
+ var endpointDataSource = CreateDataSource(services, ConfigureServerComponentBuilder);
// Assert - 1
var endpoint = Assert.IsType(Assert.Single(endpointDataSource.Endpoints,
@@ -87,7 +86,7 @@ public void RemovesEndpointWhenDataSourceChanges()
Assert.Equal("/server", endpoint.RoutePattern.RawText);
// Act - 2
- endpointDataSource.Builder.RemoveLibrary("TestAssembly");
+ endpointDataSource.ComponentApplicationBuilderActions.Add(b => b.RemoveLibrary("TestAssembly"));
endpointDataSource.Options.ConfiguredRenderModes.Clear();
HotReloadService.UpdateApplication(null);
@@ -100,9 +99,8 @@ public void RemovesEndpointWhenDataSourceChanges()
public void ModifiesEndpointWhenDataSourceChanges()
{
// Arrange
- var builder = CreateBuilder(typeof(ServerComponent));
var services = CreateServices(typeof(MockEndpointProvider));
- var endpointDataSource = CreateDataSource(builder, services);
+ var endpointDataSource = CreateDataSource(services, ConfigureServerComponentBuilder);
// Assert - 1
var endpoint = Assert.IsType(Assert.Single(endpointDataSource.Endpoints, e => e.Metadata.GetMetadata() != null));
@@ -124,9 +122,8 @@ public void ModifiesEndpointWhenDataSourceChanges()
public void NotifiesCompositeEndpointDataSource()
{
// Arrange
- var builder = CreateBuilder(typeof(ServerComponent));
var services = CreateServices(typeof(MockEndpointProvider));
- var endpointDataSource = CreateDataSource(builder, services);
+ var endpointDataSource = CreateDataSource(services, ConfigureServerComponentBuilder);
var compositeEndpointDataSource = new CompositeEndpointDataSource(
new[] { endpointDataSource });
@@ -137,7 +134,7 @@ public void NotifiesCompositeEndpointDataSource()
Assert.Equal("/server", compositeEndpoint.RoutePattern.RawText);
// Act - 2
- endpointDataSource.Builder.Pages.RemoveFromAssembly("TestAssembly");
+ endpointDataSource.ComponentApplicationBuilderActions.Add(b => b.Pages.RemoveFromAssembly("TestAssembly"));
endpointDataSource.Options.ConfiguredRenderModes.Clear();
HotReloadService.UpdateApplication(null);
@@ -148,37 +145,14 @@ public void NotifiesCompositeEndpointDataSource()
Assert.Empty(compositePageEndpoints);
}
- private sealed class WrappedChangeTokenDisposable : IDisposable
- {
- public bool IsDisposed { get; private set; }
- private readonly IDisposable _innerDisposable;
-
- public WrappedChangeTokenDisposable(IDisposable innerDisposable)
- {
- _innerDisposable = innerDisposable;
- }
-
- public void Dispose()
- {
- IsDisposed = true;
- _innerDisposable.Dispose();
- }
- }
-
[Fact]
public void ConfirmChangeTokenDisposedHotReload()
{
// Arrange
- var builder = CreateBuilder(typeof(ServerComponent));
var services = CreateServices(typeof(MockEndpointProvider));
- var endpointDataSource = CreateDataSource(builder, services);
-
- WrappedChangeTokenDisposable wrappedChangeTokenDisposable = null;
-
- endpointDataSource.SetDisposableChangeTokenAction = (IDisposable disposableChangeToken) => {
- wrappedChangeTokenDisposable = new WrappedChangeTokenDisposable(disposableChangeToken);
- return wrappedChangeTokenDisposable;
- };
+ var endpointDataSource = CreateDataSource(services, ConfigureServerComponentBuilder, null);
+ var changeTokenSource = endpointDataSource.ChangeTokenSource;
+ var changeToken = endpointDataSource.GetChangeToken();
var endpoint = Assert.IsType(Assert.Single(endpointDataSource.Endpoints, e => e.Metadata.GetMetadata() != null));
Assert.Equal("/server", endpoint.RoutePattern.RawText);
@@ -187,18 +161,21 @@ public void ConfirmChangeTokenDisposedHotReload()
// Make a modification and then perform a hot reload.
endpointDataSource.Conventions.Add(builder =>
builder.Metadata.Add(new TestMetadata()));
+
HotReloadService.UpdateApplication(null);
HotReloadService.ClearCache(null);
// Confirm the change token is disposed after ClearCache
- Assert.True(wrappedChangeTokenDisposable.IsDisposed);
+ Assert.True(changeToken.HasChanged);
+ Assert.Throws(() => changeTokenSource.Token);
}
private class TestMetadata { }
- private ComponentApplicationBuilder CreateBuilder(params Type[] types)
+ private class TestAssembly : Assembly;
+
+ private static void ConfigureBuilder(ComponentApplicationBuilder builder, params Type[] types)
{
- var builder = new ComponentApplicationBuilder();
builder.AddLibrary(new AssemblyComponentLibraryDescriptor(
"TestAssembly",
Array.Empty(),
@@ -208,8 +185,11 @@ private ComponentApplicationBuilder CreateBuilder(params Type[] types)
ComponentType = t,
RenderMode = t.GetCustomAttribute()
}).ToArray()));
+ }
- return builder;
+ private static void ConfigureServerComponentBuilder(ComponentApplicationBuilder builder)
+ {
+ ConfigureBuilder(builder, typeof(ServerComponent));
}
private IServiceProvider CreateServices(params Type[] types)
@@ -227,16 +207,21 @@ private IServiceProvider CreateServices(params Type[] types)
}
private static RazorComponentEndpointDataSource CreateDataSource(
- ComponentApplicationBuilder builder,
IServiceProvider services,
- IComponentRenderMode[] renderModes = null)
+ Action configureBuilder = null,
+ IComponentRenderMode[] renderModes = null,
+ HotReloadService hotReloadService = null)
{
var result = new RazorComponentEndpointDataSource(
- builder,
new[] { new MockEndpointProvider() },
new TestEndpointRouteBuilder(services),
new RazorComponentEndpointFactory(),
- new HotReloadService() { MetadataUpdateSupported = true });
+ hotReloadService ?? new HotReloadService() { MetadataUpdateSupported = true });
+
+ if (configureBuilder is not null)
+ {
+ result.ComponentApplicationBuilderActions.Add(configureBuilder);
+ }
if (renderModes != null)
{
diff --git a/src/aspnetcore/src/Components/Endpoints/test/RazorComponentEndpointDataSourceTest.cs b/src/aspnetcore/src/Components/Endpoints/test/RazorComponentEndpointDataSourceTest.cs
index 52cd757d62a..26a154b2cb1 100644
--- a/src/aspnetcore/src/Components/Endpoints/test/RazorComponentEndpointDataSourceTest.cs
+++ b/src/aspnetcore/src/Components/Endpoints/test/RazorComponentEndpointDataSourceTest.cs
@@ -24,6 +24,11 @@ public class RazorComponentEndpointDataSourceTest
public void RegistersEndpoints()
{
var endpointDataSource = CreateDataSource();
+ endpointDataSource.ComponentApplicationBuilderActions.Add(builder =>
+ {
+ var assembly = typeof(App).Assembly;
+ IRazorComponentApplication.GetBuilderForAssembly(builder, assembly);
+ });
var endpoints = endpointDataSource.Endpoints;
@@ -33,10 +38,15 @@ public void RegistersEndpoints()
[Fact]
public void NoDiscoveredModesDefaultsToStatic()
{
-
- var builder = CreateBuilder();
var services = CreateServices(typeof(ServerEndpointProvider));
- var endpointDataSource = CreateDataSource(builder, services);
+ var endpointDataSource = CreateDataSource(services);
+
+ endpointDataSource.ComponentApplicationBuilderActions.Add(builder =>
+ {
+ builder.AddLibrary(new AssemblyComponentLibraryDescriptor(
+ "TestAssembly",
+ Array.Empty(), Array.Empty()));
+ });
var endpoints = endpointDataSource.Endpoints;
@@ -199,22 +209,6 @@ public void NoDiscoveredModesDefaultsToStatic()
},
};
- private ComponentApplicationBuilder CreateBuilder(params Type[] types)
- {
- var builder = new ComponentApplicationBuilder();
- builder.AddLibrary(new AssemblyComponentLibraryDescriptor(
- "TestAssembly",
- Array.Empty(),
- types.Select(t => new ComponentBuilder
- {
- AssemblyName = "TestAssembly",
- ComponentType = t,
- RenderMode = t.GetCustomAttribute()
- }).ToArray()));
-
- return builder;
- }
-
private IServiceProvider CreateServices(params Type[] types)
{
var services = new ServiceCollection();
@@ -230,12 +224,10 @@ private IServiceProvider CreateServices(params Type[] types)
}
private RazorComponentEndpointDataSource CreateDataSource(
- ComponentApplicationBuilder builder = null,
IServiceProvider services = null,
IComponentRenderMode[] renderModes = null)
{
var result = new RazorComponentEndpointDataSource(
- builder ?? DefaultRazorComponentApplication.Instance.GetBuilder(),
services?.GetService>() ?? Enumerable.Empty(),
new TestEndpointRouteBuilder(services ?? CreateServices()),
new RazorComponentEndpointFactory(),
diff --git a/src/diagnostics/.github/ISSUE_TEMPLATE/01_Bug_Report.md b/src/diagnostics/.github/ISSUE_TEMPLATE/01_Bug_Report.md
index 918b30c8c8d..d643b2347d8 100644
--- a/src/diagnostics/.github/ISSUE_TEMPLATE/01_Bug_Report.md
+++ b/src/diagnostics/.github/ISSUE_TEMPLATE/01_Bug_Report.md
@@ -26,7 +26,7 @@ assignees: ''
* Do you know whether it is specific to that configuration?
* Are you running in any particular type of environment? (e.g. Containers, a cloud scenario, app you are trying to target is a different user)
* Is it a self-contained published application?
-* What's the output of `dotnet info`
+* What's the output of `dotnet --info`
-->
### Regression?
diff --git a/src/diagnostics/src/SOS/SOS.Package/SOS.Package.csproj b/src/diagnostics/src/SOS/SOS.Package/SOS.Package.csproj
index ed219206423..5607b1c05fe 100644
--- a/src/diagnostics/src/SOS/SOS.Package/SOS.Package.csproj
+++ b/src/diagnostics/src/SOS/SOS.Package/SOS.Package.csproj
@@ -14,7 +14,7 @@
truefalse
-
+
@@ -30,47 +30,54 @@
-
+
- SOS
- $(FileVersion)
- Debugging aid for .NET Core programs and runtimes
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- !soshelp
- Displays all available SOS commands or details about the command
-
-
-
-
-
+ SOS
+ $(FileVersion)
+ Debugging aid for .NET Core programs and runtimes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ !soshelp
+ Displays all available SOS commands or details about the command
+
+
+
+
+
]]>
diff --git a/src/efcore/.config/guardian/.gdnbaselines b/src/efcore/.config/guardian/.gdnbaselines
new file mode 100644
index 00000000000..b6b74d33542
--- /dev/null
+++ b/src/efcore/.config/guardian/.gdnbaselines
@@ -0,0 +1,106 @@
+{
+ "hydrated": false,
+ "properties": {
+ "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines"
+ },
+ "version": "1.0.0",
+ "baselines": {
+ "default": {
+ "name": "default",
+ "createdDate": "2025-10-09 21:18:42Z",
+ "lastUpdatedDate": "2025-10-09 21:18:42Z"
+ }
+ },
+ "results": {
+ "9d8334bec997ff899ba849d8b31406f7c95af0ffb1d237972bd5134b8c6a9b88": {
+ "signature": "9d8334bec997ff899ba849d8b31406f7c95af0ffb1d237972bd5134b8c6a9b88",
+ "alternativeSignatures": [
+ "b6a603191b00edf78ad2c6116a7a7822864031cc001884be25b3c1543dbe20a7"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "ba7df56f5519347813a7917091709adf2d27b3493d05af0fb8b7037eda3020bb": {
+ "signature": "ba7df56f5519347813a7917091709adf2d27b3493d05af0fb8b7037eda3020bb",
+ "alternativeSignatures": [
+ "5269e81e8a286ccd1568a00c455c489efa62e6887bfb55ea0dddaceb7183c882"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "bc04851b7440a10a0c2a03f2793ab06b6562fe0529e0d353765503f1bcaf8c46": {
+ "signature": "bc04851b7440a10a0c2a03f2793ab06b6562fe0529e0d353765503f1bcaf8c46",
+ "alternativeSignatures": [
+ "274b9a26e35f9604cd1c84941eb97f2edaecde6607be139e9d9d687f7d6875f4"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "9fb27502e61c5647554076d6603a1092943fb625efb6c53faa1042e0d7d217ce": {
+ "signature": "9fb27502e61c5647554076d6603a1092943fb625efb6c53faa1042e0d7d217ce",
+ "alternativeSignatures": [
+ "3355e030588f68be29994a44e2b11079e90945e26c6397345d11424ce36cc5a1"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "60f28802b8ac837691755554b460b422afaeb8dea2129097ab3b7e6c43076ea1": {
+ "signature": "60f28802b8ac837691755554b460b422afaeb8dea2129097ab3b7e6c43076ea1",
+ "alternativeSignatures": [
+ "7a3aa28c8f6e629099ba288e1a78ddb3191def880ae018f7146b66689daca838"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "3bc55e953e7199f08b4c174f6fb0f026db93865d22fc5ef535e2ba1172c8db03": {
+ "signature": "3bc55e953e7199f08b4c174f6fb0f026db93865d22fc5ef535e2ba1172c8db03",
+ "alternativeSignatures": [
+ "fb3809bbf91d374d8872aa371ff0d8858232822571dae6f9e6cba6276892d953"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "bd69975ed44d92efc4a265e13462b1471f292ad9e8566b0200b2df7786808469": {
+ "signature": "bd69975ed44d92efc4a265e13462b1471f292ad9e8566b0200b2df7786808469",
+ "alternativeSignatures": [
+ "609bf3d92ef1f73cbe4d3fa001926c0e274b04f21bf6d103a39a64849437e7e3"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "0b6a4ced009a4e3efdf4ad8f00c0b31ec0791249087560c5c6481ab2824a35a8": {
+ "signature": "0b6a4ced009a4e3efdf4ad8f00c0b31ec0791249087560c5c6481ab2824a35a8",
+ "alternativeSignatures": [
+ "c19c086ed81a8e7d7877bb2fb5a9d7df126ad553cbdd32086694b927042adc0b"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ },
+ "c689fe4e10fee4bdd5a3d759c027be8b89d28303078f76bb5aeb20dc192215c9": {
+ "signature": "c689fe4e10fee4bdd5a3d759c027be8b89d28303078f76bb5aeb20dc192215c9",
+ "alternativeSignatures": [
+ "4faf3b308c9131f0e11686d21fd36e1ef6779c394d37cfc43cd360b4bfb086f5"
+ ],
+ "memberOf": [
+ "default"
+ ],
+ "createdDate": "2025-10-09 21:18:42Z"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/efcore/.config/guardian/gdnbaselines b/src/efcore/.config/guardian/gdnbaselines
deleted file mode 100644
index b0533e8bab7..00000000000
--- a/src/efcore/.config/guardian/gdnbaselines
+++ /dev/null
@@ -1,26 +0,0 @@
-{
- "hydrated": false,
- "properties": {
- "helpUri": "https://eng.ms/docs/microsoft-security/security/azure-security/cloudai-security-fundamentals-engineering/security-integration/guardian-wiki/microsoft-guardian/general/baselines"
- },
- "version": "1.0.0",
- "baselines": {
- "default": {
- "name": "default",
- "createdDate": "2025-08-19 11:30:04Z",
- "lastUpdatedDate": "2025-08-19 11:30:04Z"
- }
- },
- "results": {
- "289457ef952517284338044be0d68120ad96554e2cd793b14a427b2208be2990": {
- "signature": "289457ef952517284338044be0d68120ad96554e2cd793b14a427b2208be2990",
- "alternativeSignatures": [
- "8b86228cd1b156622e76e1845b23b901cafd908a4dc0a7b7bdd5cdd714b726ab"
- ],
- "memberOf": [
- "default"
- ],
- "createdDate": "2025-08-19 11:30:04Z"
- }
- }
-}
diff --git a/src/efcore/EFCore.sln b/src/efcore/EFCore.sln
index fecc4fafa42..91075f55dfd 100644
--- a/src/efcore/EFCore.sln
+++ b/src/efcore/EFCore.sln
@@ -1,11 +1,12 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 17
-VisualStudioVersion = 17.0.31521.260
+# Visual Studio Version 18
+VisualStudioVersion = 18.0.11026.189
MinimumVisualStudioVersion = 17.0.31521.260
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{B9E4CC99-199C-4E3B-9EC5-D1FDFCD6C27B}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
+ azure-pipelines-internal-tests.yml = azure-pipelines-internal-tests.yml
azure-pipelines-public.yml = azure-pipelines-public.yml
azure-pipelines.yml = azure-pipelines.yml
.github\copilot-instructions.md = .github\copilot-instructions.md
diff --git a/src/efcore/azure-pipelines-internal-tests.yml b/src/efcore/azure-pipelines-internal-tests.yml
index 5f14dbd13bf..2987ae059ef 100644
--- a/src/efcore/azure-pipelines-internal-tests.yml
+++ b/src/efcore/azure-pipelines-internal-tests.yml
@@ -1,8 +1,6 @@
variables:
- name: _BuildConfig
value: Release
- - name: _TeamName
- value: AspNetCore
- name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE
value: true
- name: _PublishUsingPipelines
@@ -11,12 +9,6 @@ variables:
value: https://localhost:8081
- name: _CosmosToken
value: C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
- - ${{ if or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/'), eq(variables['Build.Reason'], 'Manual')) }}:
- - name: PostBuildSign
- value: false
- - ${{ else }}:
- - name: PostBuildSign
- value: true
- group: DotNet-HelixApi-Access
- name: _InternalRuntimeDownloadArgs
value: /p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64)
@@ -47,7 +39,6 @@ extends:
parameters:
featureFlags:
autoBaseline: false
- usePrefastVersion3: true
autoEnableRoslynWithNewRuleset: false
sdl:
createAdoIssuesForJustificationsForDisablement: false
@@ -55,19 +46,46 @@ extends:
name: $(DncEngInternalBuildPool)
image: 1es-windows-2022
os: windows
+ enabled: false
baseline:
baselineFile: $(Build.SourcesDirectory)\.config\guardian\.gdnbaselines
binskim:
- scanOutputDirectoryOnly: true
- preReleaseVersion: '4.3.1'
- env:
- GDN_EXTRACT_TOOLS: "binskim"
- GDN_EXTRACT_TARGETS: true
- GDN_EXTRACT_FILTER: "f|**\\*.zip;f|**\\*.nupkg;f|**\\*.vsix;f|**\\*.cspkg;f|**\\*.sfpkg;f|**\\*.package"
+ enabled: false
+ justificationForDisabling: 'NonProduction'
policheck:
- enabled: true
+ enabled: false
+ justificationForDisabling: 'NonProduction'
tsa:
- enabled: true
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ antimalwareScan:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ prefast:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ codeQL:
+ compiled:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ psscriptanalyzer:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ credscan:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ spmi:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ componentgovernance:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ eslint:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
+ armory:
+ enabled: false
+ justificationForDisabling: 'NonProduction'
customBuildTags:
- ES365AIMigrationTooling
stages:
@@ -78,10 +96,10 @@ extends:
parameters:
enableMicrobuild: true
enablePublishBuildArtifacts: true
- enablePublishBuildAssets: true
+ enablePublishBuildAssets: false
enablePublishTestResults: true
- enablePublishUsingPipelines: ${{ variables._PublishUsingPipelines }}
publishAssetsImmediately: true
+ isAssetlessBuild: true
enableTelemetry: true
helixRepo: dotnet/efcore
jobs:
@@ -95,15 +113,6 @@ extends:
- _InternalBuildArgs: ''
# Rely on task Arcade injects, not auto-injected build step.
- skipComponentGovernanceDetection: true
- - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}:
- - _SignType: real
- - _InternalBuildArgs: /p:DotNetSignType=$(_SignType) /p:TeamName=$(_TeamName) /p:DotNetPublishUsingPipelines=$(_PublishUsingPipelines) /p:OfficialBuildId=$(BUILD.BUILDNUMBER)
- # Ignore test and infrastructure code.
- - Codeql.SourceRoot: src
- # CodeQL3000 needs this plumbed along as a variable to enable TSA.
- - Codeql.TSAEnabled: true
- # Default expects tsaoptions.json under SourceRoot.
- - Codeql.TSAOptionsPath: '$(Build.SourcesDirectory)/.config/tsaoptions.json'
steps:
- task: NuGetCommand@2
displayName: 'Clear NuGet caches'
@@ -125,25 +134,6 @@ extends:
env:
Test__Cosmos__DefaultConnection: $(_CosmosConnectionUrl)
displayName: Build
- - task: CopyFiles@2
- displayName: 'Copy binaries for publishing'
- inputs:
- Contents: |
- artifacts/bin/**/?(*.dll|*.exe|*.pdb)
- !artifacts/bin/*Tests/**
- TargetFolder: $(Agent.TempDirectory)/BinArtifacts
- templateContext:
- outputs:
- - output: pipelineArtifact
- displayName: Publish binaries
- condition: always()
- path: $(Agent.TempDirectory)/BinArtifacts/
- artifact: BinArtifacts
- - output: pipelineArtifact
- displayName: Upload TestResults
- condition: always()
- path: artifacts/TestResults/$(_BuildConfig)/
- artifact: $(Agent.Os)_$(Agent.JobName) TestResults
- job: macOS
pool:
name: Azure Pipelines
@@ -161,13 +151,6 @@ extends:
# Work-around for https://github.com/dotnet/runtime/issues/70758
COMPlus_EnableWriteXorExecute: 0
displayName: Build
- templateContext:
- outputs:
- - output: pipelineArtifact
- displayName: Upload TestResults
- condition: always()
- path: artifacts/TestResults/$(_BuildConfig)/
- artifact: $(Agent.Os)_$(Agent.JobName) TestResults
- job: Linux
timeoutInMinutes: 180
pool:
@@ -213,12 +196,6 @@ extends:
sdl:
binskim:
prereleaseVersion: ' '
- outputs:
- - output: pipelineArtifact
- displayName: Upload TestResults
- condition: always()
- path: artifacts/TestResults/$(_BuildConfig)/
- artifact: $(Agent.Os)_$(Agent.JobName) TestResults
- job: Helix
timeoutInMinutes: 180
pool:
@@ -266,13 +243,3 @@ extends:
# Work-around for https://github.com/dotnet/runtime/issues/70758
COMPlus_EnableWriteXorExecute: 0
DotNetBuildsInternalReadSasToken: $(dotnetbuilds-internal-container-read-token)
- - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}:
- - template: /eng/common/templates-official/post-build/post-build.yml@self
- parameters:
- publishingInfraVersion: 3
- enableSigningValidation: false
- enableNugetValidation: false
- enableSourceLinkValidation: false
- publishAssetsImmediately: true
- SDLValidationParameters:
- enable: false
diff --git a/src/efcore/azure-pipelines-public.yml b/src/efcore/azure-pipelines-public.yml
index 6a3bf435d1d..70d4bdfdb3f 100644
--- a/src/efcore/azure-pipelines-public.yml
+++ b/src/efcore/azure-pipelines-public.yml
@@ -45,6 +45,7 @@ stages:
enablePublishBuildAssets: true
enablePublishUsingPipelines: ${{ variables._PublishUsingPipelines }}
publishAssetsImmediately: true
+ isAssetlessBuild: true
enableSourceIndex: false
enableTelemetry: true
helixRepo: dotnet/efcore
diff --git a/src/efcore/azure-pipelines.yml b/src/efcore/azure-pipelines.yml
index 5f14dbd13bf..510a2ff8ce6 100644
--- a/src/efcore/azure-pipelines.yml
+++ b/src/efcore/azure-pipelines.yml
@@ -6,11 +6,7 @@ variables:
- name: DOTNET_SKIP_FIRST_TIME_EXPERIENCE
value: true
- name: _PublishUsingPipelines
- value: true
- - name: _CosmosConnectionUrl
- value: https://localhost:8081
- - name: _CosmosToken
- value: C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==
+ value: false
- ${{ if or(startswith(variables['Build.SourceBranch'], 'refs/heads/release/'), startswith(variables['Build.SourceBranch'], 'refs/heads/internal/release/'), eq(variables['Build.Reason'], 'Manual')) }}:
- name: PostBuildSign
value: false
@@ -59,6 +55,7 @@ extends:
baselineFile: $(Build.SourcesDirectory)\.config\guardian\.gdnbaselines
binskim:
scanOutputDirectoryOnly: true
+ analyzeTargetGlob: '+:f|artifacts/bin/**/Microsoft.EntityFrameworkCore*.dll;+:f|artifacts/bin/**/Microsoft.Data.Sqlite*.dll;+:f|artifacts/bin/**/ef.exe;+:f|artifacts/bin/**/dotnet-ef.exe;-:f|artifacts/bin/**/shims/**/*.exe;'
preReleaseVersion: '4.3.1'
env:
GDN_EXTRACT_TOOLS: "binskim"
@@ -78,10 +75,10 @@ extends:
parameters:
enableMicrobuild: true
enablePublishBuildArtifacts: true
- enablePublishBuildAssets: true
- enablePublishTestResults: true
- enablePublishUsingPipelines: ${{ variables._PublishUsingPipelines }}
+ enablePublishBuildAssets: false
+ enablePublishTestResults: false
publishAssetsImmediately: true
+ isAssetlessBuild: true
enableTelemetry: true
helixRepo: dotnet/efcore
jobs:
@@ -90,13 +87,14 @@ extends:
name: $(DncEngInternalBuildPool)
demands: ImageOverride -equals 1es-windows-2022
os: windows
- timeoutInMinutes: 180
+ timeoutInMinutes: 60
variables:
- _InternalBuildArgs: ''
# Rely on task Arcade injects, not auto-injected build step.
- skipComponentGovernanceDetection: true
- ${{ if notin(variables['Build.Reason'], 'PullRequest') }}:
- _SignType: real
+ - _Sign: true
- _InternalBuildArgs: /p:DotNetSignType=$(_SignType) /p:TeamName=$(_TeamName) /p:DotNetPublishUsingPipelines=$(_PublishUsingPipelines) /p:OfficialBuildId=$(BUILD.BUILDNUMBER)
# Ignore test and infrastructure code.
- Codeql.SourceRoot: src
@@ -117,162 +115,7 @@ extends:
- script: "echo ##vso[build.addbuildtag]release-candidate"
condition: and(notin(variables['Build.Reason'], 'PullRequest'), eq(variables['IsFinalBuild'], 'true'))
displayName: 'Set CI tags'
- - powershell: SqlLocalDB start
- displayName: Start LocalDB
- - template: /eng/common/templates-official/steps/enable-internal-sources.yml
- - template: /eng/common/templates-official/steps/enable-internal-runtimes.yml
- - script: eng\common\cibuild.cmd -configuration $(_BuildConfig) -prepareMachine $(_InternalBuildArgs) $(_InternalRuntimeDownloadArgs)
- env:
- Test__Cosmos__DefaultConnection: $(_CosmosConnectionUrl)
- displayName: Build
- - task: CopyFiles@2
- displayName: 'Copy binaries for publishing'
- inputs:
- Contents: |
- artifacts/bin/**/?(*.dll|*.exe|*.pdb)
- !artifacts/bin/*Tests/**
- TargetFolder: $(Agent.TempDirectory)/BinArtifacts
- templateContext:
- outputs:
- - output: pipelineArtifact
- displayName: Publish binaries
- condition: always()
- path: $(Agent.TempDirectory)/BinArtifacts/
- artifact: BinArtifacts
- - output: pipelineArtifact
- displayName: Upload TestResults
- condition: always()
- path: artifacts/TestResults/$(_BuildConfig)/
- artifact: $(Agent.Os)_$(Agent.JobName) TestResults
- - job: macOS
- pool:
- name: Azure Pipelines
- image: macOS-13
- os: macOS
- variables:
- # Rely on task Arcade injects, not auto-injected build step.
- - skipComponentGovernanceDetection: true
- steps:
- - template: /eng/common/templates-official/steps/enable-internal-sources.yml
- - template: /eng/common/templates-official/steps/enable-internal-runtimes.yml
- - script: eng/common/build.sh --restore --build --test --pack --ci --configuration $(_BuildConfig) --prepareMachine $(_InternalRuntimeDownloadArgs)
- env:
- Test__Cosmos__DefaultConnection: $(_CosmosConnectionUrl)
- # Work-around for https://github.com/dotnet/runtime/issues/70758
- COMPlus_EnableWriteXorExecute: 0
- displayName: Build
- templateContext:
- outputs:
- - output: pipelineArtifact
- displayName: Upload TestResults
- condition: always()
- path: artifacts/TestResults/$(_BuildConfig)/
- artifact: $(Agent.Os)_$(Agent.JobName) TestResults
- - job: Linux
- timeoutInMinutes: 180
- pool:
- name: $(DncEngInternalBuildPool)
- demands: ImageOverride -equals 1es-ubuntu-2204
- os: linux
- variables:
- - _runCounter: $[counter(variables['Build.Reason'], 0)]
- # Rely on task Arcade injects, not auto-injected build step.
- - skipComponentGovernanceDetection: true
- - ${{ if notin(variables['Build.Reason'], 'PullRequest', 'Schedule') }}:
- - _CosmosConnectionUrl: 'true'
- steps:
- - bash: |
- echo "##vso[task.setvariable variable=_CosmosConnectionUrl]https://ef-nightly-test.documents.azure.com:443/"
- displayName: Prepare to run Cosmos tests on ef-nightly-test
- condition: and(eq(variables['_CosmosConnectionUrl'], 'true'), or(endsWith(variables['_runCounter'], '0'), endsWith(variables['_runCounter'], '2'), endsWith(variables['_runCounter'], '4'), endsWith(variables['_runCounter'], '6'), endsWith(variables['_runCounter'], '8')))
- - bash: |
- echo "##vso[task.setvariable variable=_CosmosConnectionUrl]https://ef-pr-test.documents.azure.com:443/"
- displayName: Prepare to run Cosmos tests on ef-pr-test
- condition: and(eq(variables['_CosmosConnectionUrl'], 'true'), or(endsWith(variables['_runCounter'], '1'), endsWith(variables['_runCounter'], '3'), endsWith(variables['_runCounter'], '5'), endsWith(variables['_runCounter'], '7'), endsWith(variables['_runCounter'], '9')))
- template: /eng/common/templates-official/steps/enable-internal-sources.yml
- template: /eng/common/templates-official/steps/enable-internal-runtimes.yml
- - script: eng/common/build.sh --restore --build --test --pack --ci --configuration $(_BuildConfig) --prepareMachine $(_InternalRuntimeDownloadArgs)
+ - script: eng\common\build.cmd -restore -build -sign -pack -publish -ci -configuration $(_BuildConfig) -prepareMachine $(_InternalRuntimeDownloadArgs)
displayName: Build
- - task: AzureCLI@2
- displayName: Run Cosmos tests
- condition: notin(variables['Build.Reason'], 'PullRequest', 'Schedule')
- inputs:
- azureSubscription: EFCosmosTesting
- addSpnToEnvironment: true
- scriptType: bash
- scriptLocation: 'inlineScript'
- inlineScript: |
- ./test.sh --ci --configuration $(_BuildConfig) --projects $(Build.SourcesDirectory)/test/EFCore.Cosmos.FunctionalTests/EFCore.Cosmos.FunctionalTests.csproj
- env:
- Test__Cosmos__DefaultConnection: $(_CosmosConnectionUrl)
- Test__Cosmos__UseTokenCredential: true
- Test__Cosmos__SubscriptionId: d709b837-4a74-4aec-addc-b6e4b9b23e7e
- Test__Cosmos__ResourceGroup: efcosmosci
- name: Build
- templateContext:
- sdl:
- binskim:
- prereleaseVersion: ' '
- outputs:
- - output: pipelineArtifact
- displayName: Upload TestResults
- condition: always()
- path: artifacts/TestResults/$(_BuildConfig)/
- artifact: $(Agent.Os)_$(Agent.JobName) TestResults
- - job: Helix
- timeoutInMinutes: 180
- pool:
- name: $(DncEngInternalBuildPool)
- demands: ImageOverride -equals 1es-windows-2022
- os: windows
- variables:
- # Rely on task Arcade injects, not auto-injected build step.
- - skipComponentGovernanceDetection: true
- - name: _HelixBuildConfig
- value: $(_BuildConfig)
- - name: HelixTargetQueues
- value: Windows.10.Amd64;OSX.13.Amd64;OSX.13.ARM64;Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-22.04-helix-sqlserver-amd64
- - name: _HelixAccessToken
- # Needed for internal queues
- value: $(HelixApiAccessToken)
- steps:
- - task: NuGetCommand@2
- displayName: 'Clear NuGet caches'
- condition: succeeded()
- inputs:
- command: custom
- arguments: 'locals all -clear'
- - template: /eng/common/templates-official/steps/enable-internal-sources.yml
- - template: /eng/common/templates-official/steps/enable-internal-runtimes.yml
- - ${{ if ne(variables['System.TeamProject'], 'public') }}:
- - template: /eng/common/core-templates/steps/get-delegation-sas.yml
- parameters:
- federatedServiceConnection: 'dotnetbuilds-internal-read'
- outputVariableName: 'dotnetbuilds-internal-container-read-token'
- expiryInHours: 1
- base64Encode: false
- storageAccount: dotnetbuilds
- container: internal
- permissions: rl
- - script: restore.cmd -ci /p:configuration=$(_BuildConfig) $(_InternalRuntimeDownloadArgs)
- displayName: Restore packages
- - script: .dotnet\dotnet build eng\helix.proj /restore /t:Test /p:configuration=$(_BuildConfig) /bl:$(Build.SourcesDirectory)/artifacts/log/$(_BuildConfig)/SendToHelix.binlog $(_InternalRuntimeDownloadArgs)
- displayName: Send job to helix
- env:
- HelixAccessToken: $(_HelixAccessToken)
- # We need to set this env var to publish helix results to Azure Dev Ops
- SYSTEM_ACCESSTOKEN: $(System.AccessToken)
- MSSQL_SA_PASSWORD: "PLACEHOLDERPass$$w0rd"
- # Work-around for https://github.com/dotnet/runtime/issues/70758
- COMPlus_EnableWriteXorExecute: 0
- DotNetBuildsInternalReadSasToken: $(dotnetbuilds-internal-container-read-token)
- - ${{ if notin(variables['Build.Reason'], 'PullRequest') }}:
- - template: /eng/common/templates-official/post-build/post-build.yml@self
- parameters:
- publishingInfraVersion: 3
- enableSigningValidation: false
- enableNugetValidation: false
- enableSourceLinkValidation: false
- publishAssetsImmediately: true
- SDLValidationParameters:
- enable: false
diff --git a/src/efcore/eng/Version.Details.props b/src/efcore/eng/Version.Details.props
index 0549f6aee01..397aed1c2f8 100644
--- a/src/efcore/eng/Version.Details.props
+++ b/src/efcore/eng/Version.Details.props
@@ -6,24 +6,24 @@ This file should be imported by eng/Versions.props
- 10.0.0-beta.25479.115
- 10.0.0-beta.25479.115
- 10.0.0-beta.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
- 10.0.0-rtm.25479.115
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-beta.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
+ 10.0.0-rtm.25509.106
diff --git a/src/efcore/eng/Version.Details.xml b/src/efcore/eng/Version.Details.xml
index cda2ae34f9c..709bc9ecf05 100644
--- a/src/efcore/eng/Version.Details.xml
+++ b/src/efcore/eng/Version.Details.xml
@@ -1,80 +1,80 @@
-
+
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- e72b5bbe719d747036ce9c36582a205df9f1c361
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
diff --git a/src/efcore/global.json b/src/efcore/global.json
index 7576fe190a4..a83f17df244 100644
--- a/src/efcore/global.json
+++ b/src/efcore/global.json
@@ -18,7 +18,7 @@
}
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25479.115",
- "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25479.115"
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25509.106",
+ "Microsoft.DotNet.Helix.Sdk": "10.0.0-beta.25509.106"
}
}
diff --git a/src/efcore/src/EFCore.Relational/Query/Internal/RelationalParameterProcessor.cs b/src/efcore/src/EFCore.Relational/Query/Internal/RelationalParameterProcessor.cs
index 392a94f28a9..433b0b317c1 100644
--- a/src/efcore/src/EFCore.Relational/Query/Internal/RelationalParameterProcessor.cs
+++ b/src/efcore/src/EFCore.Relational/Query/Internal/RelationalParameterProcessor.cs
@@ -31,7 +31,7 @@ private readonly IDictionary _visitedFromSqlExpre
/// (i.e. they're prefixed), since
/// can be prefixed or not.
///
- private readonly HashSet _prefixedParameterNames = [];
+ private readonly HashSet _prefixedParameterNames = new(StringComparer.OrdinalIgnoreCase);
private readonly Dictionary _sqlParameters = new();
diff --git a/src/efcore/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs b/src/efcore/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs
index 8d066cc59e5..f91ad1dee97 100644
--- a/src/efcore/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs
+++ b/src/efcore/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs
@@ -1529,13 +1529,39 @@ public override async Task Using_same_parameter_twice_in_query_generates_one_sql
AssertSql();
}
- public override async Task Two_parameters_with_same_name_get_uniquified(bool async)
- {
- // Concat with conversion, issue #34963.
- await AssertTranslationFailed(() => base.Using_same_parameter_twice_in_query_generates_one_sql_parameter(async));
+ public override Task Two_parameters_with_same_name_get_uniquified(bool async)
+ => Fixture.NoSyncTest(
+ async, async a =>
+ {
+ await base.Two_parameters_with_same_name_get_uniquified(async);
- AssertSql();
- }
+ AssertSql(
+ """
+@customerId='ANATR'
+@customerId0='ALFKI'
+
+SELECT VALUE c
+FROM root c
+WHERE ((c["id"] = @customerId) OR (c["id"] = @customerId0))
+""");
+ });
+
+ public override Task Two_parameters_with_same_case_insensitive_name_get_uniquified(bool async)
+ => Fixture.NoSyncTest(
+ async, async a =>
+ {
+ await base.Two_parameters_with_same_case_insensitive_name_get_uniquified(async);
+
+ AssertSql(
+ """
+@customerID='ANATR'
+@customerId='ALFKI'
+
+SELECT VALUE c
+FROM root c
+WHERE ((c["id"] = @customerID) OR (c["id"] = @customerId))
+""");
+ });
public override async Task Where_Queryable_ToList_Count(bool async)
{
diff --git a/src/efcore/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs b/src/efcore/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs
index 69c990d6845..e4beae2c27e 100644
--- a/src/efcore/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs
+++ b/src/efcore/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs
@@ -1327,16 +1327,27 @@ public virtual Task Using_same_parameter_twice_in_query_generates_one_sql_parame
.Select(c => c.CustomerID));
}
+ private readonly string customerId = "ALFKI";
+
[ConditionalTheory, MemberData(nameof(IsAsyncData))]
public virtual Task Two_parameters_with_same_name_get_uniquified(bool async)
{
- var i = 10;
+ var customerId = "ANATR";
+
+ return AssertQuery(
+ async,
+ ss => ss.Set().Where(c => c.CustomerID == customerId || c.CustomerID == this.customerId));
+ }
+
+ [ConditionalTheory, MemberData(nameof(IsAsyncData))]
+ public virtual Task Two_parameters_with_same_case_insensitive_name_get_uniquified(bool async)
+ {
+ var customerID = "ANATR";
- // i+1 and i+2 each get parameterized using the same parameter name (since they're complex expressions).
- // This exercises that query parameters are properly uniquified.
+ // Note the parameter names differ only by case (customerID vs. customerId)
return AssertQuery(
async,
- ss => ss.Set().Where(c => (c.CustomerID + (i + 1)) + (c.CustomerID + (i + 2)) == "ALFKI11ALFKI12"));
+ ss => ss.Set().Where(c => c.CustomerID == customerID || c.CustomerID == customerId));
}
[ConditionalTheory, MemberData(nameof(IsAsyncData))]
diff --git a/src/efcore/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs b/src/efcore/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs
index bd0137646c4..63a234e7e7c 100644
--- a/src/efcore/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs
+++ b/src/efcore/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindWhereQuerySqlServerTest.cs
@@ -1704,19 +1704,33 @@ WHERE CAST(@i AS nvarchar(max)) + [c].[CustomerID] + CAST(@i AS nvarchar(max)) =
""");
}
- [ConditionalTheory]
public override async Task Two_parameters_with_same_name_get_uniquified(bool async)
{
await base.Two_parameters_with_same_name_get_uniquified(async);
AssertSql(
"""
-@p='11'
-@p0='12'
+@customerId='ANATR' (Size = 5) (DbType = StringFixedLength)
+@customerId0='ALFKI' (Size = 5) (DbType = StringFixedLength)
+
+SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
+FROM [Customers] AS [c]
+WHERE [c].[CustomerID] = @customerId OR [c].[CustomerID] = @customerId0
+""");
+ }
+
+ public override async Task Two_parameters_with_same_case_insensitive_name_get_uniquified(bool async)
+ {
+ await base.Two_parameters_with_same_case_insensitive_name_get_uniquified(async);
+
+AssertSql(
+"""
+@customerID='ANATR' (Size = 5) (DbType = StringFixedLength)
+@customerId0='ALFKI' (Size = 5) (DbType = StringFixedLength)
SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]
FROM [Customers] AS [c]
-WHERE [c].[CustomerID] + CAST(@p AS nvarchar(max)) + [c].[CustomerID] + CAST(@p0 AS nvarchar(max)) = N'ALFKI11ALFKI12'
+WHERE [c].[CustomerID] = @customerID OR [c].[CustomerID] = @customerId0
""");
}
diff --git a/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs b/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs
index 21db8554f0a..fc1a8a78f1e 100644
--- a/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs
+++ b/src/razor/src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/SourceGenerators/RazorCohostingOptions.cs
@@ -5,5 +5,5 @@ internal static class RazorCohostingOptions
///
/// True if razor is running in the cohosting mode
///
- internal static bool UseRazorCohostServer { get; set; } = true;
+ internal static bool UseRazorCohostServer { get; set; } = false;
}
diff --git a/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs b/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs
index 8c78aaec0db..20e5cba815c 100644
--- a/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs
+++ b/src/razor/src/Compiler/test/Microsoft.NET.Sdk.Razor.SourceGenerators.Tests/RazorSourceGeneratorTests.cs
@@ -10,7 +10,6 @@
using System.Linq;
using System.Text;
using System.Threading.Tasks;
-using Microsoft.AspNetCore.Razor.Language.Syntax;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Test.Utilities;
@@ -2616,9 +2615,6 @@ public async Task SourceGenerator_DoesNotUpdateSources_WhenSourceGeneratorIsSupp
// start with the generator suppressed (this is the default state in VS)
driver = SetSuppressionState(true);
- // Disable co-hosting, this test only applies to non-cohosting scenarios
- RazorCohostingOptions.UseRazorCohostServer = false;
-
// results should be empty, and no recorded steps should have run
using var eventListener = new RazorEventListener();
var result = RunGenerator(compilation!, ref driver).VerifyPageOutput();
@@ -3461,7 +3457,6 @@ public async Task UseRazorCohostServer_CanOverride_Suppression()
["Component.Razor"] = "
Hello world
",
});
var compilation = await project.GetCompilationAsync();
- RazorCohostingOptions.UseRazorCohostServer = false;
// Start with the generator suppressed
var (driver, additionalTexts, optionsProvider) = await GetDriverWithAdditionalTextAndProviderAsync(project, configureGlobalOptions: (o) =>
diff --git a/src/razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/RazorAnalyzerAssemblyRedirector.cs b/src/razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/RazorAnalyzerAssemblyRedirector.cs
index 2da57734d95..092ce70ba9e 100644
--- a/src/razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/RazorAnalyzerAssemblyRedirector.cs
+++ b/src/razor/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/RazorAnalyzerAssemblyRedirector.cs
@@ -25,8 +25,10 @@ internal sealed class RazorAnalyzerAssemblyRedirector() : IRazorAnalyzerAssembly
GetRedirectEntry(typeof(AspNetCore.Razor.ArgHelper)), // Microsoft.AspNetCore.Razor.Utilities.Shared
// The following dependencies will be provided by the Compiler ALC so its not strictly required to redirect them, but we do so for completeness.
- GetRedirectEntry(typeof(Microsoft.Extensions.ObjectPool.ObjectPool)), // Microsoft.Extensions.ObjectPool
- GetRedirectEntry(typeof(ImmutableArray)) // System.Collections.Immutable
+ GetRedirectEntry(typeof(ImmutableArray)), // System.Collections.Immutable
+
+ // ObjectPool is special
+ GetObjectPoolRedirect() // Microsoft.Extensions.ObjectPool
];
private static readonly FrozenDictionary s_compilerAssemblyMap = s_compilerAssemblyTypes.ToFrozenDictionary(t => t.name, t => t.path);
@@ -37,6 +39,53 @@ internal sealed class RazorAnalyzerAssemblyRedirector() : IRazorAnalyzerAssembly
return s_compilerAssemblyMap.TryGetValue(name, out var path) ? path : null;
}
+ private static (string name, string path) GetObjectPoolRedirect()
+ {
+ // Temporary fix for: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2583134
+ // In VS (where this code is running) ObjectPool comes from the shared assemblies folder.
+
+ // When Roslyn wins the race to load Razor it shadow copies the assemblies before resolving them. Roslyn shadow copies assemblies
+ // into a directory based on the directory they came from. Because ObjectPool has a different directory path from the rest of
+ // our assemblies, we end up with two shadow copy directories: one for ObjectPool and one for everything else.
+
+ // Roslyn creates an ALC per directory where the assemblies are loaded from.
+ // ObjectPool isn't loaded into the same ALC as the rest of the compiler. When we come to use the ObjectPool in the compiler, it
+ // has to be resolved because its not already loaded.
+ // This invokes our assembly resolver code (which is currently in the Roslyn EA). However, our resolver expects to find the ObjectPool assembly
+ // to load next to the compiler assembly, which it isn't because of the shadow copying. It fails to load ObjectPool. That then means resolution falls back to
+ // the ServiceHub loader, which *is* able to successfully load a copy of the assembly from the framework, but into its own ALC. This is the copy of the
+ // ObjectPool that the compiler 'binds' against. Call this ObjectPool(1).
+
+ // When Razor tooling starts up, it also wants to load the same assemblies, and goes through the assembly resolver for any razor assemblies.
+ // Because it doesn't consider shadow copying, it requests them from a different path than Roslyn loaded them from (the razor language services folder).
+ // Because the compiler assemblies are already loaded (from the shadow copy folder) the resolver just returns those assemblies. These are, in fact the
+ // same assemblies so this is correct up to this point.
+ // However, when the tooling goes to load ObjectPool it calls into the resolver with the path from *the razor language services folder*. The resolver
+ // previously failed to load ObjectPool, so it tries again. This time, with the updated path, it is able to find it next to the compiler
+ // assembly and successfully load it. Call this ObjectPool(2)
+
+ // That means that the razor tooling has the compiler assemblies and ObjectPool(2), which are all in the same ALC. However, because of the earlier failed
+ // load the compiler assemblies are 'bound' to ObjectPool(1). That causes a MissingMethodException when we come to use any of the methods from the compiler
+ // assemblies: it is looking for a method bound to ObjectPool(1), but can't find it because it has ObjectPool(2).
+
+ // This doesn't happen if Razor tooling loads first. It is able to resolve ObjectPool at the same time as the compiler assemblies, and 'binds' them. When
+ // the source generator is loaded by Roslyn all of the assemblies are already loaded and can just be re-used.
+
+ // The correct fix is to not shadow copy razor assemblies (see https://github.com/dotnet/razor/issues/12307) which will ensure that the initial resolve
+ // is able to find the assembly and load it into the same ALC as the compiler assemblies when Roslyn wins the race.
+
+ // For now, to ensure consistent assembly loading and avoid ALC mismatches, explicitly override the location of ObjectPool to be next to the compiler assemblies.
+ // This ensures that when Roslyn does the shadow copy, all assemblies end up in the same directory and ALC, allowing them to be re-used when Razor loads.
+
+ // Get the compiler assembly location
+ var (_, compilerAssemblyLocation) = GetRedirectEntry(typeof(CodeAnalysis.Razor.CompilerFeatures));
+
+ // Get the redirect for the object pool, but override its location to be next to the compiler
+ var objectPoolRedirect = GetRedirectEntry(typeof(Microsoft.Extensions.ObjectPool.ObjectPool));
+ objectPoolRedirect.path = Path.Combine(Path.GetDirectoryName(compilerAssemblyLocation)!, $"{objectPoolRedirect.name}.dll");
+ return objectPoolRedirect;
+ }
+
private static (string name, string path) GetRedirectEntry(Type type, string? overrideName = null)
{
return (
diff --git a/src/roslyn/eng/Version.Details.props b/src/roslyn/eng/Version.Details.props
index 51efebaf0a7..e24a868f47c 100644
--- a/src/roslyn/eng/Version.Details.props
+++ b/src/roslyn/eng/Version.Details.props
@@ -9,7 +9,7 @@ This file should be imported by eng/Versions.props
3.11.04.10.0-1.24061.4
- 2.0.0-rtm.25507.103
+ 2.0.0-rtm.25509.1069.0.09.0.0
diff --git a/src/roslyn/eng/Version.Details.xml b/src/roslyn/eng/Version.Details.xml
index 79cd3e0eec7..bf9bdd564bc 100644
--- a/src/roslyn/eng/Version.Details.xml
+++ b/src/roslyn/eng/Version.Details.xml
@@ -1,15 +1,15 @@
-
+ https://github.com/dotnet/roslynae1fff344d46976624e68ae17164e0607ab68b10
-
+ https://github.com/dotnet/dotnet
- 915977521b41280adbe21a54345be23cb5bf3536
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/DiagnosticAnalyzerTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/DiagnosticAnalyzerTests.cs
index bb6dc5aecab..2c98eac46a0 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/DiagnosticAnalyzerTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/DiagnosticAnalyzerTests.cs
@@ -4640,5 +4640,17 @@ void M()
Assert.Same(analyzer1.SeenOptions, analyzer2.SeenOptions);
}
}
+
+ [Fact]
+ public async Task TestGetAnalysisResultAsyncWithUnknownAnalyzerThrows()
+ {
+ var compilation = CreateCompilation("").VerifyDiagnostics();
+
+ var compilationWithAnalyzers = compilation.WithAnalyzers([new CSharpCompilerDiagnosticAnalyzer()]);
+
+ // Calling with a DiagnosticAnalyzer that was not specified in 'WithAnalyzers' should throw.
+ await Assert.ThrowsAnyAsync(() =>
+ compilationWithAnalyzers.GetAnalysisResultAsync([new CSharpCompilerDiagnosticAnalyzer()], CancellationToken.None));
+ }
}
}
diff --git a/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/GetDiagnosticsTests.cs b/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/GetDiagnosticsTests.cs
index 3a7a679a1ab..19f59d0bd4f 100644
--- a/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/GetDiagnosticsTests.cs
+++ b/src/roslyn/src/Compilers/CSharp/Test/Emit3/Diagnostics/GetDiagnosticsTests.cs
@@ -1590,6 +1590,61 @@ internal class TestAttribute : Attribute
Assert.Equal(DiagnosticSuppressorForCS0657.SuppressionId, suppression.Descriptor.Id);
}
+ [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2581061")]
+ public async Task TestDiagnosticSuppressor_GetAnalysisResultAsyncCrash()
+ {
+ var source = """
+ using System;
+
+ public class SomeClass
+ {
+ [property: Test]
+ public string Name;
+ }
+
+ internal class TestAttribute : Attribute
+ {
+ }
+ """;
+ var compilation = CreateCompilation(source).VerifyDiagnostics(
+ // (5,6): warning CS0657: 'property' is not a valid attribute location for this declaration. Valid attribute locations for this declaration are 'field'. All attributes in this block will be ignored.
+ // [property: Test]
+ Diagnostic(ErrorCode.WRN_AttributeLocationOnBadDeclaration, "property").WithArguments("property", "field").WithLocation(5, 6));
+
+ // Verify that CS0657 can be suppressed with a DiagnosticSuppressor
+ var diagnosticAnalyzer = new CSharpCompilerDiagnosticAnalyzer();
+ var suppressor = new DiagnosticSuppressorForCS0657();
+
+ // Create options with our own getAnalyzerConfigOptionsProvider. That way we do initialize the map from
+ // analyzer to options within the AnalyzerDriver. This map needs to contain all analyzers and suppressors,
+ // not just the one we're calling into with GetAnalysisResultAsync.
+ var options = new CompilationWithAnalyzersOptions(
+ AnalyzerOptions.Empty,
+ onAnalyzerException: null,
+ concurrentAnalysis: false,
+ logAnalyzerExecutionTime: false,
+ reportSuppressedDiagnostics: true,
+ analyzerExceptionFilter: null,
+ getAnalyzerConfigOptionsProvider: _ => new CompilerAnalyzerConfigOptionsProvider(
+ ImmutableDictionarytotal:
- total:
+ celkem:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
index 70630b7a74b..6f0c0b4e099 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.de.xlf
@@ -1164,12 +1164,12 @@ Weitere Informationen finden Sie unter https://aka.ms/dotnet-test/mtp..NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ .NET-Testbefehl für Microsoft.Testing.Platform (über die Datei „global.json“ aktiviert). Dies unterstützt ausschließlich Microsoft.Testing.Platform und nicht VSTest. Weitere Informationen finden Sie unter https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ .NET-Testbefehl für VSTest. Um Microsoft.Testing.Platform zu verwenden, aktivieren Sie den Microsoft.Testing.Platform-basierten Befehl über global.json. Weitere Informationen finden Sie unter https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Erstellen Sie eindeutige Profilnamen.
duration:
- duration:
+ Dauer:error:
- error:
+ Fehler:
@@ -1298,7 +1298,7 @@ Erstellen Sie eindeutige Profilnamen.
failed:
- failed:
+ fehlgeschlagen:
@@ -2574,7 +2574,7 @@ Standardmäßig wird eine Framework-abhängige Anwendung veröffentlicht.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ Direktiven dürfen derzeit keine doppelten Anführungszeichen (") enthalten.
@@ -2699,7 +2699,7 @@ Standardmäßig wird eine Framework-abhängige Anwendung veröffentlicht.
retried
- retried
+ Wiederholung
@@ -2983,7 +2983,7 @@ Ihr Projekt verwendet mehrere Zielframeworks. Geben Sie über "{0}" an, welches
skipped:
- skipped:
+ übersprungen:
@@ -3123,7 +3123,7 @@ Ihr Projekt verwendet mehrere Zielframeworks. Geben Sie über "{0}" an, welches
succeeded:
- succeeded:
+ erfolgreich:
@@ -3589,7 +3589,7 @@ und die zugehörigen Paket-IDs für installierte Tools über den Befehl
total:
- total:
+ gesamt:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
index 84d3025e048..8fc261f14d5 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.es.xlf
@@ -1164,12 +1164,12 @@ Consulte https://aka.ms/dotnet-test/mtp para obtener más información.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Comando de prueba de .NET para Microsoft.Testing.Platform (activado mediante el archivo “global.json”). Solo es compatible con Microsoft.Testing.Platform y no con VSTest. Consulte https://aka.ms/dotnet-test para obtener más información.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ Comando de prueba de .NET para VSTest. Para usar Microsoft.Testing.Platform, actívelo en el comando basado en Microsoft.Testing.Platform mediante global.json. Consulte https://aka.ms/dotnet-test para obtener más información.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Defina nombres de perfiles distintos.
duration:
- duration:
+ duración:error:
- error:
+ error:
@@ -1298,7 +1298,7 @@ Defina nombres de perfiles distintos.
failed:
- failed:
+ error:
@@ -2574,7 +2574,7 @@ El valor predeterminado es publicar una aplicación dependiente del marco.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ Las directivas no pueden contener comillas dobles ("), por ahora.
@@ -2699,7 +2699,7 @@ El valor predeterminado es publicar una aplicación dependiente del marco.
retried
- retried
+ volver a intentarlo
@@ -2983,7 +2983,7 @@ Su proyecto tiene como destino varias plataformas. Especifique la que quiere usa
skipped:
- skipped:
+ omitido:
@@ -3123,7 +3123,7 @@ Su proyecto tiene como destino varias plataformas. Especifique la que quiere usa
succeeded:
- succeeded:
+ correcto:
@@ -3589,7 +3589,7 @@ y los identificadores de los paquetes correspondientes a las herramientas instal
total:
- total:
+ total:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
index 3b1487a7704..3d8be0107a5 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.fr.xlf
@@ -1164,12 +1164,12 @@ Pour découvrir plus d’informations, consultez https://aka.ms/dotnet-test/mtp.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Commande de test .NET pour Microsoft.Testing.Platform (activée via le fichier « global.json »). Cela prend uniquement en charge Microsoft.Testing.Platform et ne prend pas en charge VSTest. Pour plus d'informations, consultez https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ Commande de test .NET pour VSTest. Pour utiliser Microsoft.Testing.Platform, optez pour la commande basée sur Microsoft.Testing.Platform via global.json. Pour plus d'informations, consultez https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Faites en sorte que les noms de profil soient distincts.
duration:
- duration:
+ durée :error:
- error:
+ erreur :
@@ -1298,7 +1298,7 @@ Faites en sorte que les noms de profil soient distincts.
failed:
- failed:
+ échec :
@@ -2574,7 +2574,7 @@ La valeur par défaut est de publier une application dépendante du framework.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ Les directives ne peuvent actuellement pas contenir de guillemets doubles (").
@@ -2699,7 +2699,7 @@ La valeur par défaut est de publier une application dépendante du framework.
retried
- retried
+ réessayé
@@ -2983,7 +2983,7 @@ Votre projet cible plusieurs frameworks. Spécifiez le framework à exécuter à
skipped:
- skipped:
+ ignoré :
@@ -3123,7 +3123,7 @@ Votre projet cible plusieurs frameworks. Spécifiez le framework à exécuter à
succeeded:
- succeeded:
+ réussie :
@@ -3589,7 +3589,7 @@ et les ID de package correspondants aux outils installés, utilisez la commande
total:
- total:
+ total :
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
index fffbb67c75e..ff2e8c98609 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.it.xlf
@@ -1164,12 +1164,12 @@ Per altre informazioni, vedere https://aka.ms/dotnet-test/mtp.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Comando di test .NET per Microsoft.Testing.Platform (attivato tramite il file 'global.json'). Supporta solo Microsoft.Testing.Platform e non VSTest. Per altre informazioni, vedere https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ Comando di test .NET per VSTest. Per usare Microsoft.Testing.Platform, attivare il comando basato su Microsoft.Testing.Platform tramite global.json. Per altre informazioni, vedere https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Rendi distinti i nomi profilo.
duration:
- duration:
+ durata:error:
- error:
+ errore:
@@ -1298,7 +1298,7 @@ Rendi distinti i nomi profilo.
failed:
- failed:
+ non riuscito:
@@ -2574,7 +2574,7 @@ Per impostazione predefinita, viene generato un pacchetto dipendente dal framewo
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ Le direttive attualmente non possono contenere virgolette doppie (").
@@ -2699,7 +2699,7 @@ Per impostazione predefinita, viene generato un pacchetto dipendente dal framewo
retried
- retried
+ ripetuto
@@ -2983,7 +2983,7 @@ Il progetto è destinato a più framework. Specificare il framework da eseguire
skipped:
- skipped:
+ ignorato:
@@ -3123,7 +3123,7 @@ Il progetto è destinato a più framework. Specificare il framework da eseguire
succeeded:
- succeeded:
+ operazione completata:
@@ -3589,7 +3589,7 @@ e gli ID pacchetto corrispondenti per gli strumenti installati usando il comando
total:
- total:
+ totale:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
index 4a9b4564cd8..40678fb35f7 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ja.xlf
@@ -1164,12 +1164,12 @@ See https://aka.ms/dotnet-test/mtp for more information.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Microsoft.Testing.Platform 用の .NET テスト コマンド ('global.json' ファイルでオプトイン済み)。これは Microsoft.Testing.Platform のみをサポートしており、VSTest には対応していません。詳細については、https://aka.ms/dotnet-test をご覧ください。{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ VSTest 用の .NET テスト コマンド。Microsoft.Testing.Platform を使用するには、global.json ファイルで Microsoft.Testing.Platform ベースのコマンドにオプトインしてください。詳細については、https://aka.ms/dotnet-test をご覧ください。{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Make the profile names distinct.
duration:
- duration:
+ 期間:error:
- error:
+ エラー:
@@ -1298,7 +1298,7 @@ Make the profile names distinct.
failed:
- failed:
+ 失敗:
@@ -2574,7 +2574,7 @@ The default is to publish a framework-dependent application.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ ディレクティブには二重引用符 (") を含めることはできません。
@@ -2699,7 +2699,7 @@ The default is to publish a framework-dependent application.
retried
- retried
+ 再試行済み
@@ -2983,7 +2983,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
skipped:
- skipped:
+ スキップ済み:
@@ -3123,7 +3123,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
succeeded:
- succeeded:
+ 成功:
@@ -3589,7 +3589,7 @@ and the corresponding package Ids for installed tools using the command
total:
- total:
+ 合計:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
index d7a462877fb..b2f6c81c0d2 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ko.xlf
@@ -1164,12 +1164,12 @@ See https://aka.ms/dotnet-test/mtp for more information.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Microsoft.Testing.Platform용 .NET 테스트 명령입니다('global.json' 파일을 통해 옵트인). 이는 Microsoft.Testing.Platform만 지원하며 VSTest를 지원하지 않습니다. 자세한 내용은 https://aka.ms/dotnet-test를 참조하세요.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ VSTest에 대한 .NET 테스트 명령입니다. Microsoft.Testing.Platform을 사용하려면 global.json을 통해 Microsoft.Testing.Platform 기반 명령을 옵트인합니다. 자세한 내용은 https://aka.ms/dotnet-test를 참조하세요.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Make the profile names distinct.
duration:
- duration:
+ 기간:error:
- error:
+ 오류:
@@ -1298,7 +1298,7 @@ Make the profile names distinct.
failed:
- failed:
+ 실패:
@@ -2574,7 +2574,7 @@ The default is to publish a framework-dependent application.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ 지시문은 현재 큰따옴표(")를 포함할 수 없습니다.
@@ -2699,7 +2699,7 @@ The default is to publish a framework-dependent application.
retried
- retried
+ 다시 시도됨
@@ -2983,7 +2983,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
skipped:
- skipped:
+ 건너뜀:
@@ -3123,7 +3123,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
succeeded:
- succeeded:
+ 성공:
@@ -3589,7 +3589,7 @@ and the corresponding package Ids for installed tools using the command
total:
- total:
+ 합계:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
index 455c06c0f7d..bc9182e525a 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pl.xlf
@@ -1164,12 +1164,12 @@ Aby uzyskać więcej informacji, zobacz https://aka.ms/dotnet-test/mtp.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Polecenie testowe platformy .NET dla elementu Microsoft.Testing.Platform (aktywowane przez plik „global.json”). Obsługuje tylko Microsoft.Testing.Platform i nie obsługuje VSTest. Aby uzyskać więcej informacji, zobacz https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ Polecenie testowe platformy .NET dla narzędzia VSTest. Aby korzystać z platformy Microsoft.Testing.Platform, wyraź zgodę na użycie polecenia opartego na Microsoft.Testing.Platform za pośrednictwem pliku global.json. Aby uzyskać więcej informacji, zobacz https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Rozróżnij nazwy profilów.
duration:
- duration:
+ czas trwania:error:
- error:
+ błąd:
@@ -1298,7 +1298,7 @@ Rozróżnij nazwy profilów.
failed:
- failed:
+ zakończone niepowodzeniem:
@@ -2574,7 +2574,7 @@ Domyślnie publikowana jest aplikacja zależna od struktury.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ Dyrektywy nie mogą obecnie zawierać podwójnych cudzysłowów (").
@@ -2699,7 +2699,7 @@ Domyślnie publikowana jest aplikacja zależna od struktury.
retried
- retried
+ próbowano ponownie
@@ -2983,7 +2983,7 @@ Projekt ma wiele platform docelowych. Określ platformę do uruchomienia przy u
skipped:
- skipped:
+ pominięto:
@@ -3123,7 +3123,7 @@ Projekt ma wiele platform docelowych. Określ platformę do uruchomienia przy u
succeeded:
- succeeded:
+ zakończone powodzeniem:
@@ -3589,7 +3589,7 @@ i odpowiednie identyfikatory pakietów zainstalowanych narzędzi można znaleź
total:
- total:
+ suma:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
index f999a934e37..be9c08f1ce8 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.pt-BR.xlf
@@ -1164,12 +1164,12 @@ Consulte https://aka.ms/dotnet-test/mtp para obter mais informações.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Comando de Teste .NET para Microsoft.Testing.Platform (aceito por meio do arquivo 'global.json'). Isso dá suporte apenas a Microsoft.Testing.Platform e não dá suporte a VSTest. Para obter mais informações, confira https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ Comando de Teste .NET para VSTest. Para usar a Microsoft.Testing.Platform, faça a aceitação do comando baseado em Microsoft.Testing.Platform por meio do global.json. Para obter mais informações, confira https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Diferencie os nomes dos perfis.
duration:
- duration:
+ duração:error:
- error:
+ erro:
@@ -1298,7 +1298,7 @@ Diferencie os nomes dos perfis.
failed:
- failed:
+ falhou:
@@ -2574,7 +2574,7 @@ O padrão é publicar uma aplicação dependente de framework.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ No momento, as diretivas não podem conter aspas duplas (").
@@ -2699,7 +2699,7 @@ O padrão é publicar uma aplicação dependente de framework.
retried
- retried
+ repetido
@@ -2983,7 +2983,7 @@ Ele tem diversas estruturas como destino. Especifique que estrutura executar usa
skipped:
- skipped:
+ ignorados:
@@ -3123,7 +3123,7 @@ Ele tem diversas estruturas como destino. Especifique que estrutura executar usa
succeeded:
- succeeded:
+ concluído com êxito:
@@ -3589,7 +3589,7 @@ e as Ids de pacote correspondentes para as ferramentas instaladas usando o coman
total:
- total:
+ total:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
index adae2e4b3b1..694c6428205 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.ru.xlf
@@ -1164,12 +1164,12 @@ See https://aka.ms/dotnet-test/mtp for more information.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Тестовая команда .NET для Microsoft.Testing.Platform (предоставлено согласие с помощью файла global.json). Поддерживается только Microsoft.Testing.Platform, VSTest не поддерживается. Дополнительные сведения см. на странице https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ Тестовая команда .NET для VSTest. Чтобы использовать Microsoft.Testing.Platform, согласитесь на использование команды на основе Microsoft.Testing.Platform посредством global.json. Дополнительные сведения см. на странице https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Make the profile names distinct.
duration:
- duration:
+ длительность:error:
- error:
+ ошибка:
@@ -1298,7 +1298,7 @@ Make the profile names distinct.
failed:
- failed:
+ сбой:
@@ -2574,7 +2574,7 @@ The default is to publish a framework-dependent application.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ В директивах пока нельзя использовать двойные кавычки (").
@@ -2699,7 +2699,7 @@ The default is to publish a framework-dependent application.
retried
- retried
+ повторено
@@ -2983,7 +2983,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
skipped:
- skipped:
+ пропущено:
@@ -3123,7 +3123,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
succeeded:
- succeeded:
+ успешно:
@@ -3590,7 +3590,7 @@ and the corresponding package Ids for installed tools using the command
total:
- total:
+ итог:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
index 4e19bf47de4..f5b9e9b3825 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.tr.xlf
@@ -1164,12 +1164,12 @@ Daha fazla bilgi için https://aka.ms/dotnet-test/mtp adresine bakın.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ Microsoft.Testing.Platform için .NET Test Komutu ('global.json' dosyasıyla seçildi). Bu sadece Microsoft.Testing.Platform'u destekler, VSTest'i desteklemez. Daha fazla bilgi için bkz. https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ VSTest için .NET Test Komutu. Microsoft.Testing.Platform'u kullanmak için global.json üzerinden Microsoft.Testing.Platform tabanlı komutu seçin. Daha fazla bilgi için bkz. https://aka.ms/dotnet-test.{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Lütfen profil adlarını değiştirin.
duration:
- duration:
+ süre:error:
- error:
+ hata:
@@ -1298,7 +1298,7 @@ Lütfen profil adlarını değiştirin.
failed:
- failed:
+ başarısız oldu:
@@ -2574,7 +2574,7 @@ Varsayılan durum, çerçeveye bağımlı bir uygulama yayımlamaktır.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ Yönergeler şu anda çift tırnak (") içeremez.
@@ -2699,7 +2699,7 @@ Varsayılan durum, çerçeveye bağımlı bir uygulama yayımlamaktır.
retried
- retried
+ yeniden denendi
@@ -2983,7 +2983,7 @@ Projeniz birden fazla Framework'ü hedefliyor. '{0}' kullanarak hangi Framework'
skipped:
- skipped:
+ atlandı:
@@ -3123,7 +3123,7 @@ Projeniz birden fazla Framework'ü hedefliyor. '{0}' kullanarak hangi Framework'
succeeded:
- succeeded:
+ başarılı:
@@ -3589,7 +3589,7 @@ karşılık gelen paket kimliklerini bulmak için
total:
- total:
+ toplam:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
index 85e43f3d508..725ed5df548 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hans.xlf
@@ -1164,12 +1164,12 @@ See https://aka.ms/dotnet-test/mtp for more information.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ 适用于 Microsoft.Testing.Platform 的 .NET 测试命令(已通过 "global.json" 文件选择加入)。此命令仅支持 Microsoft.Testing.Platform,不支持 VSTest。有关详细信息,请参阅 https://aka.ms/dotnet-test。{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ 适用于 VSTest 的 .NET 测试命令。若要使用 Microsoft.Testing.Platform,请通过 global.json 选择加入基于 Microsoft.Testing.Platform 的命令。有关详细信息,请参阅 https://aka.ms/dotnet-test。{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Make the profile names distinct.
duration:
- duration:
+ 持续时间:error:
- error:
+ 错误:
@@ -1298,7 +1298,7 @@ Make the profile names distinct.
failed:
- failed:
+ 失败:
@@ -2574,7 +2574,7 @@ The default is to publish a framework-dependent application.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ 指令当前不能包含双引号(")。
@@ -2699,7 +2699,7 @@ The default is to publish a framework-dependent application.
retried
- retried
+ 已重试
@@ -2983,7 +2983,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
skipped:
- skipped:
+ 已跳过:
@@ -3123,7 +3123,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
succeeded:
- succeeded:
+ 成功:
@@ -3589,7 +3589,7 @@ and the corresponding package Ids for installed tools using the command
total:
- total:
+ 总计:
diff --git a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
index 7023d8771c0..db6fc4bd2dd 100644
--- a/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
+++ b/src/sdk/src/Cli/dotnet/Commands/xlf/CliCommandStrings.zh-Hant.xlf
@@ -1164,12 +1164,12 @@ See https://aka.ms/dotnet-test/mtp for more information.
.NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for Microsoft.Testing.Platform (opted-in via 'global.json' file). This only supports Microsoft.Testing.Platform and doesn't support VSTest. For more information, see https://aka.ms/dotnet-test.
+ .NET 測試命令,適用於 Microsoft.Testing.Platform (透過 'global.json' 檔案選擇加入)。此命令僅支援 Microsoft.Testing.Platform,不支援 VSTest。如需詳細資訊,請參閱 https://aka.ms/dotnet-test。{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}.NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
- .NET Test Command for VSTest. To use Microsoft.Testing.Platform, opt-in to the Microsoft.Testing.Platform-based command via global.json. For more information, see https://aka.ms/dotnet-test.
+ 適用於 VSTest 的 .NET 測試命令。若要使用 Microsoft.Testing.Platform,請透過 global.json 選擇加入以 Microsoft.Testing.Platform 為基礎的命令。如需詳細資訊,請參閱 https://aka.ms/dotnet-test。{Locked="global.json"}{Locked="Microsoft.Testing.Platform"}{Locked="VSTest"}
@@ -1238,12 +1238,12 @@ Make the profile names distinct.
duration:
- duration:
+ 期間:error:
- error:
+ 錯誤:
@@ -1298,7 +1298,7 @@ Make the profile names distinct.
failed:
- failed:
+ 失敗:
@@ -2574,7 +2574,7 @@ The default is to publish a framework-dependent application.
Directives currently cannot contain double quotes (").
- Directives currently cannot contain double quotes (").
+ 指令目前不能包含雙引號 (")。
@@ -2699,7 +2699,7 @@ The default is to publish a framework-dependent application.
retried
- retried
+ 已重試
@@ -2983,7 +2983,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
skipped:
- skipped:
+ 已略過:
@@ -3123,7 +3123,7 @@ Your project targets multiple frameworks. Specify which framework to run using '
succeeded:
- succeeded:
+ 已成功:
@@ -3589,7 +3589,7 @@ and the corresponding package Ids for installed tools using the command
total:
- total:
+ 總計:
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.cs.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.cs.xlf
index 793563fbddd..a55342a500c 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.cs.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.cs.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Odkaz na balíček ve formě identifikátoru balíčku, jako je „{0}“, nebo identifikátor balíčku a verze oddělené znakem @, například „{0}@{1}“.
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.de.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.de.xlf
index 75a8ea0992b..92adccab483 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.de.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.de.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Paketverweis in Form eines Paketbezeichners wie {0} oder Paketbezeichner und -version getrennt durch „@“ wie „{0}@{1}“.
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.es.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.es.xlf
index e1598973152..db4dd74c144 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.es.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.es.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Referencia de paquete en forma de identificador de paquete como "{0}" o identificador de paquete y versión separados por "@", como "{0}@{1}".
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.fr.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.fr.xlf
index c559d991fdb..f9b5582e430 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.fr.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.fr.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Référence de package sous la forme d’un identificateur de package tel que « {0} » ou d’un identificateur de package et d’une version séparés par « @ », comme « {0}@{1} ».
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.it.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.it.xlf
index 632432b2b28..8e5fb8a55e0 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.it.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.it.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Riferimento al pacchetto sotto forma di identificatore di pacchetto, ad esempio '{0}', oppure identificatore e versione di pacchetto separati da '@', ad esempio '{0}@{1}'.
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.ja.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.ja.xlf
index 4ec60d0c7ee..2504e04d917 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.ja.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.ja.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ '{0}' のようなパッケージ ID の形式のパッケージ参照、または '{0}@{1}' のように '@' で区切られたパッケージ ID とバージョンです。
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.ko.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.ko.xlf
index c65066c2341..af4f6dc21b6 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.ko.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.ko.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ '{0}'과 같은 패키지 식별자 또는 '{0}@{1}'과 같이 '@'로 구분된 패키지 식별자 및 버전 형식의 패키지 참조입니다.
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.pl.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.pl.xlf
index 47183ec7a67..b92f633f89d 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.pl.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.pl.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Odwołanie do pakietu w formie identyfikatora pakietu, takiego jak „{0}” lub identyfikatora pakietu i wersji, rozdzielonych znakiem „@”, np. „{0}@{1}”.
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf
index fccf80013c6..48cd96b70fa 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.pt-BR.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Referência de pacote na forma de um identificador de pacote como '{0}' ou identificador de pacote e versão separados por '@', como '{0}@{1}'.
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.ru.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.ru.xlf
index 3814f20f1ca..774a83ee7bd 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.ru.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.ru.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ Ссылка на пакет в виде идентификатора пакета, например "{0}", или идентификатора пакета и версии, разделенных "@", например "{0}@{1}".
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.tr.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.tr.xlf
index e6dc0a5df79..e3a3c95596e 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.tr.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.tr.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ '{0}' gibi bir paket tanımlayıcısı veya '{0}@{1}' gibi '@' ile ayrılmış paket tanımlayıcısı ve sürümü şeklinde paket başvurusu.
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf
index 7dc1e93e52e..12a34a5c5fa 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hans.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ 包引用的格式为包标识符,如 ‘{0}’,或由 ‘@’ 分隔的包标识符和版本,如 ‘{0}@{1}’。
diff --git a/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf b/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf
index bd3384fb806..7666715348c 100644
--- a/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf
+++ b/src/sdk/src/Cli/dotnet/xlf/CliStrings.zh-Hant.xlf
@@ -784,7 +784,7 @@ setx PATH "%PATH%;{0}"
Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
- Package reference in the form of a package identifier like '{0}' or package identifier and version separated by '@' like '{0}@{1}'.
+ 套件參考的格式為套件識別碼,例如 '{0}',或是以 '@' 分隔的套件識別碼和版本,例如 '{0}@{1}'。
diff --git a/src/sdk/src/Layout/pkg/windows/bundles/sdk/bundle.wxs b/src/sdk/src/Layout/pkg/windows/bundles/sdk/bundle.wxs
index 5836502fcd6..2503b1dac02 100644
--- a/src/sdk/src/Layout/pkg/windows/bundles/sdk/bundle.wxs
+++ b/src/sdk/src/Layout/pkg/windows/bundles/sdk/bundle.wxs
@@ -27,7 +27,13 @@
-
+
+
+
+
+
+
diff --git a/src/sdk/src/Layout/redist/dnx.ps1 b/src/sdk/src/Layout/redist/dnx.ps1
deleted file mode 100644
index ff880f85e2f..00000000000
--- a/src/sdk/src/Layout/redist/dnx.ps1
+++ /dev/null
@@ -1,8 +0,0 @@
-# Licensed to the .NET Foundation under one or more agreements.
-# The .NET Foundation licenses this file to you under the MIT license.
-
-# PowerShell script to launch dotnet.exe with 'dnx' and all passed arguments
-$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Definition
-$dotnet = Join-Path $scriptDir 'dotnet.exe'
-& $dotnet dnx @Args
-exit $LASTEXITCODE
diff --git a/src/sdk/src/Layout/redist/targets/GenerateInstallerLayout.targets b/src/sdk/src/Layout/redist/targets/GenerateInstallerLayout.targets
index 4c7aa7749e3..069c6a2fde2 100644
--- a/src/sdk/src/Layout/redist/targets/GenerateInstallerLayout.targets
+++ b/src/sdk/src/Layout/redist/targets/GenerateInstallerLayout.targets
@@ -67,7 +67,6 @@
-
diff --git a/src/sdk/src/Layout/redist/targets/GeneratePackagePruneData.targets b/src/sdk/src/Layout/redist/targets/GeneratePackagePruneData.targets
index 157eeabd5cd..f414f6582c7 100644
--- a/src/sdk/src/Layout/redist/targets/GeneratePackagePruneData.targets
+++ b/src/sdk/src/Layout/redist/targets/GeneratePackagePruneData.targets
@@ -30,13 +30,12 @@
-
-
+
-
+ DependsOnTargets="GetTargetingPacksForPruneData">
+
diff --git a/src/sdk/src/Layout/redist/targets/OverlaySdkOnLKG.targets b/src/sdk/src/Layout/redist/targets/OverlaySdkOnLKG.targets
index 19505de69d5..faf995466d4 100644
--- a/src/sdk/src/Layout/redist/targets/OverlaySdkOnLKG.targets
+++ b/src/sdk/src/Layout/redist/targets/OverlaySdkOnLKG.targets
@@ -34,7 +34,7 @@
+ UseHardLinksIfPossible="false" />
- <_NormalizedWindowsSdkSupportedTargetPlatformVersion Include="@(WindowsSdkSupportedTargetPlatformVersion)">
- $([System.Version]::Parse('%(Identity)').Major).$([System.Version]::Parse('%(Identity)').Minor).$([System.Version]::Parse('%(Identity)').Build).0
-
-
+ <_NormalizedWindowsSdkSupportedTargetPlatformVersion Include="@(WindowsSdkSupportedTargetPlatformVersion)">
+ $([System.Text.RegularExpressions.Regex]::Replace(%(Identity), '^((\d+\.){3})1$', '${1}0'))
+
+
diff --git a/src/sdk/src/Tasks/sdk-tasks/sdk-tasks.InTree.targets b/src/sdk/src/Tasks/sdk-tasks/sdk-tasks.InTree.targets
index 2176f30216f..547f8ccd759 100644
--- a/src/sdk/src/Tasks/sdk-tasks/sdk-tasks.InTree.targets
+++ b/src/sdk/src/Tasks/sdk-tasks/sdk-tasks.InTree.targets
@@ -13,7 +13,6 @@
-
diff --git a/src/sdk/template_feed/Microsoft.DotNet.Common.ItemTemplates/content/EditorConfig/Dotnet/.editorconfig b/src/sdk/template_feed/Microsoft.DotNet.Common.ItemTemplates/content/EditorConfig/Dotnet/.editorconfig
index bb88786e7b5..af3d70051e2 100644
--- a/src/sdk/template_feed/Microsoft.DotNet.Common.ItemTemplates/content/EditorConfig/Dotnet/.editorconfig
+++ b/src/sdk/template_feed/Microsoft.DotNet.Common.ItemTemplates/content/EditorConfig/Dotnet/.editorconfig
@@ -9,7 +9,7 @@ indent_style = space
indent_size = 2
# Xml project files
-[*.{csproj,fsproj,vbproj,proj}]
+[*.{csproj,fsproj,vbproj,proj,slnx}]
indent_size = 2
# Xml config files
diff --git a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-CSharp/Company.TestProject1.csproj b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-CSharp/Company.TestProject1.csproj
index b4490a1d30f..415f0f4b220 100644
--- a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-CSharp/Company.TestProject1.csproj
+++ b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-CSharp/Company.TestProject1.csproj
@@ -1,5 +1,5 @@
-
+net10.0
@@ -43,7 +43,7 @@
-
+
diff --git a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-FSharp/Company.TestProject1.fsproj b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-FSharp/Company.TestProject1.fsproj
index a1b85e78555..6c64e1cd116 100644
--- a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-FSharp/Company.TestProject1.fsproj
+++ b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-FSharp/Company.TestProject1.fsproj
@@ -1,5 +1,5 @@
-
+net10.0
@@ -48,7 +48,7 @@
-
+
diff --git a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-VisualBasic/Company.TestProject1.vbproj b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-VisualBasic/Company.TestProject1.vbproj
index b4490a1d30f..415f0f4b220 100644
--- a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-VisualBasic/Company.TestProject1.vbproj
+++ b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/MSTest-VisualBasic/Company.TestProject1.vbproj
@@ -1,5 +1,5 @@
-
+net10.0
@@ -43,7 +43,7 @@
-
+
diff --git a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/Playwright-MSTest-CSharp/Company.TestProject1.csproj b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/Playwright-MSTest-CSharp/Company.TestProject1.csproj
index 9c6ca5d3e25..2cffa453be0 100644
--- a/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/Playwright-MSTest-CSharp/Company.TestProject1.csproj
+++ b/src/sdk/template_feed/Microsoft.DotNet.Common.ProjectTemplates.10.0/content/Playwright-MSTest-CSharp/Company.TestProject1.csproj
@@ -1,5 +1,5 @@
-
+net10.0
@@ -44,8 +44,8 @@
-
-
+
+
diff --git a/src/sdk/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/TestProject.csproj b/src/sdk/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/TestProject.csproj
index ff9709d80d6..7bf348d2d58 100644
--- a/src/sdk/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/TestProject.csproj
+++ b/src/sdk/test/TestAssets/TestProjects/TestProjectSolutionWithCodeCoverage/TestProject/TestProject.csproj
@@ -1,13 +1,12 @@
-
+$(CurrentTargetFramework)False
- 17.12.6
-
\ No newline at end of file
+
diff --git a/src/sdk/test/dotnet-new.IntegrationTests/Approvals/AllCommonItemsCreate.-o#EditorConfig-file#-n#item.verified/EditorConfig-file/.editorconfig b/src/sdk/test/dotnet-new.IntegrationTests/Approvals/AllCommonItemsCreate.-o#EditorConfig-file#-n#item.verified/EditorConfig-file/.editorconfig
index 37f826f6640..fa2cc7622c2 100644
--- a/src/sdk/test/dotnet-new.IntegrationTests/Approvals/AllCommonItemsCreate.-o#EditorConfig-file#-n#item.verified/EditorConfig-file/.editorconfig
+++ b/src/sdk/test/dotnet-new.IntegrationTests/Approvals/AllCommonItemsCreate.-o#EditorConfig-file#-n#item.verified/EditorConfig-file/.editorconfig
@@ -9,7 +9,7 @@ indent_style = space
indent_size = 2
# Xml project files
-[*.{csproj,fsproj,vbproj,proj}]
+[*.{csproj,fsproj,vbproj,proj,slnx}]
indent_size = 2
# Xml config files
diff --git a/src/sdk/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs b/src/sdk/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs
index 104438d0808..501ce980b20 100644
--- a/src/sdk/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs
+++ b/src/sdk/test/dotnet-watch.Tests/HotReload/ApplyDeltaTests.cs
@@ -440,6 +440,64 @@ public async Task AutoRestartOnRudeEdit(bool nonInteractive)
await App.WaitForOutputLineContaining(MessageDescriptor.HotReloadSucceeded);
}
+ [Theory]
+ [CombinatorialData]
+ public async Task AutoRestartOnRuntimeRudeEdit(bool nonInteractive)
+ {
+ var testAsset = TestAssets.CopyTestAsset("WatchHotReloadApp")
+ .WithSource();
+
+ var tfm = ToolsetInfo.CurrentTargetFramework;
+ var programPath = Path.Combine(testAsset.Path, "Program.cs");
+
+ // Changes the type of lambda without updating top-level code.
+ // The loop will end up calling the old version of the lambda resulting in runtime rude edit.
+
+ File.WriteAllText(programPath, """
+ using System;
+ using System.Threading;
+
+ var d = C.F();
+
+ while (true)
+ {
+ Thread.Sleep(250);
+ d(1);
+ }
+
+ class C
+ {
+ public static Action F()
+ {
+ return a =>
+ {
+ Console.WriteLine(a.GetType());
+ };
+ }
+ }
+ """);
+
+ App.Start(testAsset, nonInteractive ? ["--non-interactive"] : []);
+
+ await App.WaitForOutputLineContaining(MessageDescriptor.WaitingForChanges);
+ await App.WaitUntilOutputContains("System.Int32");
+ App.Process.ClearOutput();
+
+ UpdateSourceFile(programPath, src => src.Replace("Action", "Action"));
+
+ await App.WaitForOutputLineContaining(MessageDescriptor.WaitingForChanges);
+ await App.WaitUntilOutputContains("System.Byte");
+
+ App.AssertOutputContains($"dotnet watch 🕵️ [WatchHotReloadApp ({tfm})] HotReloadException handler installed.");
+ App.AssertOutputContains($"dotnet watch 🕵️ [WatchHotReloadApp ({tfm})] Runtime rude edit detected:");
+
+ App.AssertOutputContains($"dotnet watch ⚠ [WatchHotReloadApp ({tfm})] " +
+ "Attempted to invoke a deleted lambda or local function implementation. " +
+ "This can happen when lambda or local function is deleted while the application is running.");
+
+ App.AssertOutputContains(MessageDescriptor.RestartingApplication, $"WatchHotReloadApp ({tfm})");
+ }
+
[Fact]
public async Task AutoRestartOnRudeEditAfterRestartPrompt()
{
diff --git a/src/sdk/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs b/src/sdk/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs
index 499c04e6883..ff2c8491194 100644
--- a/src/sdk/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs
+++ b/src/sdk/test/dotnet-watch.Tests/HotReload/RuntimeProcessLauncherTests.cs
@@ -526,7 +526,7 @@ public async Task RudeEditInProjectWithoutRunningProcess()
// Terminate the process:
Log($"Terminating process {runningProject.ProjectNode.GetDisplayName()} ...");
- await runningProject.TerminateAsync(isRestarting: false);
+ await runningProject.TerminateAsync();
// rude edit in A (changing assembly level attribute):
UpdateSourceFile(serviceSourceA2, """
diff --git a/src/sdk/test/dotnet-watch.Tests/TestUtilities/AssertEx.cs b/src/sdk/test/dotnet-watch.Tests/TestUtilities/AssertEx.cs
index aeaffc43f28..c80299e56b7 100644
--- a/src/sdk/test/dotnet-watch.Tests/TestUtilities/AssertEx.cs
+++ b/src/sdk/test/dotnet-watch.Tests/TestUtilities/AssertEx.cs
@@ -249,9 +249,8 @@ private static void AssertSubstringPresence(string expected, IEnumerable
var message = new StringBuilder();
-
message.AppendLine(expectedPresent
- ? "Expected text found in the output:"
+ ? "Expected text not found in the output:"
: "Text not expected to be found in the output:");
message.AppendLine(expected);
diff --git a/src/sdk/test/dotnet.Tests/CommandTests/MSBuild/GivenMSBuildLogger.cs b/src/sdk/test/dotnet.Tests/CommandTests/MSBuild/GivenMSBuildLogger.cs
index eb5678178da..12a75b9493e 100644
--- a/src/sdk/test/dotnet.Tests/CommandTests/MSBuild/GivenMSBuildLogger.cs
+++ b/src/sdk/test/dotnet.Tests/CommandTests/MSBuild/GivenMSBuildLogger.cs
@@ -214,101 +214,5 @@ public void ItIgnoresNonIntegerPropertiesDuringAggregation()
fakeTelemetry.LogEntry.Properties.Should().NotContainKey("InvalidProperty");
fakeTelemetry.LogEntry.Properties.Should().NotContainKey("InvalidProperty2");
}
-
- [Fact]
- public void ItAggregatesEvents()
- {
- var fakeTelemetry = new FakeTelemetry();
- fakeTelemetry.Enabled = true;
- var logger = new MSBuildLogger(fakeTelemetry);
-
- var event1 = new TelemetryEventArgs
- {
- EventName = MSBuildLogger.TaskFactoryTelemetryAggregatedEventName,
- Properties = new Dictionary
- {
- { "AssemblyTaskFactoryTasksExecutedCount", "2" },
- { "RoslynCodeTaskFactoryTasksExecutedCount", "1" }
- }
- };
-
- var event2 = new TelemetryEventArgs
- {
- EventName = MSBuildLogger.TaskFactoryTelemetryAggregatedEventName,
- Properties = new Dictionary
- {
- { "AssemblyTaskFactoryTasksExecutedCount", "3" },
- { "CustomTaskFactoryTasksExecutedCount", "2" }
- }
- };
-
- var event3 = new TelemetryEventArgs
- {
- EventName = MSBuildLogger.TasksTelemetryAggregatedEventName,
- Properties = new Dictionary
- {
- { "TasksExecutedCount", "3" },
- { "TaskHostTasksExecutedCount", "2" }
- }
- };
-
- var event4 = new TelemetryEventArgs
- {
- EventName = MSBuildLogger.TasksTelemetryAggregatedEventName,
- Properties = new Dictionary
- {
- { "TasksExecutedCount", "5" }
- }
- };
-
- logger.AggregateEvent(event1);
- logger.AggregateEvent(event2);
- logger.AggregateEvent(event3);
- logger.AggregateEvent(event4);
-
- logger.SendAggregatedEventsOnBuildFinished(fakeTelemetry);
-
- fakeTelemetry.LogEntries.Should().HaveCount(2);
-
- var taskFactoryEntry = fakeTelemetry.LogEntries.FirstOrDefault(e => e.EventName == $"msbuild/{MSBuildLogger.TaskFactoryTelemetryAggregatedEventName}");
- taskFactoryEntry.Should().NotBeNull();
- taskFactoryEntry.Properties["AssemblyTaskFactoryTasksExecutedCount"].Should().Be("5"); // 2 + 3
- taskFactoryEntry.Properties["RoslynCodeTaskFactoryTasksExecutedCount"].Should().Be("1"); // 1 + 0
- taskFactoryEntry.Properties["CustomTaskFactoryTasksExecutedCount"].Should().Be("2"); // 0 + 2
-
- var tasksEntry = fakeTelemetry.LogEntries.FirstOrDefault(e => e.EventName == $"msbuild/{MSBuildLogger.TasksTelemetryAggregatedEventName}");
- tasksEntry.Should().NotBeNull();
- tasksEntry.Properties["TasksExecutedCount"].Should().Be("8"); // 3 + 5
- tasksEntry.Properties["TaskHostTasksExecutedCount"].Should().Be("2"); // 2 + 0
- }
-
- [Fact]
- public void ItIgnoresNonIntegerPropertiesDuringAggregation()
- {
- var fakeTelemetry = new FakeTelemetry();
- fakeTelemetry.Enabled = true;
- var logger = new MSBuildLogger(fakeTelemetry);
-
- var eventArgs = new TelemetryEventArgs
- {
- EventName = MSBuildLogger.TaskFactoryTelemetryAggregatedEventName,
- Properties = new Dictionary
- {
- { "AssemblyTaskFactoryTasksExecutedCount", "3" },
- { "InvalidProperty", "not-a-number" },
- { "InvalidProperty2", "1.234" },
- }
- };
-
- logger.AggregateEvent(eventArgs);
-
- logger.SendAggregatedEventsOnBuildFinished(fakeTelemetry);
-
- fakeTelemetry.LogEntry.Should().NotBeNull();
- fakeTelemetry.LogEntry.EventName.Should().Be($"msbuild/{MSBuildLogger.TaskFactoryTelemetryAggregatedEventName}");
- fakeTelemetry.LogEntry.Properties["AssemblyTaskFactoryTasksExecutedCount"].Should().Be("3");
- fakeTelemetry.LogEntry.Properties.Should().NotContainKey("InvalidProperty");
- fakeTelemetry.LogEntry.Properties.Should().NotContainKey("InvalidProperty2");
- }
}
}
diff --git a/src/sdk/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs b/src/sdk/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs
index 90763462aeb..72a600549d6 100644
--- a/src/sdk/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs
+++ b/src/sdk/test/dotnet.Tests/CommandTests/Project/Convert/DotnetProjectConvertTests.cs
@@ -1154,6 +1154,50 @@ public void Directives_EmptyName(
expectedWildcardPattern: RunFileTests.DirectiveError("/app/Program.cs", 1, CliCommandStrings.MissingDirectiveName, directive));
}
+ [Theory]
+ [InlineData("")]
+ [InlineData(" ")]
+ public void Directives_EmptyValue(string value)
+ {
+ VerifyConversion(
+ inputCSharp: $"""
+ #:property TargetFramework={value}
+ #:property Prop1={value}
+ #:sdk First@{value}
+ #:sdk Second@{value}
+ #:package P1@{value}
+ """,
+ expectedProject: """
+
+
+
+
+
+ Exe
+ enable
+ enable
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+ """,
+ expectedCSharp: "");
+
+ VerifyConversionThrows(
+ inputCSharp: $"""
+ #:project{value}
+ """,
+ expectedWildcardPattern: RunFileTests.DirectiveError("/app/Program.cs", 1, CliCommandStrings.MissingDirectiveName, "project"));
+ }
+
[Fact]
public void Directives_MissingPropertyValue()
{
diff --git a/src/sdk/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs b/src/sdk/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
index 541788369fb..54c5c845493 100644
--- a/src/sdk/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
+++ b/src/sdk/test/dotnet.Tests/CommandTests/Run/RunFileTests.cs
@@ -1613,6 +1613,230 @@ public void NoBuild_02()
.And.HaveStdOut("Changed");
}
+ [Fact]
+ public void Build_Library()
+ {
+ var testInstance = _testAssetsManager.CreateTestDirectory();
+ var programFile = Path.Join(testInstance.Path, "lib.cs");
+ File.WriteAllText(programFile, """
+ #:property OutputType=Library
+ class C;
+ """);
+
+ var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
+ if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+ new DotnetCommand(Log, "build", "lib.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, "run", "lib.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Fail()
+ .And.HaveStdErr(string.Format(CliCommandStrings.RunCommandExceptionUnableToRun,
+ Path.ChangeExtension(programFile, ".csproj"),
+ ToolsetInfo.CurrentTargetFrameworkVersion,
+ "Library"));
+ }
+
+ [Fact]
+ public void Build_Library_MultiTarget()
+ {
+ var testInstance = _testAssetsManager.CreateTestDirectory();
+ var programFile = Path.Join(testInstance.Path, "lib.cs");
+ File.WriteAllText(programFile, $"""
+ #:property OutputType=Library
+ #:property PublishAot=false
+ #:property LangVersion=preview
+ #:property TargetFrameworks=netstandard2.0;{ToolsetInfo.CurrentTargetFramework}
+ class C;
+ """);
+
+ // https://github.com/dotnet/sdk/issues/51077: cannot set this via `#:property` directive.
+ File.WriteAllText(Path.Join(testInstance.Path, "Directory.Build.props"), """
+
+
+
+
+
+ """);
+
+ var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
+ if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+ new DotnetCommand(Log, "build", "lib.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, "run", "lib.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Fail()
+ .And.HaveStdErr(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyFramework, "--framework"));
+
+ new DotnetCommand(Log, "run", "lib.cs", "--framework", ToolsetInfo.CurrentTargetFramework)
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Fail()
+ .And.HaveStdErr(string.Format(CliCommandStrings.RunCommandExceptionUnableToRun,
+ Path.ChangeExtension(programFile, ".csproj"),
+ ToolsetInfo.CurrentTargetFrameworkVersion,
+ "Library"));
+ }
+
+ [Fact]
+ public void Build_Module()
+ {
+ var testInstance = _testAssetsManager.CreateTestDirectory();
+ var programFile = Path.Join(testInstance.Path, "module.cs");
+ File.WriteAllText(programFile, """
+ #:property OutputType=Module
+ #:property ProduceReferenceAssembly=false
+ class C;
+ """);
+
+ var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
+ if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+ new DotnetCommand(Log, "build", "module.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, "run", "module.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Fail()
+ .And.HaveStdErr(string.Format(CliCommandStrings.RunCommandExceptionUnableToRun,
+ Path.ChangeExtension(programFile, ".csproj"),
+ ToolsetInfo.CurrentTargetFrameworkVersion,
+ "Module"));
+ }
+
+ [Fact]
+ public void Build_WinExe()
+ {
+ var testInstance = _testAssetsManager.CreateTestDirectory();
+ var programFile = Path.Join(testInstance.Path, "winexe.cs");
+ File.WriteAllText(programFile, """
+ #:property OutputType=WinExe
+ Console.WriteLine("Hello WinExe");
+ """);
+
+ var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
+ if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+ new DotnetCommand(Log, "build", "winexe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, "run", "winexe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOut("Hello WinExe");
+ }
+
+ [Fact]
+ public void Build_Exe()
+ {
+ var testInstance = _testAssetsManager.CreateTestDirectory();
+ var programFile = Path.Join(testInstance.Path, "exe.cs");
+ File.WriteAllText(programFile, """
+ #:property OutputType=Exe
+ Console.WriteLine("Hello Exe");
+ """);
+
+ var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
+ if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+ new DotnetCommand(Log, "build", "exe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, "run", "exe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOut("Hello Exe");
+ }
+
+ [Fact]
+ public void Build_Exe_MultiTarget()
+ {
+ var testInstance = _testAssetsManager.CreateTestDirectory();
+ var programFile = Path.Join(testInstance.Path, "exe.cs");
+ File.WriteAllText(programFile, $"""
+ #:property OutputType=Exe
+ #:property PublishAot=false
+ #:property LangVersion=preview
+ #:property TargetFrameworks=netstandard2.0;{ToolsetInfo.CurrentTargetFramework}
+ Console.WriteLine("Hello Exe");
+ """);
+
+ // https://github.com/dotnet/sdk/issues/51077: cannot set this via `#:property` directive.
+ File.WriteAllText(Path.Join(testInstance.Path, "Directory.Build.props"), """
+
+
+
+
+
+ """);
+
+ var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
+ if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+ new DotnetCommand(Log, "build", "exe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, "run", "exe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Fail()
+ .And.HaveStdErr(string.Format(CliCommandStrings.RunCommandExceptionUnableToRunSpecifyFramework, "--framework"));
+
+ new DotnetCommand(Log, "run", "exe.cs", "--framework", ToolsetInfo.CurrentTargetFramework)
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass()
+ .And.HaveStdOut("Hello Exe");
+ }
+
+ [Fact]
+ public void Build_AppContainerExe()
+ {
+ var testInstance = _testAssetsManager.CreateTestDirectory();
+ var programFile = Path.Join(testInstance.Path, "appcontainerexe.cs");
+ File.WriteAllText(programFile, """
+ #:property OutputType=AppContainerExe
+ Console.WriteLine("Hello AppContainerExe");
+ """);
+
+ var artifactsDir = VirtualProjectBuildingCommand.GetArtifactsPath(programFile);
+ if (Directory.Exists(artifactsDir)) Directory.Delete(artifactsDir, recursive: true);
+
+ new DotnetCommand(Log, "build", "appcontainerexe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Pass();
+
+ new DotnetCommand(Log, "run", "appcontainerexe.cs")
+ .WithWorkingDirectory(testInstance.Path)
+ .Execute()
+ .Should().Fail()
+ .And.HaveStdErr(string.Format(CliCommandStrings.RunCommandExceptionUnableToRun,
+ Path.ChangeExtension(programFile, ".csproj"),
+ ToolsetInfo.CurrentTargetFrameworkVersion,
+ "AppContainerExe"));
+ }
+
[Fact]
public void Publish()
{
diff --git a/src/source-manifest.json b/src/source-manifest.json
index a988ed957bc..322086599dc 100644
--- a/src/source-manifest.json
+++ b/src/source-manifest.json
@@ -1,16 +1,16 @@
{
"repositories": [
{
- "barId": 286215,
+ "barId": 286474,
"path": "arcade",
"remoteUri": "https://github.com/dotnet/arcade",
- "commitSha": "7ff6478d902606d65aa33cb8cedc2730e1843fe1"
+ "commitSha": "ba45f22d375e21c42fdc89695451932731d94552"
},
{
- "barId": 286219,
+ "barId": 286532,
"path": "aspnetcore",
"remoteUri": "https://github.com/dotnet/aspnetcore",
- "commitSha": "305280b3a9092b709b4449640e4d8db9a327d46f"
+ "commitSha": "08964b968ed6d4381b74b05cb01afa8daeae5b6d"
},
{
"barId": 279211,
@@ -31,16 +31,16 @@
"commitSha": "c0c52874069a4dc0fe1e880014e6a5f316e9d3b8"
},
{
- "barId": 285923,
+ "barId": 286647,
"path": "diagnostics",
"remoteUri": "https://github.com/dotnet/diagnostics",
- "commitSha": "f40e210b5da69e3c7585917137322cac01f0dffc"
+ "commitSha": "53c7e6f445c2d1a918707a609b0fd08c3604c659"
},
{
- "barId": 285648,
+ "barId": 286575,
"path": "efcore",
"remoteUri": "https://github.com/dotnet/efcore",
- "commitSha": "9f21708d124ca38c7d2c94d5538b597ba20129e1"
+ "commitSha": "f07ec89c55b88de5b1992cbbed86ae0529f3307f"
},
{
"barId": 283436,
@@ -67,22 +67,22 @@
"commitSha": "5514d935e3e77d90d931758cf9e2589735b905a3"
},
{
- "barId": 286084,
+ "barId": 286683,
"path": "razor",
"remoteUri": "https://github.com/dotnet/razor",
- "commitSha": "d52cf7384867f6592a7a45f1696f8fa298441de4"
+ "commitSha": "4e5ddbfa9a31b06d262234f8e582575d6ceb0739"
},
{
- "barId": 286121,
+ "barId": 286456,
"path": "roslyn",
"remoteUri": "https://github.com/dotnet/roslyn",
- "commitSha": "23d275e30097136b12a68d1bab4997148361d116"
+ "commitSha": "929ae2333a73eca047b9b6e2f01bf7121558308f"
},
{
- "barId": 286218,
+ "barId": 286595,
"path": "runtime",
"remoteUri": "https://github.com/dotnet/runtime",
- "commitSha": "d321bc6abef02ed27790e8da3740d253976b9ac6"
+ "commitSha": "a402595199e366ae6cf697d74b9dd43081fa2fcd"
},
{
"barId": 277711,
@@ -91,10 +91,10 @@
"commitSha": "082359066ee0064039b9b1f1f025bdd0507d06de"
},
{
- "barId": 286006,
+ "barId": 286627,
"path": "sdk",
"remoteUri": "https://github.com/dotnet/sdk",
- "commitSha": "cf932ba08b38f8a148536f5d0e9c98d56280cc24"
+ "commitSha": "09b6a7d0d679cf9480932424ae025e83c49fd9f6"
},
{
"barId": 282656,
@@ -115,10 +115,10 @@
"commitSha": "26c6c313a35f020dc9fa8c7270a012bcd75fc81b"
},
{
- "barId": 285272,
+ "barId": 286484,
"path": "templating",
"remoteUri": "https://github.com/dotnet/templating",
- "commitSha": "4c36907d7149f0b3b59c7178acea6330540df851"
+ "commitSha": "89fd90b5b2016cff0ee924dca2c8bf71b4935a39"
},
{
"barId": 285355,
diff --git a/src/templating/.editorconfig b/src/templating/.editorconfig
index bc46cb200f8..178d2855e1c 100644
--- a/src/templating/.editorconfig
+++ b/src/templating/.editorconfig
@@ -186,10 +186,14 @@ dotnet_code_quality.ca1822.api_surface = private, internal
dotnet_code_quality.ca2208.api_surface = public
dotnet_diagnostic.CS1591.severity = suggestion
dotnet_analyzer_diagnostic.category-Style.severity = warning
+#Name can be simplified
+dotnet_diagnostic.IDE0002.severity = suggestion
#Use explicit type instead of var
dotnet_diagnostic.IDE0008.severity = suggestion
#Add missing cases to switch statement
dotnet_diagnostic.IDE0010.severity = suggestion
+#Simplify LINQ expression
+dotnet_diagnostic.IDE0120.severity = suggestion
#Use expression body for constructors
dotnet_diagnostic.IDE0021.severity = suggestion
#Use expression body for methods
@@ -235,6 +239,9 @@ file_header_template = Licensed to the .NET Foundation under one or more agreeme
# Ensure minimum API surface is respected
dotnet_diagnostic.BCL0001.severity = warning
+# Don't require explicit access modifiers for interface members (conflicts with IDE0040)
+dotnet_diagnostic.SA1400.severity = none
+
# AppContext default value expected to be true
dotnet_diagnostic.BCL0010.severity = warning
diff --git a/src/templating/eng/Version.Details.props b/src/templating/eng/Version.Details.props
index 9c9fabfbbc0..1653acc7903 100644
--- a/src/templating/eng/Version.Details.props
+++ b/src/templating/eng/Version.Details.props
@@ -6,8 +6,8 @@ This file should be imported by eng/Versions.props
- 10.0.0-beta.25479.109
- 2.0.0-rtm.25479.109
+ 10.0.0-beta.25509.106
+ 2.0.0-rtm.25509.1069.0.39.0.3
diff --git a/src/templating/eng/Version.Details.xml b/src/templating/eng/Version.Details.xml
index a28e2082ff6..cdaccc6842f 100644
--- a/src/templating/eng/Version.Details.xml
+++ b/src/templating/eng/Version.Details.xml
@@ -1,16 +1,16 @@
-
+
-
+ https://github.com/dotnet/dotnet
- 8aba88f6f12f3ce1dd5740575cff9442f1f9122c
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
-
+ https://github.com/dotnet/dotnet
- 8aba88f6f12f3ce1dd5740575cff9442f1f9122c
+ f448387a0e80f2fdeaec2d2f99ace7284fe37aac
diff --git a/src/templating/eng/common/core-templates/job/source-build.yml b/src/templating/eng/common/core-templates/job/source-build.yml
index d805d5faeb9..947f0971eb5 100644
--- a/src/templating/eng/common/core-templates/job/source-build.yml
+++ b/src/templating/eng/common/core-templates/job/source-build.yml
@@ -34,6 +34,9 @@ parameters:
# container and pool.
platform: {}
+ # Optional list of directories to ignore for component governance scans.
+ componentGovernanceIgnoreDirectories: []
+
is1ESPipeline: ''
# If set to true and running on a non-public project,
@@ -94,3 +97,4 @@ jobs:
parameters:
is1ESPipeline: ${{ parameters.is1ESPipeline }}
platform: ${{ parameters.platform }}
+ componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
diff --git a/src/templating/eng/common/core-templates/jobs/source-build.yml b/src/templating/eng/common/core-templates/jobs/source-build.yml
index d92860cba20..eb4b923a777 100644
--- a/src/templating/eng/common/core-templates/jobs/source-build.yml
+++ b/src/templating/eng/common/core-templates/jobs/source-build.yml
@@ -15,6 +15,9 @@ parameters:
# one job runs on 'defaultManagedPlatform'.
platforms: []
+ # Optional list of directories to ignore for component governance scans.
+ componentGovernanceIgnoreDirectories: []
+
is1ESPipeline: ''
# If set to true and running on a non-public project,
@@ -31,6 +34,7 @@ jobs:
is1ESPipeline: ${{ parameters.is1ESPipeline }}
jobNamePrefix: ${{ parameters.jobNamePrefix }}
platform: ${{ platform }}
+ componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
enableInternalSources: ${{ parameters.enableInternalSources }}
- ${{ if eq(length(parameters.platforms), 0) }}:
@@ -39,4 +43,5 @@ jobs:
is1ESPipeline: ${{ parameters.is1ESPipeline }}
jobNamePrefix: ${{ parameters.jobNamePrefix }}
platform: ${{ parameters.defaultManagedPlatform }}
+ componentGovernanceIgnoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
enableInternalSources: ${{ parameters.enableInternalSources }}
diff --git a/src/templating/eng/common/core-templates/steps/source-build.yml b/src/templating/eng/common/core-templates/steps/source-build.yml
index acf16ed3496..77321eee11f 100644
--- a/src/templating/eng/common/core-templates/steps/source-build.yml
+++ b/src/templating/eng/common/core-templates/steps/source-build.yml
@@ -11,6 +11,10 @@ parameters:
# for details. The entire object is described in the 'job' template for simplicity, even though
# the usage of the properties on this object is split between the 'job' and 'steps' templates.
platform: {}
+
+ # Optional list of directories to ignore for component governance scans.
+ componentGovernanceIgnoreDirectories: []
+
is1ESPipeline: false
steps:
diff --git a/src/templating/global.json b/src/templating/global.json
index 2601ff58bf9..7d699a3dfc6 100644
--- a/src/templating/global.json
+++ b/src/templating/global.json
@@ -13,6 +13,6 @@
"dotnet": "10.0.100-rc.1.25451.107"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25479.109"
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25509.106"
}
}
diff --git a/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IBindSymbolSource.cs b/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IBindSymbolSource.cs
index faacc3ef1da..beeefddb72f 100644
--- a/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IBindSymbolSource.cs
+++ b/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IBindSymbolSource.cs
@@ -12,17 +12,17 @@ public interface IBindSymbolSource : IPrioritizedComponent
///
/// The user friendly name of the component.
///
- public string DisplayName { get; }
+ string DisplayName { get; }
///
/// Prefix that is used in binding to reference the component.
///
- public string? SourcePrefix { get; }
+ string? SourcePrefix { get; }
///
/// If set to true, the component required exact prefix match to be used.
///
- public bool RequiresPrefixMatch { get; }
+ bool RequiresPrefixMatch { get; }
///
/// Gets the value corresponding to .
@@ -31,6 +31,6 @@ public interface IBindSymbolSource : IPrioritizedComponent
/// the value to retrieve (without prefix).
/// cancellation token.
///
- public Task GetBoundValueAsync(IEngineEnvironmentSettings settings, string bindName, CancellationToken cancellationToken);
+ Task GetBoundValueAsync(IEngineEnvironmentSettings settings, string bindName, CancellationToken cancellationToken);
}
}
diff --git a/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/ISdkInfoProvider.cs b/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/ISdkInfoProvider.cs
index 7074e49488b..ebe85225cee 100644
--- a/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/ISdkInfoProvider.cs
+++ b/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/ISdkInfoProvider.cs
@@ -13,14 +13,14 @@ public interface ISdkInfoProvider : IIdentifiedComponent
///
///
/// SDK version.
- public Task GetCurrentVersionAsync(CancellationToken cancellationToken);
+ Task GetCurrentVersionAsync(CancellationToken cancellationToken);
///
/// All installed SDK installations semver version strings.
///
///
/// SDK version strings.
- public Task> GetInstalledVersionsAsync(CancellationToken cancellationToken);
+ Task> GetInstalledVersionsAsync(CancellationToken cancellationToken);
///
/// Provides localized suggestion on action to be taken so that constraints requiring specified workloads can be met.
@@ -31,6 +31,6 @@ public interface ISdkInfoProvider : IIdentifiedComponent
/// SDK versions required by a constraint (in an 'OR' relationship).
/// SDK versions installed, that can meet the constraint - instructions should be provided to switch to any of those.
/// Localized string with remedy suggestion specific to current host.
- public string ProvideConstraintRemedySuggestion(IReadOnlyList supportedVersions, IReadOnlyList viableInstalledVersions);
+ string ProvideConstraintRemedySuggestion(IReadOnlyList supportedVersions, IReadOnlyList viableInstalledVersions);
}
}
diff --git a/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IWorkloadsInfoProvider.cs b/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IWorkloadsInfoProvider.cs
index 8aeb8ae4317..9e512c4e163 100644
--- a/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IWorkloadsInfoProvider.cs
+++ b/src/templating/src/Microsoft.TemplateEngine.Abstractions/Components/IWorkloadsInfoProvider.cs
@@ -13,7 +13,7 @@ public interface IWorkloadsInfoProvider : IIdentifiedComponent
///
///
/// Set of installed workloads.
- public Task> GetInstalledWorkloadsAsync(CancellationToken token);
+ Task> GetInstalledWorkloadsAsync(CancellationToken token);
///
/// Provides localized suggestion on action to be taken so that constraints requiring specified workloads can be met.
@@ -23,6 +23,6 @@ public interface IWorkloadsInfoProvider : IIdentifiedComponent
///
/// Workloads required by a constraint (in an 'OR' relationship).
/// Localized string with remedy suggestion specific to current host.
- public string ProvideConstraintRemedySuggestion(IReadOnlyList supportedWorkloads);
+ string ProvideConstraintRemedySuggestion(IReadOnlyList supportedWorkloads);
}
}
diff --git a/src/templating/src/Microsoft.TemplateEngine.Abstractions/IValidationEntry.cs b/src/templating/src/Microsoft.TemplateEngine.Abstractions/IValidationEntry.cs
index 30bacbccb2c..f82b0ecf6c9 100644
--- a/src/templating/src/Microsoft.TemplateEngine.Abstractions/IValidationEntry.cs
+++ b/src/templating/src/Microsoft.TemplateEngine.Abstractions/IValidationEntry.cs
@@ -11,7 +11,7 @@ public interface IValidationEntry
///
/// Error severity.
///
- public enum SeverityLevel
+ enum SeverityLevel
{
None,
Info,
@@ -42,7 +42,7 @@ public enum SeverityLevel
///
/// Details of the error location.
///
- public readonly struct ErrorLocation
+ readonly struct ErrorLocation
{
///
/// Gets the filename where the error occurred.
diff --git a/src/templating/src/Microsoft.TemplateSearch.Common/Abstractions/ITemplatePackageInfo.cs b/src/templating/src/Microsoft.TemplateSearch.Common/Abstractions/ITemplatePackageInfo.cs
index 2654dad250a..0b523ec8bce 100644
--- a/src/templating/src/Microsoft.TemplateSearch.Common/Abstractions/ITemplatePackageInfo.cs
+++ b/src/templating/src/Microsoft.TemplateSearch.Common/Abstractions/ITemplatePackageInfo.cs
@@ -11,23 +11,23 @@ public interface ITemplatePackageInfo
///
/// Gets template package name.
///
- public string Name { get; }
+ string Name { get; }
///
/// Gets template package version.
///
- public string? Version { get; }
+ string? Version { get; }
///
/// Gets total number of downloads for the package.
/// Optional, might be 0 in case search provider cannot provide number of downloads.
///
- public long TotalDownloads { get; }
+ long TotalDownloads { get; }
///
/// Gets the list of template package owners.
///
- public IReadOnlyList Owners { get; }
+ IReadOnlyList Owners { get; }
///
/// Gets the indication if the package is verified.
@@ -35,16 +35,16 @@ public interface ITemplatePackageInfo
///
/// For NuGet.org 'verified' means that package ID is under reserved namespaces, see .
///
- public bool Reserved { get; }
+ bool Reserved { get; }
///
/// Gets the NuGet package description.
///
- public string? Description { get; }
+ string? Description { get; }
///
/// Gets the URL to the package icon.
///
- public string? IconUrl { get; }
+ string? IconUrl { get; }
}
}
diff --git a/test/Microsoft.DotNet.Installer.Tests/LinuxInstallerTests.cs b/test/Microsoft.DotNet.Installer.Tests/LinuxInstallerTests.cs
index 14a0a7bf685..8c3114394e8 100755
--- a/test/Microsoft.DotNet.Installer.Tests/LinuxInstallerTests.cs
+++ b/test/Microsoft.DotNet.Installer.Tests/LinuxInstallerTests.cs
@@ -81,6 +81,10 @@ public partial class LinuxInstallerTests : IDisposable
[GeneratedRegex(@"\s*\([^)]*\)", RegexOptions.CultureInvariant)]
private static partial Regex RemoveVersionConstraintRegex { get; }
+ // Remove version numbers from package names: "dotnet-runtime-10.0.0-rc.1.25480.112-x64.rpm" -> "dotnet-runtime-*-x64.rpm"
+ [GeneratedRegex(@"\d+\.\d+\.\d+(?:-(?:rc|rtm|preview)(?:\.\d+)*)?", RegexOptions.CultureInvariant)]
+ private static partial Regex RemoveVersionFromPackageNameRegex { get; }
+
private const string RuntimeDepsRepo = "mcr.microsoft.com/dotnet/runtime-deps";
private const string RuntimeDepsVersion = "10.0-preview";
private const string DotnetRuntimeDepsPrefix = "dotnet-runtime-deps-";
@@ -170,6 +174,18 @@ public async Task DebPackageMetadataTest(string repo, string tag)
ValidatePackageMetadata($"{repo}:{tag}", PackageType.Deb);
}
+ [ConditionalFact(typeof(LinuxInstallerTests), nameof(IncludeRpmTests))]
+ public void ValidateRpmPackageList()
+ {
+ ValidatePackageList(PackageType.Rpm);
+ }
+
+ [ConditionalFact(typeof(LinuxInstallerTests), nameof(IncludeDebTests))]
+ public void ValidateDebPackageList()
+ {
+ ValidatePackageList(PackageType.Deb);
+ }
+
private async Task InitializeContextAsync(PackageType packageType, bool initializeSharedContext = true)
{
string packageArchitecture =
@@ -712,4 +728,80 @@ private static List ParseDebControlDependencies(string contents)
return results;
}
+
+ private void ValidatePackageList(PackageType packageType)
+ {
+ string extension = packageType == PackageType.Rpm ? "*.rpm" : "*.deb";
+ List expectedPatterns = GetExpectedPackagePatterns(packageType).OrderBy(p => p).ToList();
+
+ // Find all packages of the specified type and normalize by removing version numbers
+ List normalizedActual = Directory.GetFiles(Config.AssetsDirectory, extension, SearchOption.AllDirectories)
+ .Select(path => RemoveVersionFromPackageNameRegex.Replace(Path.GetFileName(path), "*"))
+ .Distinct()
+ .OrderBy(name => name)
+ .ToList();
+
+ Assert.True(
+ expectedPatterns.SequenceEqual(normalizedActual),
+ $"Package list validation failed for {packageType}:\nExpected:\n{string.Join("\n", expectedPatterns)}\nActual:\n{string.Join("\n", normalizedActual)}"
+ );
+ }
+
+ private List GetExpectedPackagePatterns(PackageType packageType)
+ {
+ string extension = packageType == PackageType.Rpm ? ".rpm" : ".deb";
+ string arch = Config.Architecture == Architecture.X64 ? "x64" :
+ (packageType == PackageType.Rpm ? "aarch64" : "arm64");
+
+ var patterns = new List();
+
+ // Base package prefixes (common to both RPM and DEB)
+ var basePackages = new List
+ {
+ "aspnetcore-runtime", "aspnetcore-targeting-pack", "dotnet-apphost-pack",
+ "dotnet-host", "dotnet-hostfxr", "dotnet-runtime", "dotnet-sdk", "dotnet-targeting-pack"
+ };
+
+ // Add runtime-deps for DEB only (RPM only has distro-specific variants)
+ if (packageType == PackageType.Deb)
+ {
+ basePackages.Add("dotnet-runtime-deps");
+ }
+
+ // Standard variants
+ foreach (string package in basePackages)
+ {
+ patterns.Add($"{package}-*-{arch}{extension}");
+ }
+
+ // New key variants
+ foreach (string package in basePackages)
+ {
+ patterns.Add($"{package}-*-newkey-{arch}{extension}");
+ }
+
+ if (packageType == PackageType.Rpm)
+ {
+ // Azure Linux variants
+ foreach (string package in basePackages)
+ {
+ patterns.Add($"{package}-*-azl-{arch}{extension}");
+ }
+
+ // Runtime deps distro variants (RPM only)
+ string[] distros = new[] { "azl.3", "opensuse.15", "sles.15" };
+ foreach (string distro in distros)
+ {
+ patterns.Add($"dotnet-runtime-deps-*-{distro}-{arch}{extension}");
+
+ // `azl` deps packages do not have a -newkey- variant
+ if (distro != "azl.3")
+ {
+ patterns.Add($"dotnet-runtime-deps-*-{distro}-newkey-{arch}{extension}");
+ }
+ }
+ }
+
+ return patterns;
+ }
}