Merge branch 'release/7.0.4xx'

This commit is contained in:
Jason Zhai 2023-06-02 02:15:06 -07:00
Родитель 46b88e5708 da950cad81
Коммит df5018d939
74 изменённых файлов: 1030 добавлений и 297 удалений

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

@ -20,7 +20,6 @@
"src\\Cli\\Microsoft.TemplateEngine.Cli\\Microsoft.TemplateEngine.Cli.csproj",
"src\\Cli\\dotnet\\dotnet.csproj",
"src\\Containers\\Microsoft.NET.Build.Containers\\Microsoft.NET.Build.Containers.csproj",
"src\\Containers\\containerize\\containerize.csproj",
"src\\Containers\\packaging\\package.csproj",
"src\\Layout\\redist\\redist.csproj",
"src\\Layout\\tool_fsharp\\tool_fsc.csproj",

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

@ -463,30 +463,9 @@ namespace Microsoft.DotNet.Workloads.Workload.Install
throw new ArgumentException(string.Format(LocalizableStrings.RollbackDefinitionFileDoesNotExist, rollbackDefinitionFilePath));
}
}
return JsonSerializer.Deserialize<IDictionary<string, string>>(fileContent)
.Select(manifest =>
{
ManifestVersion manifestVersion;
SdkFeatureBand manifestFeatureBand;
var parts = manifest.Value.Split('/');
string manifestVersionString = (parts[0]);
if (!FXVersion.TryParse(manifestVersionString, out FXVersion version))
{
throw new FormatException(String.Format(LocalizableStrings.InvalidVersionForWorkload, manifest.Key, manifestVersionString));
}
manifestVersion = new ManifestVersion(parts[0]);
if (parts.Length == 1)
{
manifestFeatureBand = _sdkFeatureBand;
}
else
{
manifestFeatureBand = new SdkFeatureBand(parts[1]);
}
return (new ManifestId(manifest.Key), manifestVersion, manifestFeatureBand);
});
return WorkloadSet.FromJson(fileContent, _sdkFeatureBand).ManifestVersions
.Select(kvp => (kvp.Key, kvp.Value.Version, kvp.Value.FeatureBand));
}
private bool BackgroundUpdatesAreDisabled() =>

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

@ -90,10 +90,10 @@ namespace Microsoft.DotNet.Workloads.Workload.Update
}
else if (_printRollbackDefinitionOnly)
{
var manifests = _workloadResolver.GetInstalledManifests().ToDictionary(m => m.Id, m => m.Version + "/" + m.ManifestFeatureBand, StringComparer.OrdinalIgnoreCase);
var workloadSet = WorkloadSet.FromManifests(_workloadResolver.GetInstalledManifests());
Reporter.WriteLine("==workloadRollbackDefinitionJsonOutputStart==");
Reporter.WriteLine(JsonSerializer.Serialize(manifests, new JsonSerializerOptions() { WriteIndented = true }));
Reporter.WriteLine(workloadSet.ToJson());
Reporter.WriteLine("==workloadRollbackDefinitionJsonOutputEnd==");
}
else

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

@ -274,21 +274,21 @@ public static class ContainerHelpers
/// <summary>
/// Checks if a given container image name adheres to the image name spec. If not, and recoverable, then normalizes invalid characters.
/// </summary>
internal static bool NormalizeImageName(string containerImageName,
internal static bool NormalizeRepository(string containerRepository,
[NotNullWhen(false)] out string? normalizedImageName)
{
if (IsValidImageName(containerImageName))
if (IsValidImageName(containerRepository))
{
normalizedImageName = null;
return true;
}
else
{
if (!Char.IsLetterOrDigit(containerImageName, 0))
if (!Char.IsLetterOrDigit(containerRepository, 0))
{
throw new ArgumentException(Resources.Resource.GetString(nameof(Strings.InvalidImageName)));
}
var loweredImageName = containerImageName.ToLowerInvariant();
var loweredImageName = containerRepository.ToLowerInvariant();
normalizedImageName = imageNameCharacters.Replace(loweredImageName, "-");
return false;
}

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

@ -9,7 +9,9 @@ internal static class KnownStrings
{
public static readonly string ContainerBaseImage = nameof(ContainerBaseImage);
public static readonly string ContainerRegistry = nameof(ContainerRegistry);
/// <summary>Note that this is deprecated in favor of <see cref="ContainerRepository"/></summary>
public static readonly string ContainerImageName = nameof(ContainerImageName);
public static readonly string ContainerRepository = nameof(ContainerRepository);
public static readonly string ContainerImageTag = nameof(ContainerImageTag);
public static readonly string ContainerImageTags = nameof(ContainerImageTags);
public static readonly string ContainerWorkingDirectory = nameof(ContainerWorkingDirectory);
@ -33,6 +35,8 @@ internal static class KnownStrings
public static class ErrorCodes
{
public static readonly string CONTAINER002 = nameof(CONTAINER002);
public static readonly string CONTAINER003 = nameof(CONTAINER003);
public static readonly string CONTAINER1011 = nameof(CONTAINER1011);
public static readonly string CONTAINER1012 = nameof(CONTAINER1012);
public static readonly string CONTAINER1013 = nameof(CONTAINER1013);

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

@ -137,7 +137,8 @@ internal record struct Layer
fs.Position = 0;
SHA256.HashData(fs, hash);
int bW = SHA256.HashData(fs, hash);
Debug.Assert(bW == hash.Length);
// Writes a tar entry corresponding to the file system item.
static void WriteTarEntryForFile(TarWriter writer, FileSystemInfo file, string containerPath, IEnumerable<KeyValuePair<string, string>> entryAttributes)

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

@ -95,4 +95,9 @@
</ItemGroup>
</Target>
<!-- Copy to *.csproj for using in sanity checks integration tests. -->
<Target Name="CopyCsprojToTestExecutionDirectory" AfterTargets="Build">
<Copy SourceFiles="$(MSBuildThisFileFullPath)" DestinationFiles="$(ArtifactsTmpDir)Container\ProjectFiles\$(MSBuildThisFileName).csproj" />
</Target>
</Project>

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

@ -47,8 +47,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerConfigurat
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerConfiguration.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerManifest.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerManifest.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageName.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageTags.get -> string![]!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageTags.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Labels.get -> Microsoft.Build.Framework.ITaskItem![]!
@ -71,8 +71,8 @@ override Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GetProcessStartInfo
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageName.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerRepository.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerRepository.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageTag.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageTag.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageTags.get -> string![]!
@ -82,7 +82,7 @@ Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerRegistry.
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.FullyQualifiedBaseImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.FullyQualifiedBaseImageName.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerEnvironmentVariables.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerRepository.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerRegistry.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerTags.get -> string![]!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ParseContainerProperties() -> void

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

@ -137,8 +137,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerConfigurat
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerConfiguration.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerManifest.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.GeneratedContainerManifest.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageName.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.get -> string!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Repository.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageTags.get -> string![]!
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.ImageTags.set -> void
Microsoft.NET.Build.Containers.Tasks.CreateNewImage.Labels.get -> Microsoft.Build.Framework.ITaskItem![]!
@ -160,8 +160,8 @@ Microsoft.NET.Build.Containers.Tasks.CreateNewImage.WorkingDirectory.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerEnvironmentVariables.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageName.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerRepository.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerRepository.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageTag.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageTag.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerImageTags.get -> string![]!
@ -171,7 +171,7 @@ Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ContainerRegistry.
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.FullyQualifiedBaseImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.FullyQualifiedBaseImageName.set -> void
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerEnvironmentVariables.get -> Microsoft.Build.Framework.ITaskItem![]!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerImageName.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerRepository.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerRegistry.get -> string!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.NewContainerTags.get -> string![]!
Microsoft.NET.Build.Containers.Tasks.ParseContainerProperties.ParseContainerProperties() -> void

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

@ -421,7 +421,8 @@ internal sealed class Registry
HttpResponseMessage patchResponse = await client.PatchAsync(uploadUri.Uri, content, cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
if (patchResponse.StatusCode != HttpStatusCode.Accepted)
// Fail the upload if the response code is not Accepted (202) or if uploading to Amazon ECR which returns back Created (201).
if (!(patchResponse.StatusCode == HttpStatusCode.Accepted || (IsAmazonECRRegistry && patchResponse.StatusCode == HttpStatusCode.Created)))
{
var headers = patchResponse.Headers.ToString();
var detail = await patchResponse.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);

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

@ -10,8 +10,8 @@
namespace Microsoft.NET.Build.Containers.Resources {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
@ -23,15 +23,15 @@ namespace Microsoft.NET.Build.Containers.Resources {
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Strings {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Strings() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
@ -45,7 +45,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
@ -59,7 +59,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER0000: Value for unit test {0}.
/// </summary>
@ -68,7 +68,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("_Test", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1002: Request to Amazon Elastic Container Registry failed prematurely. This is often caused when the target repository does not exist in the registry..
/// </summary>
@ -77,7 +77,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("AmazonRegistryFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2008: Both {0} and {1} were provided, but only one or the other is allowed..
/// </summary>
@ -86,7 +86,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("AmbiguousTags", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2009: Could not parse {0}: {1}.
/// </summary>
@ -95,7 +95,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("BaseImageNameParsingFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2013: {0} had spaces in it, replacing with dashes..
/// </summary>
@ -104,7 +104,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("BaseImageNameWithSpaces", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2020: {0} does not specify a registry and will be pulled from Docker Hub. Please prefix the name with the image registry, for example: '{1}/<image>'..
/// </summary>
@ -122,7 +122,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("BaseImageNotFound", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1001: Failed to upload blob to {0}; received {1} with detail {2}..
/// </summary>
@ -131,7 +131,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("BlobUploadFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1007: Could not deserialize token from JSON..
/// </summary>
@ -140,7 +140,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("CouldntDeserializeJsonToken", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2012: Could not recognize registry &apos;{0}&apos;..
/// </summary>
@ -149,7 +149,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("CouldntRecognizeRegistry", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER3002: Failed to get docker info({0})\n{1}\n{2}.
/// </summary>
@ -158,7 +158,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("DockerInfoFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER3002: Failed to get docker info: {0}.
/// </summary>
@ -167,7 +167,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("DockerInfoFailed_Ex", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER3001: Failed creating docker process..
/// </summary>
@ -176,7 +176,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("DockerProcessCreationFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER4006: Property &apos;{0}&apos; is empty or contains whitespace and will be ignored..
/// </summary>
@ -185,7 +185,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("EmptyOrWhitespacePropertyIgnored", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER4004: Items &apos;{0}&apos; contain empty item(s) which will be ignored..
/// </summary>
@ -194,7 +194,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("EmptyValuesIgnored", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1008: Failed retrieving credentials for &quot;{0}&quot;: {1}.
/// </summary>
@ -203,7 +203,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("FailedRetrievingCredentials", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to No host object detected..
/// </summary>
@ -212,7 +212,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("HostObjectNotDetected", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1009: Failed to load image to local registry. stdout: {0}.
/// </summary>
@ -221,7 +221,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("ImageLoadFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1010: Pulling images from local registry is not supported..
/// </summary>
@ -230,16 +230,16 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("ImagePullNotSupported", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2014: Invalid {0}: {1}..
/// </summary>
internal static string InvalidContainerImageName {
internal static string InvalidContainerRepository {
get {
return ResourceManager.GetString("InvalidContainerImageName", resourceCulture);
return ResourceManager.GetString("InvalidContainerRepository", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2015: {0}: &apos;{1}&apos; was not a valid Environment Variable. Ignoring..
/// </summary>
@ -248,7 +248,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidEnvVar", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2005: The first character of the image name must be a lowercase letter or a digit..
/// </summary>
@ -257,7 +257,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidImageName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2017: A ContainerPort item was provided with an invalid port number &apos;{0}&apos;. ContainerPort items must have an Include value that is an integer, and a Type value that is either &apos;tcp&apos; or &apos;udp&apos;..
/// </summary>
@ -266,7 +266,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidPort_Number", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2017: A ContainerPort item was provided with an invalid port number &apos;{0}&apos; and an invalid port type &apos;{1}&apos;. ContainerPort items must have an Include value that is an integer, and a Type value that is either &apos;tcp&apos; or &apos;udp&apos;..
/// </summary>
@ -275,7 +275,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidPort_NumberAndType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2017: A ContainerPort item was provided with an invalid port type &apos;{0}&apos;. ContainerPort items must have an Include value that is an integer, and a Type value that is either &apos;tcp&apos; or &apos;udp&apos;..
/// </summary>
@ -284,7 +284,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidPort_Type", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2018: Invalid SDK prerelease version &apos;{0}&apos; - only &apos;rc&apos; and &apos;preview&apos; are supported..
/// </summary>
@ -293,7 +293,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidSdkPrereleaseVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2019: Invalid SDK semantic version &apos;{0}&apos;..
/// </summary>
@ -302,7 +302,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidSdkVersion", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2007: Invalid {0} provided: {1}. Image tags must be alphanumeric, underscore, hyphen, or period..
/// </summary>
@ -311,7 +311,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidTag", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2010: Invalid {0} provided: {1}. {0} must be a semicolon-delimited list of valid image tags. Image tags must be alphanumeric, underscore, hyphen, or period..
/// </summary>
@ -320,7 +320,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidTags", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1003: Token response had neither token nor access_token..
/// </summary>
@ -329,7 +329,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("InvalidTokenResponse", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER4005: Item &apos;{0}&apos; contains items without metadata &apos;Value&apos;, and they will be ignored..
/// </summary>
@ -338,7 +338,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("ItemsWithoutMetadata", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1012: The local registry is not available, but pushing to a local registry was requested.
/// </summary>
@ -347,7 +347,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("LocalRegistryNotAvailable", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2004: Unable to download layer with descriptor &apos;{0}&apos; from registry &apos;{1}&apos; because it does not exist..
/// </summary>
@ -356,7 +356,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("MissingLinkToRegistry", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2016: ContainerPort item &apos;{0}&apos; does not specify the port number. Please ensure the item&apos;s Include is a port number, for example &apos;&lt;ContainerPort Include=&quot;80&quot; /&gt;&apos;.
/// </summary>
@ -365,7 +365,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("MissingPortNumber", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1004: No RequestUri specified..
/// </summary>
@ -374,7 +374,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("NoRequestUriSpecified", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &apos;{0}&apos; was not a valid container image name, it was normalized to &apos;{1}&apos;.
/// </summary>
@ -383,7 +383,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("NormalizedContainerName", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2011: {0} &apos;{1}&apos; does not exist.
/// </summary>
@ -392,7 +392,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("PublishDirectoryDoesntExist", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1013: Failed to push to the output registry: {0}.
/// </summary>
@ -401,7 +401,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("RegistryOutputPushFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1005: Registry push failed..
/// </summary>
@ -410,7 +410,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("RegistryPushFailed", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER4003: Required &apos;{0}&apos; items contain empty items..
/// </summary>
@ -419,7 +419,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("RequiredItemsContainsEmptyItems", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER4002: Required &apos;{0}&apos; items were not set..
/// </summary>
@ -428,7 +428,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("RequiredItemsNotSet", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER4001: Required property &apos;{0}&apos; was not set or empty..
/// </summary>
@ -437,7 +437,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("RequiredPropertyNotSetOrEmpty", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER1006: Too many retries, stopping..
/// </summary>
@ -446,7 +446,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("TooManyRetries", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2002: Unknown local registry type &apos;{0}&apos;. Valid local container registry types are {1}..
/// </summary>
@ -455,7 +455,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("UnknownLocalRegistryType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2003: The manifest for {0}:{1} from registry {2} was an unknown type: {3}. Please raise an issue at https://github.com/dotnet/sdk-container-builds/issues with this message..
/// </summary>
@ -464,7 +464,7 @@ namespace Microsoft.NET.Build.Containers.Resources {
return ResourceManager.GetString("UnknownMediaType", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to CONTAINER2001: Unrecognized mediaType &apos;{0}&apos;..
/// </summary>

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

@ -1,17 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
@ -26,36 +26,36 @@
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
@ -188,7 +188,7 @@
<value>CONTAINER1009: Failed to load image from local registry. stdout: {0}</value>
<comment>{StrBegin="CONTAINER1009: "}</comment>
</data>
<data name="InvalidContainerImageName" xml:space="preserve">
<data name="InvalidContainerRepository" xml:space="preserve">
<value>CONTAINER2014: Invalid {0}: {1}.</value>
<comment>{StrBegin="CONTAINER2014: "}</comment>
</data>
@ -299,4 +299,4 @@
<value>CONTAINER0000: Value for unit test {0}</value>
<comment>Used only for unit tests</comment>
</data>
</root>
</root>

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

@ -92,7 +92,7 @@
<target state="new">CONTAINER1010: Pulling images from local registry is not supported.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: Neplatná {0}: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="new">CONTAINER1010: Pulling images from local registry is not supported.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: Ungültiger {0}: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="needs-review-translation">CONTAINER1010: No se admite la extracción de imágenes del demonio de Docker local.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: {0} no válido: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="new">CONTAINER1010: Pulling images from local registry is not supported.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: {0} non valide : {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="new">CONTAINER1010: Pulling images from local registry is not supported.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: {0}non valido: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="needs-review-translation">CONTAINER1010: ローカル Docker デーモンからのイメージのプルはサポートされていません。</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: 無効な {0}: {1}。</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="needs-review-translation">CONTAINER1010: 로컬 Docker 디먼에서 이미지 끌어오기가 지원되지 않습니다.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: 잘못된 {0}: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="needs-review-translation">CONTAINER1010: ściąganie obrazów z lokalnego demona platformy Docker nie jest obsługiwane.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: Nieprawidłowy element {0}: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="needs-review-translation">CONTAINER1010: não há suporte para a extração de imagens do daemon do Docker local.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: Inválido {0}: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="needs-review-translation">CONTAINER1010: извлечение образов из локальной управляющей программы Docker не поддерживается.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: недопустимый {0}: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="new">CONTAINER1010: Pulling images from local registry is not supported.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: Geçersiz {0}: {1}.</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="new">CONTAINER1010: Pulling images from local registry is not supported.</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: 无效 {0}: {1}。</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -92,7 +92,7 @@
<target state="needs-review-translation">CONTAINER1010: 不支援從本機 Docker 精靈提取映像。</target>
<note>{StrBegin="CONTAINER1010: "}</note>
</trans-unit>
<trans-unit id="InvalidContainerImageName">
<trans-unit id="InvalidContainerRepository">
<source>CONTAINER2014: Invalid {0}: {1}.</source>
<target state="translated">CONTAINER2014: 無效的 {0}: {1}。</target>
<note>{StrBegin="CONTAINER2014: "}</note>

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

@ -55,7 +55,7 @@ partial class CreateNewImage
/// The name of the output image that will be pushed to the registry.
/// </summary>
[Required]
public string ImageName { get; set; }
public string Repository { get; set; }
/// <summary>
/// The tag to associate with the new image.
@ -140,7 +140,7 @@ partial class CreateNewImage
BaseImageName = "";
BaseImageTag = "";
OutputRegistry = "";
ImageName = "";
Repository = "";
ImageTags = Array.Empty<string>();
PublishDirectory = "";
WorkingDirectory = "";

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

@ -41,7 +41,7 @@ public sealed partial class CreateNewImage : Microsoft.Build.Utilities.Task, ICa
return !Log.HasLoggedErrors;
}
ImageReference sourceImageReference = new(SourceRegistry.Value, BaseImageName, BaseImageTag);
var destinationImageReferences = ImageTags.Select(t => new ImageReference(DestinationRegistry.Value, ImageName, t));
var destinationImageReferences = ImageTags.Select(t => new ImageReference(DestinationRegistry.Value, Repository, t));
ImageBuilder? imageBuilder;
if (SourceRegistry.Value is { } registry)
@ -64,7 +64,7 @@ public sealed partial class CreateNewImage : Microsoft.Build.Utilities.Task, ICa
return !Log.HasLoggedErrors;
}
SafeLog("Building image '{0}' with tags {1} on top of base image {2}", ImageName, String.Join(",", ImageTags), sourceImageReference);
SafeLog("Building image '{0}' with tags {1} on top of base image {2}", Repository, String.Join(",", ImageTags), sourceImageReference);
Layer newLayer = Layer.FromDirectory(PublishDirectory, WorkingDirectory, imageBuilder.IsWindows);
imageBuilder.AddLayer(newLayer);
@ -167,7 +167,7 @@ public sealed partial class CreateNewImage : Microsoft.Build.Utilities.Task, ICa
else
{
ContainerHelpers.ParsePortError parsedErrors = (ContainerHelpers.ParsePortError)errors!;
if (parsedErrors.HasFlag(ContainerHelpers.ParsePortError.MissingPortNumber))
{
Log.LogErrorWithCodeFromResources(nameof(Strings.MissingPortNumber), port.ItemSpec);

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

@ -86,9 +86,9 @@ public partial class CreateNewImage : ToolTask, ICancelableTask
{
throw new InvalidOperationException(Resource.FormatString(nameof(Strings.RequiredPropertyNotSetOrEmpty), nameof(BaseImageName)));
}
if (string.IsNullOrWhiteSpace(ImageName))
if (string.IsNullOrWhiteSpace(Repository))
{
throw new InvalidOperationException(Resource.FormatString(nameof(Strings.RequiredPropertyNotSetOrEmpty), nameof(ImageName)));
throw new InvalidOperationException(Resource.FormatString(nameof(Strings.RequiredPropertyNotSetOrEmpty), nameof(Repository)));
}
if (string.IsNullOrWhiteSpace(WorkingDirectory))
{
@ -110,7 +110,7 @@ public partial class CreateNewImage : ToolTask, ICancelableTask
builder.AppendFileNameIfNotNull(PublishDirectory.TrimEnd(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }));
builder.AppendSwitchIfNotNull("--baseregistry ", BaseRegistry);
builder.AppendSwitchIfNotNull("--baseimagename ", BaseImageName);
builder.AppendSwitchIfNotNull("--imagename ", ImageName);
builder.AppendSwitchIfNotNull("--repository ", Repository);
builder.AppendSwitchIfNotNull("--workingdirectory ", WorkingDirectory);
ITaskItem[] sanitizedEntryPoints = Entrypoint.Where(e => !string.IsNullOrWhiteSpace(e.ItemSpec)).ToArray();
builder.AppendSwitchIfNotNull("--entrypoint ", sanitizedEntryPoints, delimiter: " ");

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

@ -23,10 +23,10 @@ public sealed class ParseContainerProperties : Microsoft.Build.Utilities.Task
public string ContainerRegistry { get; set; }
/// <summary>
/// The image name for the container to be created.
/// The name of the container to be created.
/// </summary>
[Required]
public string ContainerImageName { get; set; }
public string ContainerRepository { get; set; }
/// <summary>
/// The tag for the container to be created.
@ -55,7 +55,7 @@ public sealed class ParseContainerProperties : Microsoft.Build.Utilities.Task
public string NewContainerRegistry { get; private set; }
[Output]
public string NewContainerImageName { get; private set; }
public string NewContainerRepository { get; private set; }
[Output]
public string[] NewContainerTags { get; private set; }
@ -67,7 +67,7 @@ public sealed class ParseContainerProperties : Microsoft.Build.Utilities.Task
{
FullyQualifiedBaseImageName = "";
ContainerRegistry = "";
ContainerImageName = "";
ContainerRepository = "";
ContainerImageTag = "";
ContainerImageTags = Array.Empty<string>();
ContainerEnvironmentVariables = Array.Empty<ITaskItem>();
@ -75,7 +75,7 @@ public sealed class ParseContainerProperties : Microsoft.Build.Utilities.Task
ParsedContainerImage = "";
ParsedContainerTag = "";
NewContainerRegistry = "";
NewContainerImageName = "";
NewContainerRepository = "";
NewContainerTags = Array.Empty<string>();
NewContainerEnvironmentVariables = Array.Empty<ITaskItem>();
@ -149,20 +149,20 @@ public sealed class ParseContainerProperties : Microsoft.Build.Utilities.Task
try
{
if (!ContainerHelpers.NormalizeImageName(ContainerImageName, out var normalizedImageName))
if (!ContainerHelpers.NormalizeRepository(ContainerRepository, out var normalizedRepository))
{
Log.LogMessageFromResources(nameof(Strings.NormalizedContainerName), nameof(ContainerImageName), normalizedImageName);
NewContainerImageName = normalizedImageName!; // known to be not null due to output of NormalizeImageName
Log.LogMessageFromResources(nameof(Strings.NormalizedContainerName), nameof(ContainerRepository), normalizedRepository);
NewContainerRepository = normalizedRepository!; // known to be not null due to output of NormalizeImageName
}
else
{
// name was valid already
NewContainerImageName = ContainerImageName;
NewContainerRepository = ContainerRepository;
}
}
catch (ArgumentException)
{
Log.LogErrorWithCodeFromResources(nameof(Strings.InvalidContainerImageName), nameof(ContainerImageName), ContainerImageName);
Log.LogErrorWithCodeFromResources(nameof(Strings.InvalidContainerRepository), nameof(ContainerRepository), ContainerRepository);
return !Log.HasLoggedErrors;
}
@ -178,7 +178,7 @@ public sealed class ParseContainerProperties : Microsoft.Build.Utilities.Task
Log.LogMessage(MessageImportance.Low, "Host: {0}", ParsedContainerRegistry);
Log.LogMessage(MessageImportance.Low, "Image: {0}", ParsedContainerImage);
Log.LogMessage(MessageImportance.Low, "Tag: {0}", ParsedContainerTag);
Log.LogMessage(MessageImportance.Low, "Image Name: {0}", NewContainerImageName);
Log.LogMessage(MessageImportance.Low, "Image Name: {0}", NewContainerRepository);
Log.LogMessage(MessageImportance.Low, "Image Tags: {0}", String.Join(", ", NewContainerTags));
}

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

@ -43,9 +43,9 @@ internal class ContainerizeCommand : RootCommand
IsRequired = false
};
internal Option<string> ImageNameOption { get; } = new Option<string>(
name: "--imagename",
description: "The name of the output image that will be pushed to the registry.")
internal Option<string> RepositoryOption { get; } = new Option<string>(
name: "--repository",
description: "The name of the output container repository that will be pushed to the registry.")
{
IsRequired = true
};
@ -168,13 +168,13 @@ internal class ContainerizeCommand : RootCommand
internal ContainerizeCommand() : base("Containerize an application without Docker.")
{
{
this.AddArgument(PublishDirectoryArgument);
this.AddOption(BaseRegistryOption);
this.AddOption(BaseImageNameOption);
this.AddOption(BaseImageTagOption);
this.AddOption(OutputRegistryOption);
this.AddOption(ImageNameOption);
this.AddOption(RepositoryOption);
this.AddOption(ImageTagsOption);
this.AddOption(WorkingDirectoryOption);
this.AddOption(EntrypointOption);
@ -194,7 +194,7 @@ internal class ContainerizeCommand : RootCommand
string _baseName = context.ParseResult.GetValue(BaseImageNameOption)!;
string _baseTag = context.ParseResult.GetValue(BaseImageTagOption)!;
string? _outputReg = context.ParseResult.GetValue(OutputRegistryOption);
string _name = context.ParseResult.GetValue(ImageNameOption)!;
string _name = context.ParseResult.GetValue(RepositoryOption)!;
string[] _tags = context.ParseResult.GetValue(ImageTagsOption)!;
string _workingDir = context.ParseResult.GetValue(WorkingDirectoryOption)!;
string[] _entrypoint = context.ParseResult.GetValue(EntrypointOption)!;

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

@ -7,6 +7,7 @@
<Nullable>enable</Nullable>
<StrongNameKeyId>MicrosoftShared</StrongNameKeyId>
<SignAssembly>true</SignAssembly>
<ExcludeFromSourceBuild>true</ExcludeFromSourceBuild>
</PropertyGroup>
<ItemGroup>
@ -24,4 +25,9 @@
</ItemGroup>
<Copy SourceFiles="@(ContainerizeFiles)" DestinationFiles="@(ContainerizeFiles->'$(ArtifactsTmpDir)Container\containerize\%(RecursiveDir)%(Filename)%(Extension)')" />
</Target>
<!-- Copy to *.csproj for using in sanity checks integration tests. -->
<Target Name="CopyCsprojToTestExecutionDirectory" AfterTargets="Build">
<Copy SourceFiles="$(MSBuildThisFileFullPath)" DestinationFiles="$(ArtifactsTmpDir)Container\ProjectFiles\$(MSBuildThisFileName).csproj" />
</Target>
</Project>

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

@ -69,6 +69,9 @@
<ContainerImageTag Condition="'$(AutoGenerateImageTag)' == 'true'">$([System.DateTime]::UtcNow.ToString('yyyyMMddhhmmss'))</ContainerImageTag>
</PropertyGroup>
<!-- Compatibility: previous versions used ImageName, but the proper term is Repository. Keep using that if explicitly set. -->
<Warning Condition="'$(ContainerImageName)' != ''" Code="CONTAINER003" Text="The property 'ContainerImageName' was set but is obsolete - please use 'ContainerRepository' instead." />
<!-- Container Defaults -->
<PropertyGroup>
<!-- An empty ContainerRegistry implies pushing to the local registry, putting this here for documentation purposes -->
@ -77,8 +80,10 @@
<!-- Set which local container registry to use. We only explicitly support Docker (or things that mimic Docker APIs and binary names) at the moment. -->
<LocalRegistry Condition="'$(LocalRegistry)' == ''">Docker</LocalRegistry>
<!-- Note: spaces will be replaced with '-' in ContainerImageName and ContainerImageTag -->
<ContainerImageName Condition="'$(ContainerImageName)' == ''">$(AssemblyName)</ContainerImageName>
<!-- Compatibility: previous versions used ImageName, but the proper term is Repository. Keep using that if explicitly set. -->
<ContainerRepository Condition="'$(ContainerImageName)' != ''">$(ContainerImageName)</ContainerRepository>
<!-- Note: spaces will be replaced with '-' in ContainerRepository and ContainerImageTag -->
<ContainerRepository Condition="'$(ContainerRepository)' == ''">$(AssemblyName)</ContainerRepository>
<!-- Only default a tag name if no tag names at all are provided -->
<ContainerImageTag Condition="'$(ContainerImageTag)' == '' and '$(ContainerImageTags)' == ''">$(Version)</ContainerImageTag>
@ -113,7 +118,7 @@
<ParseContainerProperties FullyQualifiedBaseImageName="$(ContainerBaseImage)"
ContainerRegistry="$(ContainerRegistry)"
ContainerImageName="$(ContainerImageName)"
ContainerRepository="$(ContainerRepository)"
ContainerImageTag="$(ContainerImageTag)"
ContainerImageTags="$(ContainerImageTags)"
ContainerEnvironmentVariables="@(ContainerEnvironmentVariable)">
@ -122,7 +127,7 @@
<Output TaskParameter="ParsedContainerImage" PropertyName="ContainerBaseName" />
<Output TaskParameter="ParsedContainerTag" PropertyName="ContainerBaseTag" />
<Output TaskParameter="NewContainerRegistry" PropertyName="ContainerRegistry" />
<Output TaskParameter="NewContainerImageName" PropertyName="ContainerImageName" />
<Output TaskParameter="NewContainerRepository" PropertyName="ContainerRepository" />
<Output TaskParameter="NewContainerTags" ItemName="ContainerImageTags" />
<Output TaskParameter="NewContainerEnvironmentVariables" ItemName="ContainerEnvironmentVariables" />
</ParseContainerProperties>
@ -201,7 +206,7 @@
BaseImageTag="$(ContainerBaseTag)"
LocalRegistry="$(LocalRegistry)"
OutputRegistry="$(ContainerRegistry)"
ImageName="$(ContainerImageName)"
Repository="$(ContainerRepository)"
ImageTags="@(ContainerImageTags)"
PublishDirectory="$(PublishDir)"
WorkingDirectory="$(ContainerWorkingDirectory)"

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

@ -28,12 +28,15 @@
SetTargetFramework="TargetFramework=$(TargetFramework)"
OutputItemType="ContainerLibraryOutput"/>
<ProjectReference Include="../../Cli/Microsoft.DotNet.Cli.Utils/Microsoft.DotNet.Cli.Utils.csproj"
SetTargetFramework="TargetFramework=$(TargetFramework)"
OutputItemType="DotNetCliUtilsLibraryOutput"/>
<ProjectReference Include="../Microsoft.NET.Build.Containers/Microsoft.NET.Build.Containers.csproj"
SetTargetFramework="TargetFramework=$(VSCompatTargetFramework)"
OutputItemType="ContainerLibraryOutputNet472" Condition="'$(DotNetBuildFromSource)' != 'true'" />
<ProjectReference Include="../containerize/containerize.csproj" PrivateAssets="all" IncludeAssets="runtime" ReferenceOutputAssembly="true" />
<PackageReference Include="System.CommandLine" PrivateAssets="all" IncludeAssets="runtime" Version="$(SystemCommandLineVersion)"/>
<ProjectReference Include="../containerize/containerize.csproj" PrivateAssets="all" IncludeAssets="runtime" ReferenceOutputAssembly="true" Condition="'$(DotNetBuildFromSource)' != 'true'" />
</ItemGroup>
<Target Name="PreparePackageReleaseNotesFromFile" BeforeTargets="GenerateNuspec">
@ -48,18 +51,12 @@
<Output TaskParameter="TargetOutputs" ItemName="_AllNet472ContainerTaskDependencies" />
</MSBuild>
<ItemGroup Condition="'$(DotNetBuildFromSource)' != 'true'">
<NecessaryNet472ContainerTaskDependencies
Include="@(_AllNet472ContainerTaskDependencies)"
Condition="(
$([MSBuild]::ValueOrDefault('%(_AllNet472ContainerTaskDependencies.NuGetPackageId)', '').Contains('NuGet')) or
$([MSBuild]::ValueOrDefault('%(_AllNet472ContainerTaskDependencies.NuGetPackageId)', '').Contains('Newtonsoft'))
) and
%(_AllNet472ContainerTaskDependencies.NuGetIsFrameworkReference) != true" />
</ItemGroup>
<ItemGroup>
<!-- root folder -->
<Content Include="README.md" Pack="true" PackagePath="" />
<NecessaryNet472ContainerTaskDependencies Include="@(_AllNet472ContainerTaskDependencies)" Condition="(
$([MSBuild]::ValueOrDefault('%(_AllNet472ContainerTaskDependencies.NuGetPackageId)', '').Contains('NuGet')) or
$([MSBuild]::ValueOrDefault('%(_AllNet472ContainerTaskDependencies.NuGetPackageId)', '').Contains('Newtonsoft'))
) and
%(_AllNet472ContainerTaskDependencies.NuGetIsFrameworkReference) != true" />
<!-- containerize folder -->
<Content Include="$(OutDir)containerize.dll" Pack="true" PackagePath="containerize/" />
<Content Include="$(OutDir)containerize.runtimeconfig.json" Pack="true" PackagePath="containerize/" />
@ -70,25 +67,37 @@
<Content Include="$(OutDir)Valleysoft.DockerCredsProvider.dll" Pack="true" PackagePath="containerize/" />
<Content Include="@(ContainerLibraryOutput)" Pack="true" PackagePath="containerize/" />
<!-- net472 tasks -->
<!-- dependencies -->
<Content Include="@(NecessaryNet472ContainerTaskDependencies)" Pack="true" PackagePath="tasks/$(VSCompatTargetFramework)/" />
<!-- actual DLL -->
<Content Include="@(ContainerLibraryOutputNet472)" Pack="true" PackagePath="tasks/$(VSCompatTargetFramework)/" />
</ItemGroup>
<MSBuild Projects="../Microsoft.NET.Build.Containers/Microsoft.NET.Build.Containers.csproj" Properties="TargetFramework=$(TargetFramework)" Targets="ResolveAssemblyReferences">
<Output TaskParameter="TargetOutputs" ItemName="_AllNetContainerTaskDependencies" />
</MSBuild>
<ItemGroup>
<NecessaryNetContainerTaskDependencies Include="@(_AllNetContainerTaskDependencies)" Condition="(
$([MSBuild]::ValueOrDefault('%(_AllNetContainerTaskDependencies.NuGetPackageId)', '').Contains('NuGet')) or
$([MSBuild]::ValueOrDefault('%(_AllNetContainerTaskDependencies.NuGetPackageId)', '').Contains('Newtonsoft')) or
$([MSBuild]::ValueOrDefault('%(_AllNetContainerTaskDependencies.NuGetPackageId)', '').Contains('Valleysoft'))
) and
%(_AllNetContainerTaskDependencies.NuGetIsFrameworkReference) != true" />
<!-- root folder -->
<Content Include="README.md" Pack="true" PackagePath="" />
<!-- tasks folder -->
<!-- net7.0 tasks -->
<!-- dependencies -->
<Content Include="$(OutDir)Valleysoft.DockerCredsProvider.dll" Pack="true" PackagePath="tasks/$(TargetFramework)" />
<Content Include="$(OutDir)NuGet.*.dll" Pack="true" PackagePath="tasks/$(TargetFramework)" />
<Content Include="$(OutDir)Newtonsoft.Json.dll" Pack="true" PackagePath="tasks/$(TargetFramework)" />
<Content Include="$(OutDir)Microsoft.DotNet.Cli.Utils.dll" Pack="true" PackagePath="tasks/$(TargetFramework)" />
<Content Include="@(NecessaryNetContainerTaskDependencies)" Pack="true" PackagePath="tasks/$(TargetFramework)/" />
<Content Include="@(DotNetCliUtilsLibraryOutput)" Pack="true" PackagePath="tasks/$(TargetFramework)/" />
<!-- runtime deps json -->
<Content Include="$(ArtifactsDir)bin/Microsoft.NET.Build.Containers/$(Configuration)/$(TargetFramework)/Microsoft.NET.Build.Containers.deps.json" Pack="true" PackagePath="tasks/$(TargetFramework)" />
<!-- actual DLL -->
<Content Include="@(ContainerLibraryOutput)" Pack="true" PackagePath="tasks/$(TargetFramework)/" />
<!-- net472 tasks -->
<!-- dependencies -->
<Content Include="@(NecessaryNet472ContainerTaskDependencies)" Pack="true" PackagePath="tasks/$(VSCompatTargetFramework)/" Condition="'$(DotNetBuildFromSource)' != 'true'" />
<!-- runtime deps json isn't valid for netfx -->
<!-- actual DLL -->
<Content Include="@(ContainerLibraryOutputNet472)" Pack="true" PackagePath="tasks/$(VSCompatTargetFramework)/" Condition="'$(DotNetBuildFromSource)' != 'true'" />
<!-- build folder -->
<Content Include="build/**" Pack="true" PackagePath="build/" />
</ItemGroup>

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

@ -209,7 +209,8 @@
<MSBuild
Targets="Publish"
Projects="$(RepoRoot)/src/Containers/containerize/containerize.csproj"
Properties="Configuration=$(Configuration);PublishDir=$(OutputPath)/Containers/containerize" />
Properties="Configuration=$(Configuration);PublishDir=$(OutputPath)/Containers/containerize"
Condition="'$(DotNetBuildFromSource)' != 'true'" />
</Target>
<Target Name="GenerateCliRuntimeConfigurationFiles"

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

@ -14,6 +14,8 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
{
public class SdkDirectoryWorkloadManifestProvider : IWorkloadManifestProvider
{
private const string WorkloadSetsFolderName = "workloadsets";
private readonly string _sdkRootPath;
private readonly SdkFeatureBand _sdkVersionBand;
private readonly string[] _manifestRoots;
@ -21,15 +23,15 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
"microsoft.net.workload.maccatalyst", "microsoft.net.workload.macos", "microsoft.net.workload.tvos", "microsoft.net.workload.mono.toolchain" };
private readonly Dictionary<string, int>? _knownManifestIdsAndOrder;
private readonly Dictionary<string, ManifestSpecifier> _requestedManifestVersions;
private readonly WorkloadSet? _workloadSet;
public SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, string? userProfileDir, IEnumerable<ManifestSpecifier>? requestedManifestVersions = null)
: this(sdkRootPath, sdkVersion, Environment.GetEnvironmentVariable, userProfileDir, requestedManifestVersions)
public SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, string? userProfileDir, string? requestedWorkloadSet = null)
: this(sdkRootPath, sdkVersion, Environment.GetEnvironmentVariable, userProfileDir, requestedWorkloadSet)
{
}
internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, Func<string, string?> getEnvironmentVariable, string? userProfileDir, IEnumerable<ManifestSpecifier>? requestedManifestVersions = null)
internal SdkDirectoryWorkloadManifestProvider(string sdkRootPath, string sdkVersion, Func<string, string?> getEnvironmentVariable, string? userProfileDir, string? requestedWorkloadSet = null)
{
if (string.IsNullOrWhiteSpace(sdkVersion))
{
@ -87,15 +89,19 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
_manifestRoots = _manifestRoots ?? Array.Empty<string>();
_requestedManifestVersions = new Dictionary<string, ManifestSpecifier>(StringComparer.OrdinalIgnoreCase);
if (requestedManifestVersions != null)
var availableWorkloadSets = GetAvailableWorkloadSets();
if (requestedWorkloadSet != null)
{
foreach (var manifestVersion in requestedManifestVersions)
if (!availableWorkloadSets.TryGetValue(requestedWorkloadSet, out _workloadSet))
{
_requestedManifestVersions[manifestVersion.Id.ToString()] = manifestVersion;
throw new FileNotFoundException(string.Format(Strings.SpecifiedWorkloadSetNotFound, requestedWorkloadSet));
}
}
else if (availableWorkloadSets.Any())
{
var maxWorkloadSetVersion = availableWorkloadSets.Keys.Select(k => new ReleaseVersion(k)).Max()!;
_workloadSet = availableWorkloadSets[maxWorkloadSetVersion.ToString()];
}
}
public IEnumerable<ReadableWorkloadManifest> GetManifests()
@ -117,7 +123,7 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
public IEnumerable<string> GetManifestDirectories()
{
// Scan manifest directories
var manifestIdsToDirectories = new Dictionary<string, string>();
var manifestIdsToDirectories = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
void ProbeDirectory(string manifestDirectory)
{
@ -162,10 +168,13 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
}
}
// Load manifests that were explicitly specified
foreach (var kvp in _requestedManifestVersions)
// Load manifests from workload set, if any
if (_workloadSet != null)
{
manifestIdsToDirectories.Add(kvp.Key, GetManifestDirectoryFromSpecifier(kvp.Value));
foreach (var kvp in _workloadSet.ManifestVersions)
{
manifestIdsToDirectories[kvp.Key.ToString()] = GetManifestDirectoryFromSpecifier(new ManifestSpecifier(kvp.Key, kvp.Value.Version, kvp.Value.FeatureBand));
}
}
if (_knownManifestIdsAndOrder != null && _knownManifestIdsAndOrder.Keys.Any(id => !manifestIdsToDirectories.ContainsKey(id)))
@ -205,7 +214,8 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
private (string? id, string? manifestDirectory) ResolveManifestDirectory(string manifestDirectory)
{
string manifestId = Path.GetFileName(manifestDirectory);
if (_outdatedManifestIds.Contains(manifestId))
if (_outdatedManifestIds.Contains(manifestId) ||
manifestId.Equals(WorkloadSetsFolderName, StringComparison.OrdinalIgnoreCase))
{
return (null, null);
}
@ -285,10 +295,48 @@ namespace Microsoft.NET.Sdk.WorkloadManifestReader
throw new FileNotFoundException(string.Format(Strings.SpecifiedManifestNotFound, manifestSpecifier.ToString()));
}
private bool IsManifestIdOutdated(string workloadManifestDir)
/// <summary>
/// Returns installed workload sets that are available for this SDK (ie are in the same feature band)
/// </summary>
private Dictionary<string, WorkloadSet> GetAvailableWorkloadSets()
{
var manifestId = Path.GetFileName(workloadManifestDir);
return _outdatedManifestIds.Contains(manifestId);
Dictionary<string, WorkloadSet> availableWorkloadSets = new Dictionary<string, WorkloadSet>();
foreach (var manifestRoot in _manifestRoots.Reverse())
{
// Workload sets must match the SDK feature band, we don't support any fallback to a previous band
var workloadSetsRoot = Path.Combine(manifestRoot, _sdkVersionBand.ToString(), WorkloadSetsFolderName);
if (Directory.Exists(workloadSetsRoot))
{
foreach (var workloadSetDirectory in Directory.GetDirectories(workloadSetsRoot))
{
WorkloadSet? workloadSet = null;
foreach (var jsonFile in Directory.GetFiles(workloadSetDirectory, "*.workloadset.json"))
{
var newWorkloadSet = WorkloadSet.FromJson(File.ReadAllText(jsonFile), _sdkVersionBand);
if (workloadSet == null)
{
workloadSet = newWorkloadSet;
}
else
{
// If there are multiple workloadset.json files, merge them
foreach (var kvp in newWorkloadSet.ManifestVersions)
{
workloadSet.ManifestVersions.Add(kvp.Key, kvp.Value);
}
}
}
if (workloadSet != null)
{
workloadSet.Version = Path.GetFileName(workloadSetDirectory);
availableWorkloadSets[workloadSet.Version] = workloadSet;
}
}
}
}
return availableWorkloadSets;
}
public string GetSdkFeatureBand()

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

@ -192,4 +192,10 @@
<data name="SpecifiedManifestNotFound" xml:space="preserve">
<value>Specified workload manifest was not found: {0}</value>
</data>
<data name="SpecifiedWorkloadSetNotFound" xml:space="preserve">
<value>Specified workload set was not found: {0}</value>
</data>
<data name="InvalidVersionForWorkload" xml:space="preserve">
<value>Error parsing version '{1}' for workload manifest ID '{0}'</value>
</data>
</root>

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

@ -0,0 +1,97 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.DotNet.MSBuildSdkResolver;
using Strings = Microsoft.NET.Sdk.Localization.Strings;
#if USE_SYSTEM_TEXT_JSON
using System.Text.Json;
#else
using Newtonsoft.Json;
#endif
namespace Microsoft.NET.Sdk.WorkloadManifestReader
{
public class WorkloadSet
{
public Dictionary<ManifestId, (ManifestVersion Version, SdkFeatureBand FeatureBand)> ManifestVersions = new Dictionary<ManifestId, (ManifestVersion version, SdkFeatureBand featureBand)>();
// TODO: Generate version from hash of manifest versions if not otherwise set
public string? Version { get; set; }
public static WorkloadSet FromManifests(IEnumerable<WorkloadManifestInfo> manifests)
{
return new WorkloadSet()
{
ManifestVersions = manifests.ToDictionary(m => new ManifestId(m.Id), m => (new ManifestVersion(m.Version), new SdkFeatureBand(m.ManifestFeatureBand)))
};
}
public static WorkloadSet FromDictionaryForJson(IDictionary<string, string> dictionary, SdkFeatureBand defaultFeatureBand)
{
var manifestVersions = dictionary
.Select(manifest =>
{
ManifestVersion manifestVersion;
SdkFeatureBand manifestFeatureBand;
var parts = manifest.Value.Split('/');
string manifestVersionString = parts[0];
if (!FXVersion.TryParse(manifestVersionString, out FXVersion version))
{
throw new FormatException(String.Format(Strings.InvalidVersionForWorkload, manifest.Key, manifestVersionString));
}
manifestVersion = new ManifestVersion(parts[0]);
if (parts.Length == 1)
{
manifestFeatureBand = defaultFeatureBand;
}
else
{
manifestFeatureBand = new SdkFeatureBand(parts[1]);
}
return (id: new ManifestId(manifest.Key), manifestVersion, manifestFeatureBand);
}).ToDictionary(t => t.id, t => (t.manifestVersion, t.manifestFeatureBand));
return new WorkloadSet()
{
ManifestVersions = manifestVersions
};
}
public static WorkloadSet FromJson(string json, SdkFeatureBand defaultFeatureBand)
{
#if USE_SYSTEM_TEXT_JSON
return FromDictionaryForJson(JsonSerializer.Deserialize<IDictionary<string, string>>(json)!, defaultFeatureBand);
#else
return FromDictionaryForJson(JsonConvert.DeserializeObject<IDictionary<string, string>>(json)!, defaultFeatureBand);
#endif
}
public Dictionary<string, string> ToDictionaryForJson()
{
var dictionary = ManifestVersions.ToDictionary(kvp => kvp.Key.ToString(), kvp => kvp.Value.Version + "/" + kvp.Value.FeatureBand, StringComparer.OrdinalIgnoreCase);
return dictionary;
}
public string ToJson()
{
#if USE_SYSTEM_TEXT_JSON
var json = JsonSerializer.Serialize(ToDictionaryForJson(), new JsonSerializerOptions() { WriteIndented = true });
#else
var json = JsonConvert.SerializeObject(ToDictionaryForJson(), Formatting.Indented);
#endif
return json;
}
}
}

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

@ -62,6 +62,11 @@
<target state="translated">Neplatná verze: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">Nebyla nalezena závislost manifestu úlohy {0} požadovaná manifestem {1} [{2}].</target>
@ -102,6 +107,11 @@
<target state="translated">Zadaný manifest úlohy se nenašel: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Neočekávaný token {0} u posunu {1}</target>

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

@ -62,6 +62,11 @@
<target state="translated">Ungültige Version: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">Die Workloadmanifestabhängigkeit „{0}“, die vom Manifest „{1}“ [{2}] benötigt wird, wurde nicht gefunden.</target>
@ -102,6 +107,11 @@
<target state="translated">Das angegebene Workloadmanifest wurde nicht gefunden: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Unerwartetes Token "{0}" bei Offset {1}.</target>

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

@ -62,6 +62,11 @@
<target state="translated">Versión no válida: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">No se ha encontrado la dependencia del manifiesto de carga de trabajo '{0}' requerida por el manifiesto '{1}' [{2}]</target>
@ -102,6 +107,11 @@
<target state="translated">No se encontró el manifiesto de carga de trabajo especificado: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Token "{0}" inesperado en el desplazamiento {1}</target>

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

@ -62,6 +62,11 @@
<target state="translated">Version non valide : {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">La dépendance de manifeste de charge de travail « {0} » requise par le manifeste « {1} » [{2}] est introuvable</target>
@ -102,6 +107,11 @@
<target state="translated">Le manifeste de charge de travail spécifié est introuvable : {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Jeton '{0}' inattendu à l'offset {1}</target>

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

@ -62,6 +62,11 @@
<target state="translated">Versione non valida: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">La dipendenza del manifesto del carico di lavoro '{0}' richiesta dal manifesto '{1}' [{2}] non è stata trovata</target>
@ -102,6 +107,11 @@
<target state="translated">Il manifesto del carico di lavoro specificato non è stato trovato: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Token '{0}' imprevisto alla posizione di offset {1}</target>

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

@ -62,6 +62,11 @@
<target state="translated">無効なバージョン: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">マニフェスト '{1}' [{2}] で必要なワークロード マニフェストの依存関係 '{0}' が見つかりません</target>
@ -102,6 +107,11 @@
<target state="translated">指定されたワークロード マニフェストが見つかりませんでした: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">オフセット {1} に予期しないトークン '{0}' があります</target>

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

@ -62,6 +62,11 @@
<target state="translated">잘못된 버전: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">매니페스트 '{1}' [{2}]에 필요한 워크로드 매니페스트 종속성 '{0}'을(를) 찾지 못했습니다</target>
@ -102,6 +107,11 @@
<target state="translated">지정한 워크로드 매니페스트를 찾을 수 없습니다. {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">오프셋 {1}에 예기치 않은 토큰 '{0}'이(가) 있습니다.</target>

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

@ -62,6 +62,11 @@
<target state="translated">Nieprawidłowa wersja: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">Nie znaleziono zależności manifestu obciążenia „{0}” wymaganej przez manifest „{1}” [{2}]</target>
@ -102,6 +107,11 @@
<target state="translated">Nie znaleziono określonego manifestu obciążenia: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Nieoczekiwany token „{0}” pod przesunięciem {1}</target>

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

@ -62,6 +62,11 @@
<target state="translated">Versão inválida: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">Não foi possível encontrar a dependência do manifesto de carga de trabalho '{0}' exigida pelo manifesto '{1}' [{2}]</target>
@ -102,6 +107,11 @@
<target state="translated">O manifesto de carga de trabalho especificado não foi encontrado: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Token inesperado '{0}' no deslocamento {1}</target>

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

@ -62,6 +62,11 @@
<target state="translated">Недопустимая версия: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">Не найдена зависимость манифеста рабочей нагрузки "{0}", необходимая для манифеста "{1}" [{2}]</target>
@ -102,6 +107,11 @@
<target state="translated">Указанный манифест рабочей нагрузки не найден: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">Непредвиденный токен "{0}" в смещении {1}</target>

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

@ -62,6 +62,11 @@
<target state="translated">Geçersiz sürüm: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">{1}' [{2}] bildirimi için gereken '{0}' iş yükü bildirimi bağımlılığı bulunamadı</target>
@ -102,6 +107,11 @@
<target state="translated">Belirtilen iş yükü bildirimi bulunamadı: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">{1} uzaklığında beklenmeyen '{0}' belirteci</target>

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

@ -62,6 +62,11 @@
<target state="translated">版本 {0} 无效</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">未找到清单“{1}”[{2}] 所需的工作负载清单依赖项“{0}”</target>
@ -102,6 +107,11 @@
<target state="translated">找不到指定的工作负荷清单: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">偏移为 {1} 时意外出现的标记“{0}”</target>

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

@ -62,6 +62,11 @@
<target state="translated">無效的版本: {0}</target>
<note />
</trans-unit>
<trans-unit id="InvalidVersionForWorkload">
<source>Error parsing version '{1}' for workload manifest ID '{0}'</source>
<target state="new">Error parsing version '{1}' for workload manifest ID '{0}'</target>
<note />
</trans-unit>
<trans-unit id="ManifestDependencyMissing">
<source>Did not find workload manifest dependency '{0}' required by manifest '{1}' [{2}]</source>
<target state="translated">找不到資訊清單 '{1}' [{2}] 所需的工作負載資訊清單相依性 '{0}'</target>
@ -102,6 +107,11 @@
<target state="translated">找不到指定的工作負載資訊清單: {0}</target>
<note />
</trans-unit>
<trans-unit id="SpecifiedWorkloadSetNotFound">
<source>Specified workload set was not found: {0}</source>
<target state="new">Specified workload set was not found: {0}</target>
<note />
</trans-unit>
<trans-unit id="UnexpectedTokenAtOffset">
<source>Unexpected token '{0}' at offset {1}</source>
<target state="translated">位移 {1} 有未預期的權杖 '{0}'</target>

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: Architektura {0} se nepodporuje a v budoucnu už nebude dostávat aktualizace zabezpečení. Další informace o zásadách podpory najdete tady: {1}.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: Die Workload „{0}“ wird nicht mehr unterstützt und erhält in Zukunft keine Sicherheitsupdates mehr. Weitere Informationen zur Supportrichtlinie finden Sie unter „{1}“.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: La carga de trabajo "{0}" está fuera de soporte y no recibirá actualizaciones de seguridad en el futuro. Consulte {1} más información sobre la directiva de soporte.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: La charge de travail '{0}' nest pas prise en charge et ne recevra pas les mises à jour de sécurité. Consultez {1} pour plus dinformations sur la stratégie de support.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: il carico di lavoro '{0}' non è supportato e non riceverà gli aggiornamenti della sicurezza in futuro. Per altre informazioni sui criteri di supporto, vedere {1} .</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: ワークロード '{0}' はサポートされていません。今後、セキュリティ更新プログラムを受け取ることはありません。サポート ポリシーの詳細については、{1} をご覧ください。</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: '{0}' 워크로드는 지원되지 않으며 향후 보안 업데이트를 받지 않습니다. 지원 정책에 대한 자세한 내용은 {1}을(를) 참조하세요.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: Obciążenie „{0}” nie jest obsługiwane i nie będzie otrzymywać aktualizacji zabezpieczeń w przyszłości. Aby uzyskać więcej informacji na temat zasad pomocy technicznej, zapoznaj się z {1} .</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: a carga de trabalho '{0}' está sem suporte e não receberá atualizações de segurança no futuro. Consulte o {1} para obter mais informações sobre a política de suporte.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: рабочая нагрузка "{0}" не поддерживается, для нее не будут выпускаться обновления системы безопасности. Дополнительные сведения о политике поддержки: {1}.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: '{0}' iş yükü destek kapsamı dışında olduğu için gelecekte güvenlik güncelleştirmeleri almayacak. Destek ilkesi hakkında daha fazla bilgi edinmek için lütfen şuraya bakın: {1}.</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: 工作负载“{0}”已失去支持,并且将来不会收到安全更新。有关支持政策的详细信息,请参阅 {1}。</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -1014,7 +1014,7 @@ The following are names of parameters or literal values and should not be transl
</trans-unit>
<trans-unit id="WorkloadIsEol">
<source>NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</source>
<target state="new">NETSDK1202: The workload '{0}' is out of support and will not receive security updates in the future. Please refer to {1} for more information about the support policy.</target>
<target state="translated">NETSDK1202: 已不支援目標工作負載 '{0}',未來將不會再收到任何安全性更新。如需支援原則的詳細資訊,請參閱 {1}。</target>
<note>{StrBegin="NETSDK1202: "}</note>
</trans-unit>
<trans-unit id="WorkloadNotAvailable">

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

@ -457,12 +457,11 @@ Copyright (c) .NET Foundation. All rights reserved.
<Output TaskParameter="FullFrameworkReferenceAssemblyPaths" PropertyName="_FullFrameworkReferenceAssemblyPaths"/>
</GetReferenceAssemblyPaths>
<ItemGroup>
<_ExistingReferenceAssembliesPackageReference Include="@(PackageReference)" Condition="'%(PackageReference.Identity)' == 'Microsoft.NETFramework.ReferenceAssemblies'"/>
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" Version="$(MicrosoftNETFrameworkReferenceAssembliesLatestPackageVersion)" IsImplicitlyDefined="true" PrivateAssets="All"
Condition="'$(_FullFrameworkReferenceAssemblyPaths)' == '' and '@(_ExistingReferenceAssembliesPackageReference)' == ''"/>
Condition="('$(_FullFrameworkReferenceAssemblyPaths)' == '' or $(_FullFrameworkReferenceAssemblyPaths.Contains('microsoft.netframework.referenceassemblies'))) and '@(_ExistingReferenceAssembliesPackageReference)' == ''"/>
</ItemGroup>
</Target>

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

@ -10,6 +10,9 @@ using Microsoft.NET.Build.Containers.UnitTests;
using Microsoft.NET.TestFramework.Assertions;
using Microsoft.NET.TestFramework.Commands;
using Microsoft.NET.TestFramework;
using FakeItEasy;
using Microsoft.Build.Framework;
using System.Runtime.CompilerServices;
namespace Microsoft.NET.Build.Containers.Tasks.IntegrationTests;
@ -26,8 +29,7 @@ public class CreateNewImageTests
[DockerAvailableFact]
public void CreateNewImage_Baseline()
{
DirectoryInfo newProjectDir = new DirectoryInfo(Path.Combine(TestSettings.TestArtifactsDirectory, nameof(CreateNewImage_Baseline)));
DirectoryInfo newProjectDir = new(GetTestDirectoryName());
if (newProjectDir.Exists)
{
newProjectDir.Delete(recursive: true);
@ -46,28 +48,33 @@ public class CreateNewImageTests
.Execute()
.Should().Pass();
CreateNewImage task = new CreateNewImage();
CreateNewImage task = new();
(IBuildEngine buildEngine, List<string?> errors) = SetupBuildEngine();
task.BuildEngine = buildEngine;
task.BaseRegistry = "mcr.microsoft.com";
task.BaseImageName = "dotnet/runtime";
task.BaseImageTag = "7.0";
task.OutputRegistry = "localhost:5010";
task.LocalRegistry = "Docker";
task.PublishDirectory = Path.Combine(newProjectDir.FullName, "bin", "Release", ToolsetInfo.CurrentTargetFramework, "linux-arm64", "publish");
task.ImageName = "dotnet/testimage";
task.Repository = "dotnet/create-new-image-baseline";
task.ImageTags = new[] { "latest" };
task.WorkingDirectory = "app/";
task.ContainerRuntimeIdentifier = "linux-arm64";
task.Entrypoint = new TaskItem[] { new("dotnet"), new("build") };
task.RuntimeIdentifierGraphPath = ToolsetUtils.GetRuntimeGraphFilePath();
Assert.True(task.Execute());
Assert.True(task.Execute(), FormatBuildMessages(errors));
newProjectDir.Delete(true);
}
[DockerAvailableFact]
public void ParseContainerProperties_EndToEnd()
{
DirectoryInfo newProjectDir = new DirectoryInfo(Path.Combine(TestSettings.TestArtifactsDirectory, nameof(ParseContainerProperties_EndToEnd)));
DirectoryInfo newProjectDir = new(GetTestDirectoryName());
if (newProjectDir.Exists)
{
@ -87,34 +94,40 @@ public class CreateNewImageTests
.Execute()
.Should().Pass();
ParseContainerProperties pcp = new ParseContainerProperties();
ParseContainerProperties pcp = new();
(IBuildEngine buildEngine, List<string?> errors) = SetupBuildEngine();
pcp.BuildEngine = buildEngine;
pcp.FullyQualifiedBaseImageName = "mcr.microsoft.com/dotnet/runtime:7.0";
pcp.ContainerRegistry = "localhost:5010";
pcp.ContainerImageName = "dotnet/testimage";
pcp.ContainerRepository = "dotnet/testimage";
pcp.ContainerImageTags = new[] { "5.0", "latest" };
Assert.True(pcp.Execute());
Assert.True(pcp.Execute(), FormatBuildMessages(errors));
Assert.Equal("mcr.microsoft.com", pcp.ParsedContainerRegistry);
Assert.Equal("dotnet/runtime", pcp.ParsedContainerImage);
Assert.Equal("7.0", pcp.ParsedContainerTag);
Assert.Equal("dotnet/testimage", pcp.NewContainerImageName);
Assert.Equal("dotnet/testimage", pcp.NewContainerRepository);
pcp.NewContainerTags.Should().BeEquivalentTo(new[] { "5.0", "latest" });
CreateNewImage cni = new CreateNewImage();
CreateNewImage cni = new();
(buildEngine, errors) = SetupBuildEngine();
cni.BuildEngine = buildEngine;
cni.BaseRegistry = pcp.ParsedContainerRegistry;
cni.BaseImageName = pcp.ParsedContainerImage;
cni.BaseImageTag = pcp.ParsedContainerTag;
cni.ImageName = pcp.NewContainerImageName;
cni.Repository = pcp.NewContainerRepository;
cni.OutputRegistry = "localhost:5010";
cni.PublishDirectory = Path.Combine(newProjectDir.FullName, "bin", "release", ToolsetInfo.CurrentTargetFramework);
cni.WorkingDirectory = "app/";
cni.Entrypoint = new TaskItem[] { new("ParseContainerProperties_EndToEnd") };
cni.Entrypoint = new TaskItem[] { new(newProjectDir.Name) };
cni.ImageTags = pcp.NewContainerTags;
cni.ContainerRuntimeIdentifier = "linux-x64";
cni.RuntimeIdentifierGraphPath = ToolsetUtils.GetRuntimeGraphFilePath();
Assert.True(cni.Execute());
Assert.True(cni.Execute(), FormatBuildMessages(errors));
newProjectDir.Delete(true);
}
@ -124,7 +137,7 @@ public class CreateNewImageTests
[DockerAvailableFact]
public void Tasks_EndToEnd_With_EnvironmentVariable_Validation()
{
DirectoryInfo newProjectDir = new DirectoryInfo(Path.Combine(TestSettings.TestArtifactsDirectory, nameof(Tasks_EndToEnd_With_EnvironmentVariable_Validation)));
DirectoryInfo newProjectDir = new(GetTestDirectoryName());
if (newProjectDir.Exists)
{
@ -146,10 +159,13 @@ public class CreateNewImageTests
.Execute()
.Should().Pass();
ParseContainerProperties pcp = new ParseContainerProperties();
ParseContainerProperties pcp = new();
(IBuildEngine buildEngine, List<string?> errors) = SetupBuildEngine();
pcp.BuildEngine = buildEngine;
pcp.FullyQualifiedBaseImageName = $"mcr.microsoft.com/{DockerRegistryManager.RuntimeBaseImage}:{DockerRegistryManager.Net8PreviewImageTag}";
pcp.ContainerRegistry = "";
pcp.ContainerImageName = "dotnet/envvarvalidation";
pcp.ContainerRepository = "dotnet/envvarvalidation";
pcp.ContainerImageTag = "latest";
Dictionary<string, string> dict = new Dictionary<string, string>();
@ -157,34 +173,37 @@ public class CreateNewImageTests
pcp.ContainerEnvironmentVariables = new[] { new TaskItem("B@dEnv.Var", dict), new TaskItem("GoodEnvVar", dict) };
Assert.True(pcp.Execute());
Assert.True(pcp.Execute(), FormatBuildMessages(errors));
Assert.Equal("mcr.microsoft.com", pcp.ParsedContainerRegistry);
Assert.Equal("dotnet/runtime", pcp.ParsedContainerImage);
Assert.Equal(DockerRegistryManager.Net8PreviewImageTag, pcp.ParsedContainerTag);
Assert.Single(pcp.NewContainerEnvironmentVariables);
Assert.Equal("Foo", pcp.NewContainerEnvironmentVariables[0].GetMetadata("Value"));
Assert.Equal("dotnet/envvarvalidation", pcp.NewContainerImageName);
Assert.Equal("dotnet/envvarvalidation", pcp.NewContainerRepository);
Assert.Equal("latest", pcp.NewContainerTags[0]);
CreateNewImage cni = new CreateNewImage();
CreateNewImage cni = new();
(buildEngine, errors) = SetupBuildEngine();
cni.BuildEngine = buildEngine;
cni.BaseRegistry = pcp.ParsedContainerRegistry;
cni.BaseImageName = pcp.ParsedContainerImage;
cni.BaseImageTag = pcp.ParsedContainerTag;
cni.ImageName = pcp.NewContainerImageName;
cni.Repository = pcp.NewContainerRepository;
cni.OutputRegistry = pcp.NewContainerRegistry;
cni.PublishDirectory = Path.Combine(newProjectDir.FullName, "bin", "release", ToolsetInfo.CurrentTargetFramework, "linux-x64");
cni.WorkingDirectory = "/app";
cni.Entrypoint = new TaskItem[] { new("/app/Tasks_EndToEnd_With_EnvironmentVariable_Validation") };
cni.Entrypoint = new TaskItem[] { new($"/app/{newProjectDir.Name}") };
cni.ImageTags = pcp.NewContainerTags;
cni.ContainerEnvironmentVariables = pcp.NewContainerEnvironmentVariables;
cni.ContainerRuntimeIdentifier = "linux-x64";
cni.RuntimeIdentifierGraphPath = ToolsetUtils.GetRuntimeGraphFilePath();
cni.LocalRegistry = global::Microsoft.NET.Build.Containers.KnownLocalRegistryTypes.Docker;
Assert.True(cni.Execute());
Assert.True(cni.Execute(), FormatBuildMessages(errors));
ContainerCli.RunCommand(_testOutput, "--rm", $"{pcp.NewContainerImageName}:latest")
ContainerCli.RunCommand(_testOutput, "--rm", $"{pcp.NewContainerRepository}:latest")
.Execute()
.Should().Pass()
.And.HaveStdOut("Foo");
@ -246,7 +265,7 @@ public class CreateNewImageTests
task.OutputRegistry = "localhost:5010";
task.PublishDirectory = Path.Combine(newProjectDir.FullName, "bin", "Release", ToolsetInfo.CurrentTargetFramework, "linux-x64", "publish");
task.ImageName = AppImage;
task.Repository = AppImage;
task.ImageTags = new[] { "latest" };
task.WorkingDirectory = "app/";
task.ContainerRuntimeIdentifier = "linux-x64";
@ -266,4 +285,19 @@ public class CreateNewImageTests
Assert.Equal(RootlessUser, imageBuilder.BaseImageConfig.User);
}
private static (IBuildEngine buildEngine, List<string?> errors) SetupBuildEngine()
{
List<string?> errors = new();
IBuildEngine buildEngine = A.Fake<IBuildEngine>();
A.CallTo(() => buildEngine.LogWarningEvent(A<BuildWarningEventArgs>.Ignored)).Invokes((BuildWarningEventArgs e) => errors.Add(e.Message));
A.CallTo(() => buildEngine.LogErrorEvent(A<BuildErrorEventArgs>.Ignored)).Invokes((BuildErrorEventArgs e) => errors.Add(e.Message));
A.CallTo(() => buildEngine.LogMessageEvent(A<BuildMessageEventArgs>.Ignored)).Invokes((BuildMessageEventArgs e) => errors.Add(e.Message));
return (buildEngine, errors);
}
private static string GetTestDirectoryName([CallerMemberName]string testName = "DefaultTest") => Path.Combine(TestSettings.TestArtifactsDirectory, testName + "_" + DateTime.Now.ToString("yyyyMMddHHmmss"));
private static string FormatBuildMessages(List<string?> messages) => string.Join("\r\n", messages);
}

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

@ -26,7 +26,7 @@ public class EndToEndTests
public static string NewImageName([CallerMemberName] string callerMemberName = "")
{
bool normalized = ContainerHelpers.NormalizeImageName(callerMemberName, out string? normalizedName);
bool normalized = ContainerHelpers.NormalizeRepository(callerMemberName, out string? normalizedName);
if (!normalized)
{
return normalizedName!;
@ -228,7 +228,7 @@ public class EndToEndTests
"/p:runtimeidentifier=linux-x64",
$"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}",
$"/p:ContainerRegistry={DockerRegistryManager.LocalRegistry}",
$"/p:ContainerImageName={imageName}",
$"/p:ContainerRepository={imageName}",
$"/p:Version={imageTag}",
$"/p:RuntimeFrameworkVersion=8.0.0-preview.3.23174.8")
.WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)
@ -366,7 +366,7 @@ public class EndToEndTests
"/p:runtimeidentifier=linux-x64",
$"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}",
$"/p:ContainerRegistry={DockerRegistryManager.LocalRegistry}",
$"/p:ContainerImageName={imageName}",
$"/p:ContainerRepository={imageName}",
$"/p:RuntimeFrameworkVersion=8.0.0-preview.3.23174.8",
$"/p:Version={imageTag}")
.WithEnvironmentVariable("NUGET_PACKAGES", privateNuGetAssets.FullName)

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

@ -46,9 +46,9 @@ public class CreateNewImageToolTaskTests
task.BaseImageName = "MyBaseImageName";
e = Assert.Throws<InvalidOperationException>(() => task.GenerateCommandLineCommandsInt());
Assert.Equal("CONTAINER4001: Required property 'ImageName' was not set or empty.", e.Message);
Assert.Equal("CONTAINER4001: Required property 'Repository' was not set or empty.", e.Message);
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
e = Assert.Throws<InvalidOperationException>(() => task.GenerateCommandLineCommandsInt());
Assert.Equal("CONTAINER4001: Required property 'WorkingDirectory' was not set or empty.", e.Message);
@ -58,7 +58,7 @@ public class CreateNewImageToolTaskTests
e = Assert.Throws<InvalidOperationException>(() => task.GenerateCommandLineCommandsInt());
Assert.Equal("CONTAINER4002: Required 'Entrypoint' items were not set.", e.Message);
task.Entrypoint = new[] { new TaskItem("") };
task.Entrypoint = new[] { new TaskItem("") };
e = Assert.Throws<InvalidOperationException>(() => task.GenerateCommandLineCommandsInt());
Assert.Equal("CONTAINER4003: Required 'Entrypoint' items contain empty items.", e.Message);
@ -88,7 +88,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -103,7 +103,7 @@ public class CreateNewImageToolTaskTests
else
{
Assert.DoesNotContain("--baseimagetag", args);
}
}
}
@ -119,7 +119,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -149,7 +149,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -178,7 +178,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -211,7 +211,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -257,7 +257,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -304,7 +304,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -348,7 +348,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };
@ -385,7 +385,7 @@ public class CreateNewImageToolTaskTests
task.PublishDirectory = publishDir.FullName;
task.BaseRegistry = "MyBaseRegistry";
task.BaseImageName = "MyBaseImageName";
task.ImageName = "MyImageName";
task.Repository = "MyImageName";
task.WorkingDirectory = "MyWorkingDirectory";
task.Entrypoint = new[] { new TaskItem("MyEntryPoint") };

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

@ -18,6 +18,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildTasksCorePackageVersion)"/>
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildUtilitiesCorePackageVersion)"/>
<PackageReference Include="Microsoft.Build" Version="$(MicrosoftBuildPackageVersion)" />
<PackageReference Include="Microsoft.Build.Framework" Version="$(MicrosoftBuildFrameworkPackageVersion)"/>

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

@ -0,0 +1,133 @@
// Copyright (c) .NET Foundation and contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
using System.IO.Compression;
using System.Xml.Linq;
using FluentAssertions;
using Microsoft.NET.TestFramework;
using Microsoft.DotNet.Cli.Utils;
using Xunit;
namespace Microsoft.NET.Build.Containers.IntegrationTests;
public class PackageTests
{
[Fact]
public void SanityTest_ContainerizeDependencies()
{
IReadOnlyList<string> knownPackageReferences = new List<string>()
{
"System.CommandLine"
};
IReadOnlyList<string> knownProjectReferences = new List<string>()
{
"..\\Microsoft.NET.Build.Containers\\Microsoft.NET.Build.Containers.csproj"
};
string projectFilePath = Path.Combine(TestContext.Current.TestExecutionDirectory, "Container", "ProjectFiles", "containerize.csproj");
XDocument project = XDocument.Load(projectFilePath);
XNamespace ns = project.Root?.Name.Namespace ?? throw new InvalidOperationException("Project file is empty");
IEnumerable<string?> packageReferences = project.Descendants().Where(element => element.Name.Equals(ns + "PackageReference")).Select(element => element.Attribute("Include")?.Value);
packageReferences.Should().BeEquivalentTo(knownPackageReferences, $"Known package references for containerize project are different from actual. Check if this is expected. If the new package reference is expected, add it to {nameof(knownPackageReferences)} and verify they are included to NuGet package in package.csproj correctly");
IEnumerable<string?> projectReferences = project.Descendants().Where(element => element.Name.Equals(ns + "ProjectReference")).Select(element => element.Attribute("Include")?.Value);
projectReferences.Should().BeEquivalentTo(knownProjectReferences, $"Known project references for containerize project are different from actual. Check if this is expected. If the new project reference is expected, add it to {nameof(knownProjectReferences)} and verify they are included to NuGet package in package.csproj correctly");
}
[Fact]
public void SanityTest_NET_Build_ContainersDependencies()
{
IReadOnlyList<string> knownPackageReferences = new List<string>()
{
"Microsoft.Build.Utilities.Core",
"Microsoft.CodeAnalysis.PublicApiAnalyzers",
"Nuget.Packaging",
"Valleysoft.DockerCredsProvider"
};
IReadOnlyList<string> knownProjectReferences = new List<string>()
{
"..\\..\\Cli\\Microsoft.DotNet.Cli.Utils\\Microsoft.DotNet.Cli.Utils.csproj"
};
string projectFilePath = Path.Combine(TestContext.Current.TestExecutionDirectory, "Container", "ProjectFiles", "Microsoft.NET.Build.Containers.csproj");
XDocument project = XDocument.Load(projectFilePath);
XNamespace ns = project.Root?.Name.Namespace ?? throw new InvalidOperationException("Project file is empty");
IEnumerable<string?> packageReferences = project.Descendants().Where(element => element.Name.Equals(ns + "PackageReference")).Select(element => element.Attribute("Include")?.Value);
packageReferences.Should().BeEquivalentTo(knownPackageReferences, $"Known package references for Microsoft.NET.Build.Containers project are different from actual. Check if this is expected. If the new package reference is expected, add it to {nameof(knownPackageReferences)} and verify they are included to NuGet package in package.csproj correctly");
IEnumerable<string?> projectReferences = project.Descendants().Where(element => element.Name.Equals(ns + "ProjectReference")).Select(element => element.Attribute("Include")?.Value);
projectReferences.Should().BeEquivalentTo(knownProjectReferences, $"Known project references for Microsoft.NET.Build.Containers project are different from actual. Check if this is expected. If the new project reference is expected, add it to {nameof(knownProjectReferences)} and verify they are included to NuGet package in package.csproj correctly");
}
[Fact]
public void PackageContentTest()
{
string ignoredZipFileEntriesPrefix = "package/services/metadata";
IReadOnlyList<string> packageContents = new List<string>()
{
"_rels/.rels",
"[Content_Types].xml",
"build/Microsoft.NET.Build.Containers.props",
"build/Microsoft.NET.Build.Containers.targets",
"containerize/containerize.dll",
"containerize/containerize.runtimeconfig.json",
"containerize/Microsoft.DotNet.Cli.Utils.dll",
"containerize/Microsoft.NET.Build.Containers.dll",
"containerize/Newtonsoft.Json.dll",
"containerize/NuGet.Common.dll",
"containerize/NuGet.Configuration.dll",
"containerize/NuGet.DependencyResolver.Core.dll",
"containerize/NuGet.Frameworks.dll",
"containerize/NuGet.LibraryModel.dll",
"containerize/NuGet.Packaging.dll",
"containerize/NuGet.ProjectModel.dll",
"containerize/NuGet.Protocol.dll",
"containerize/NuGet.Versioning.dll",
"containerize/System.CommandLine.dll",
"containerize/Valleysoft.DockerCredsProvider.dll",
"Icon.png",
"Microsoft.NET.Build.Containers.nuspec",
"README.md",
"tasks/net472/Microsoft.NET.Build.Containers.dll",
"tasks/net472/Newtonsoft.Json.dll",
"tasks/net472/NuGet.Common.dll",
"tasks/net472/NuGet.Configuration.dll",
"tasks/net472/NuGet.DependencyResolver.Core.dll",
"tasks/net472/NuGet.Frameworks.dll",
"tasks/net472/NuGet.LibraryModel.dll",
"tasks/net472/NuGet.Packaging.Core.dll",
"tasks/net472/NuGet.Packaging.dll",
"tasks/net472/NuGet.ProjectModel.dll",
"tasks/net472/NuGet.Protocol.dll",
"tasks/net472/NuGet.Versioning.dll",
"tasks/net7.0/Microsoft.DotNet.Cli.Utils.dll",
"tasks/net7.0/Microsoft.NET.Build.Containers.deps.json",
"tasks/net7.0/Microsoft.NET.Build.Containers.dll",
"tasks/net7.0/Newtonsoft.Json.dll",
"tasks/net7.0/NuGet.Common.dll",
"tasks/net7.0/NuGet.Configuration.dll",
"tasks/net7.0/NuGet.DependencyResolver.Core.dll",
"tasks/net7.0/NuGet.Frameworks.dll",
"tasks/net7.0/NuGet.LibraryModel.dll",
"tasks/net7.0/NuGet.Packaging.dll",
"tasks/net7.0/NuGet.Packaging.Core.dll",
"tasks/net7.0/NuGet.ProjectModel.dll",
"tasks/net7.0/NuGet.Protocol.dll",
"tasks/net7.0/NuGet.Versioning.dll",
"tasks/net7.0/Valleysoft.DockerCredsProvider.dll"
};
string packageFilePath = Path.Combine(TestContext.Current.TestExecutionDirectory, "Container", "package", $"Microsoft.NET.Build.Containers.{Product.Version}.nupkg");
using ZipArchive archive = new(File.OpenRead(packageFilePath), ZipArchiveMode.Read, false);
archive.Entries
.Select(e => e.FullName)
.Where(e => !e.StartsWith(ignoredZipFileEntriesPrefix, StringComparison.InvariantCultureIgnoreCase))
.Should()
.BeEquivalentTo(packageContents, $"Microsoft.NET.Build.Containers.{Product.Version}.nupkg content differs from expected. Please add the entry to the list, if the addition is expected.");
}
}

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

@ -16,21 +16,21 @@ public class ParseContainerPropertiesTests
[DockerAvailableFact]
public void Baseline()
{
var (project, _, d) = ProjectInitializer.InitProject(new () {
var (project, logs, d) = ProjectInitializer.InitProject(new () {
[ContainerBaseImage] = "mcr.microsoft.com/dotnet/runtime:7.0",
[ContainerRegistry] = "localhost:5010",
[ContainerImageName] = "dotnet/testimage",
[ContainerRepository] = "dotnet/testimage",
[ContainerImageTags] = "7.0;latest"
});
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
Assert.True(instance.Build(new[]{ComputeContainerConfig}, null, null, out var outputs));
Assert.True(instance.Build(new[]{ComputeContainerConfig}, new [] { logs }, null, out var outputs));
Assert.Equal("mcr.microsoft.com", instance.GetPropertyValue(ContainerBaseRegistry));
Assert.Equal("dotnet/runtime", instance.GetPropertyValue(ContainerBaseName));
Assert.Equal("7.0", instance.GetPropertyValue(ContainerBaseTag));
Assert.Equal("dotnet/testimage", instance.GetPropertyValue(ContainerImageName));
Assert.Equal("dotnet/testimage", instance.GetPropertyValue(ContainerRepository));
instance.GetItems(ContainerImageTags).Select(i => i.EvaluatedInclude).ToArray().Should().BeEquivalentTo(new[] { "7.0", "latest" });
instance.GetItems("ProjectCapability").Select(i => i.EvaluatedInclude).ToArray().Should().BeEquivalentTo(new[] { "NetSdkOCIImageBuild" });
}
@ -38,13 +38,13 @@ public class ParseContainerPropertiesTests
[DockerAvailableFact]
public void SpacesGetReplacedWithDashes()
{
var (project, _, d) = ProjectInitializer.InitProject(new () {
var (project, logs, d) = ProjectInitializer.InitProject(new () {
[ContainerBaseImage] = "mcr.microsoft.com/dotnet runtime:7.0",
[ContainerRegistry] = "localhost:5010"
});
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
Assert.True(instance.Build(new[]{ComputeContainerConfig}, null, null, out var outputs));
Assert.True(instance.Build(new[]{ComputeContainerConfig}, new [] { logs }, null, out var outputs));
Assert.Equal("mcr.microsoft.com",instance.GetPropertyValue(ContainerBaseRegistry));
Assert.Equal("dotnet-runtime", instance.GetPropertyValue(ContainerBaseName));
@ -57,13 +57,13 @@ public class ParseContainerPropertiesTests
var (project, logs, d) = ProjectInitializer.InitProject(new () {
[ContainerBaseImage] = "mcr.microsoft.com/dotnet/runtime:7.0",
[ContainerRegistry] = "localhost:5010",
[ContainerImageName] = "dotnet testimage",
[ContainerRepository] = "dotnet testimage",
[ContainerImageTag] = "5.0"
});
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
Assert.True(instance.Build(new[]{ComputeContainerConfig}, new [] { logs }, null, out var outputs));
Assert.Contains(logs.Messages, m => m.Message?.Contains("'ContainerImageName' was not a valid container image name, it was normalized to 'dotnet-testimage'") == true);
Assert.Contains(logs.Messages, m => m.Message?.Contains("'ContainerRepository' was not a valid container image name, it was normalized to 'dotnet-testimage'") == true);
}
[DockerAvailableFact]
@ -72,7 +72,7 @@ public class ParseContainerPropertiesTests
var (project, logs, d) = ProjectInitializer.InitProject(new () {
[ContainerBaseImage] = "mcr.microsoft.com/dotnet/runtime:7.0",
[ContainerRegistry] = "localhost:5010",
[ContainerImageName] = "dotnet/testimage",
[ContainerRepository] = "dotnet/testimage",
[ContainerImageTag] = "5 0"
});
using var _ = d;
@ -89,7 +89,7 @@ public class ParseContainerPropertiesTests
var (project, logs, d) = ProjectInitializer.InitProject(new () {
[ContainerBaseImage] = "mcr.microsoft.com/dotnet/runtime:7.0",
[ContainerRegistry] = "localhost:5010",
[ContainerImageName] = "dotnet/testimage",
[ContainerRepository] = "dotnet/testimage",
[ContainerImageTag] = "5.0",
[ContainerImageTags] = "latest;oldest"
});

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

@ -31,6 +31,21 @@ public class TargetsTests
}
}
[Fact]
public void CanDeferToContainerImageNameWhenPresent() {
var customImageName = "my-container-app";
var (project, logger, d) = ProjectInitializer.InitProject(new()
{
[ContainerImageName] = customImageName
});
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
instance.Build(new[] { ComputeContainerConfig }, new []{ logger });
logger.Warnings.Should().HaveCount(1, "a warning for the use of the old ContainerImageName property should have been created");
logger.Warnings[0].Code.Should().Be(KnownStrings.ErrorCodes.CONTAINER003);
Assert.Equal(customImageName, instance.GetPropertyValue(ContainerRepository));
}
[InlineData("WebApplication44", "webapplication44", true)]
[InlineData("friendly-suspicious-alligator", "friendly-suspicious-alligator", true)]
[InlineData("*friendly-suspicious-alligator", "", false)]
@ -39,14 +54,14 @@ public class TargetsTests
[Theory]
public void CanNormalizeInputContainerNames(string projectName, string expectedContainerImageName, bool shouldPass)
{
var (project, _, d) = ProjectInitializer.InitProject(new()
var (project, logger, d) = ProjectInitializer.InitProject(new()
{
[AssemblyName] = projectName
}, projectName: $"{nameof(CanNormalizeInputContainerNames)}_{projectName}_{expectedContainerImageName}_{shouldPass}");
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
instance.Build(new[] { ComputeContainerConfig }, null, null, out var outputs).Should().Be(shouldPass, "Build should have succeeded");
Assert.Equal(expectedContainerImageName, instance.GetPropertyValue(ContainerImageName));
instance.Build(new[] { ComputeContainerConfig }, new [] { logger }, null, out var outputs).Should().Be(shouldPass, "Build should have succeeded");
Assert.Equal(expectedContainerImageName, instance.GetPropertyValue(ContainerRepository));
}
[InlineData("7.0.100", true)]
@ -58,16 +73,25 @@ public class TargetsTests
[Theory]
public void CanWarnOnInvalidSDKVersions(string sdkVersion, bool isAllowed)
{
var (project, _, d) = ProjectInitializer.InitProject(new()
var (project, logger, d) = ProjectInitializer.InitProject(new()
{
["NETCoreSdkVersion"] = sdkVersion,
["PublishProfile"] = "DefaultContainer"
}, projectName: $"{nameof(CanWarnOnInvalidSDKVersions)}_{sdkVersion}_{isAllowed}");
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
instance.Build(new[]{"_ContainerVerifySDKVersion"}, new[] { logger }, null, out var outputs).Should().Be(isAllowed);
var derivedIsAllowed = Boolean.Parse(project.GetProperty("_IsSDKContainerAllowedVersion").EvaluatedValue);
// var buildResult = instance.Build(new[]{"_ContainerVerifySDKVersion"}, null, null, out var outputs);
derivedIsAllowed.Should().Be(isAllowed, $"SDK version {(isAllowed ? "should" : "should not")} have been allowed ");
if (isAllowed)
{
logger.Errors.Should().HaveCount(0, "an error should not have been created");
derivedIsAllowed.Should().Be(true, "SDK version {0} should have been allowed", sdkVersion);
}
else
{
logger.Errors.Should().HaveCount(1, "an error should have been created").And.Satisfy(error => error.Code == KnownStrings.ErrorCodes.CONTAINER002);
derivedIsAllowed.Should().Be(false, "SDK version {0} should not have been allowed", sdkVersion);
}
}
[InlineData(true)]
@ -75,13 +99,13 @@ public class TargetsTests
[Theory]
public void GetsConventionalLabelsByDefault(bool shouldEvaluateLabels)
{
var (project, _, d) = ProjectInitializer.InitProject(new()
var (project, logger, d) = ProjectInitializer.InitProject(new()
{
[ContainerGenerateLabels] = shouldEvaluateLabels.ToString()
}, projectName: $"{nameof(GetsConventionalLabelsByDefault)}_{shouldEvaluateLabels}");
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
instance.Build(new[] { ComputeContainerConfig }, null, null, out var outputs).Should().BeTrue("Build should have succeeded");
instance.Build(new[] { ComputeContainerConfig }, new [] { logger }, null, out var outputs).Should().BeTrue("Build should have succeeded");
if (shouldEvaluateLabels)
{
instance.GetItems(ContainerLabel).Should().NotBeEmpty("Should have evaluated some labels by default");
@ -110,7 +134,7 @@ public class TargetsTests
}, projectName: $"{nameof(ShouldNotIncludeSourceControlLabelsUnlessUserOptsIn)}_{includeSourceControl}");
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
instance.Build(new[] { ComputeContainerConfig }, null, null, out var outputs).Should().BeTrue("Build should have succeeded but failed due to {0}", String.Join("\n", logger.AllMessages));
instance.Build(new[] { ComputeContainerConfig }, new [] { logger }, null, out var outputs).Should().BeTrue("Build should have succeeded but failed due to {0}", String.Join("\n", logger.AllMessages));
var labels = instance.GetItems(ContainerLabel);
if (includeSourceControl)
{
@ -156,7 +180,7 @@ public class TargetsTests
}, projectName: $"{nameof(CanComputeTagsForSupportedSDKVersions)}_{sdkVersion}_{tfm}_{expectedTag}");
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
instance.Build(new[]{"_ComputeContainerBaseImageTag"}, null, null, out var outputs).Should().BeTrue(String.Join(Environment.NewLine, logger.Errors));
instance.Build(new[]{"_ComputeContainerBaseImageTag"}, new [] { logger }, null, out var outputs).Should().BeTrue(String.Join(Environment.NewLine, logger.Errors));
var computedTag = instance.GetProperty("_ContainerBaseImageTag").EvaluatedValue;
computedTag.Should().Be(expectedTag);
}
@ -176,10 +200,10 @@ public class TargetsTests
["TargetFrameworkVersion"] = tfm,
["TargetFramework"] = "net" + tfm.TrimStart('v'),
["ContainerRuntimeIdentifier"] = rid
}, projectName: $"{nameof(CanComputeTagsForSupportedSDKVersions)}_{tfm}_{rid}_{expectedUser}");
}, projectName: $"{nameof(CanComputeContainerUser)}_{tfm}_{rid}_{expectedUser}");
using var _ = d;
var instance = project.CreateProjectInstance(global::Microsoft.Build.Execution.ProjectInstanceSettings.None);
instance.Build(new[]{ComputeContainerConfig}, null, null, out var outputs).Should().BeTrue(String.Join(Environment.NewLine, logger.Errors));
instance.Build(new[]{ComputeContainerConfig}, new [] { logger }, null, out var outputs).Should().BeTrue(String.Join(Environment.NewLine, logger.Errors));
var computedTag = instance.GetProperty("ContainerUser")?.EvaluatedValue;
computedTag.Should().Be(expectedUser);
}

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

@ -167,6 +167,241 @@ namespace ManifestReaderTests
"ios: 18.0.1/7.0.400");
}
[Fact]
public void ItUsesManifestsFromWorkloadSet()
{
Initialize("8.0.200");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2-rc.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200-rc.1", "maui", "15.0.1-preview.123", true);
CreateMockManifest(_manifestRoot, "8.0.200-rc.2", "maui", "15.0.1-rc.456", true);
CreateMockManifest(_manifestRoot, "8.0.200", "maui", "15.0.1", true);
CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.200", """
{
"ios": "11.0.2/8.0.100",
"android": "33.0.2-rc.1/8.0.200",
"maui": "15.0.1-rc.456/8.0.200-rc.2"
}
""");
var sdkDirectoryWorkloadManifestProvider
= new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null);
GetManifestContents(sdkDirectoryWorkloadManifestProvider)
.Should()
.BeEquivalentTo("ios: 11.0.2/8.0.100", "android: 33.0.2-rc.1/8.0.200", "maui: 15.0.1-rc.456/8.0.200-rc.2");
}
[Fact]
public void ItUsesLatestWorkloadSet()
{
Initialize("8.0.200");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.201", """
{
"ios": "11.0.2/8.0.100"
}
""");
CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.202", """
{
"ios": "12.0.1/8.0.200"
}
""");
var sdkDirectoryWorkloadManifestProvider
= new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null);
GetManifestContents(sdkDirectoryWorkloadManifestProvider)
.Should()
.BeEquivalentTo("ios: 12.0.1/8.0.200");
}
[Fact]
public void ItUsesLatestManifestThatIsNotInWorkloadSet()
{
Initialize("8.0.200");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2-rc.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200-rc.1", "maui", "15.0.1-preview.123", true);
CreateMockManifest(_manifestRoot, "8.0.200-rc.2", "maui", "15.0.1-rc.456", true);
CreateMockManifest(_manifestRoot, "8.0.200", "maui", "15.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "maui", "15.0.2", true);
CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.200", """
{
"ios": "11.0.2/8.0.100",
"android": "33.0.2-rc.1/8.0.200"
}
""");
var sdkDirectoryWorkloadManifestProvider
= new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null);
GetManifestContents(sdkDirectoryWorkloadManifestProvider)
.Should()
.BeEquivalentTo("ios: 11.0.2/8.0.100", "android: 33.0.2-rc.1/8.0.200", "maui: 15.0.2/8.0.200");
}
[Fact]
public void ItFallsBackForManifestNotInWorkloadSet()
{
Initialize("8.0.200");
var knownWorkloadsFilePath = Path.Combine(_fakeDotnetRootDirectory, "sdk", "8.0.201", "IncludedWorkloadManifests.txt");
Directory.CreateDirectory(Path.GetDirectoryName(knownWorkloadsFilePath)!);
File.WriteAllText(knownWorkloadsFilePath, "android\nios\nmaui");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "android", "33.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "android", "33.0.2-rc.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "android", "33.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200-rc.1", "maui", "15.0.1-preview.123", true);
CreateMockManifest(_manifestRoot, "8.0.200-rc.2", "maui", "15.0.1-rc.456", true);
CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.201", """
{
"ios": "11.0.2/8.0.100"
}
""");
var sdkDirectoryWorkloadManifestProvider
= new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.201", userProfileDir: null);
GetManifestContents(sdkDirectoryWorkloadManifestProvider)
.Should()
.BeEquivalentTo("ios: 11.0.2/8.0.100", "android: 33.0.2/8.0.100", "maui: 15.0.1-rc.456/8.0.200-rc.2");
}
[Fact]
public void ItThrowsIfWorkloadSetHasInvalidVersion()
{
Initialize("8.0.200");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.200.1", """
{
"ios": "11.0.2/8.0.100"
}
""");
Assert.Throws<FormatException>(() => new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null));
}
[Fact]
public void ItThrowsIfManifestFromWorkloadSetIsNotFound()
{
Initialize("8.0.200");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockWorkloadSet(_manifestRoot, "8.0.200", "8.0.200", """
{
"ios": "12.0.2/8.0.200"
}
""");
var sdkDirectoryWorkloadManifestProvider
= new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null);
Assert.Throws<FileNotFoundException>(() => GetManifestContents(sdkDirectoryWorkloadManifestProvider).ToList());
}
[Fact]
public void WorkloadSetCanIncludeMultipleJsonFiles()
{
Initialize("8.0.200");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2-rc.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2", true);
var workloadSetDirectory = Path.Combine(_manifestRoot, "8.0.200", "workloadsets", "8.0.200");
Directory.CreateDirectory(workloadSetDirectory);
File.WriteAllText(Path.Combine(workloadSetDirectory, "1.workloadset.json"), """
{
"ios": "11.0.2/8.0.100"
}
""");
File.WriteAllText(Path.Combine(workloadSetDirectory, "2.workloadset.json"), """
{
"android": "33.0.2-rc.1/8.0.200"
}
""");
var sdkDirectoryWorkloadManifestProvider
= new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null);
GetManifestContents(sdkDirectoryWorkloadManifestProvider)
.Should()
.BeEquivalentTo("ios: 11.0.2/8.0.100", "android: 33.0.2-rc.1/8.0.200");
}
[Fact]
public void ItThrowsExceptionIfWorkloadSetJsonFilesHaveDuplicateManifests()
{
Initialize("8.0.200");
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.100", "ios", "11.0.2", true);
CreateMockManifest(_manifestRoot, "8.0.200", "ios", "12.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2-rc.1", true);
CreateMockManifest(_manifestRoot, "8.0.200", "android", "33.0.2", true);
var workloadSetDirectory = Path.Combine(_manifestRoot, "8.0.200", "workloadsets", "8.0.200");
Directory.CreateDirectory(workloadSetDirectory);
File.WriteAllText(Path.Combine(workloadSetDirectory, "1.workloadset.json"), """
{
"ios": "11.0.2/8.0.100"
}
""");
File.WriteAllText(Path.Combine(workloadSetDirectory, "2.workloadset.json"), """
{
"android": "33.0.2-rc.1/8.0.200",
"ios": "11.0.2/8.0.100"
}
""");
Assert.Throws<ArgumentException>(() =>
new SdkDirectoryWorkloadManifestProvider(sdkRootPath: _fakeDotnetRootDirectory, sdkVersion: "8.0.200", userProfileDir: null));
}
[Fact]
public void ItShouldReturnManifestsFromTestHook()
{
@ -456,6 +691,16 @@ Microsoft.Net.Workload.Emscripten.net7"
File.WriteAllText(Path.Combine(manifestDirectory, "WorkloadManifest.json"), $"{manifestId}: {manifestVersion}/{featureBand}");
}
private void CreateMockWorkloadSet(string manifestRoot, string featureBand, string workloadSetVersion, string workloadSetContents)
{
var workloadSetDirectory = Path.Combine(manifestRoot, featureBand, "workloadsets", workloadSetVersion);
if (!Directory.Exists(workloadSetDirectory))
{
Directory.CreateDirectory(workloadSetDirectory);
}
File.WriteAllText(Path.Combine(workloadSetDirectory, "workloadset.workloadset.json"), workloadSetContents);
}
[Fact]
public void ItShouldIgnoreManifestsNotFoundInFallback()
{

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

@ -22,7 +22,7 @@ public class ParserTests
"MyBaseRegistry",
command.BaseImageNameOption.Aliases.First(),
"MyBaseImageName",
command.ImageNameOption.Aliases.First(),
command.RepositoryOption.Aliases.First(),
"MyImageName",
command.WorkingDirectoryOption.Aliases.First(),
"MyWorkingDirectory",
@ -65,7 +65,7 @@ public class ParserTests
"MyBaseRegistry",
command.BaseImageNameOption.Aliases.First(),
"MyBaseImageName",
command.ImageNameOption.Aliases.First(),
command.RepositoryOption.Aliases.First(),
"MyImageName",
command.WorkingDirectoryOption.Aliases.First(),
"MyWorkingDirectory",
@ -101,7 +101,7 @@ public class ParserTests
"MyBaseRegistry",
command.BaseImageNameOption.Aliases.First(),
"MyBaseImageName",
command.ImageNameOption.Aliases.First(),
command.RepositoryOption.Aliases.First(),
"MyImageName",
command.WorkingDirectoryOption.Aliases.First(),
"MyWorkingDirectory",
@ -133,7 +133,7 @@ public class ParserTests
"MyBaseRegistry",
command.BaseImageNameOption.Aliases.First(),
"MyBaseImageName",
command.ImageNameOption.Aliases.First(),
command.RepositoryOption.Aliases.First(),
"MyImageName",
command.WorkingDirectoryOption.Aliases.First(),
"MyWorkingDirectory",
@ -177,7 +177,7 @@ public class ParserTests
"MyBaseRegistry",
command.BaseImageNameOption.Aliases.First(),
"MyBaseImageName",
command.ImageNameOption.Aliases.First(),
command.RepositoryOption.Aliases.First(),
"MyImageName",
command.WorkingDirectoryOption.Aliases.First(),
"MyWorkingDirectory",
@ -222,7 +222,7 @@ public class ParserTests
"MyBaseRegistry",
command.BaseImageNameOption.Aliases.First(),
"MyBaseImageName",
command.ImageNameOption.Aliases.First(),
command.RepositoryOption.Aliases.First(),
"MyImageName",
command.WorkingDirectoryOption.Aliases.First(),
"MyWorkingDirectory",

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

@ -340,7 +340,7 @@ namespace Microsoft.DotNet.Cli.Workload.Update.Tests
updateCommand.Execute();
_reporter.Lines.Count().Should().Be(3);
string.Join("", _reporter.Lines).Should().Contain("SampleManifest");
string.Join("", _reporter.Lines).Should().Contain("samplemanifest");
}
[Theory]
@ -454,7 +454,13 @@ namespace Microsoft.DotNet.Cli.Workload.Update.Tests
var installer = includeInstalledPacks ?
new MockPackWorkloadInstaller(failingWorkload, failingPack, installedWorkloads: installedWorkloads, installedPacks: installedPacks) :
new MockPackWorkloadInstaller(failingWorkload, failingPack, installedWorkloads: installedWorkloads);
var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(new[] { _manifestPath }), dotnetRoot);
var copiedManifestFolder = Path.Combine(dotnetRoot, "sdk-manifests", new SdkFeatureBand(sdkVersion).ToString(), "SampleManifest");
Directory.CreateDirectory(copiedManifestFolder);
var copiedManifestFile = Path.Combine(copiedManifestFolder, "WorkloadManifest.json");
File.Copy(_manifestPath, copiedManifestFile);
var workloadResolver = WorkloadResolver.CreateForTests(new MockManifestProvider(new[] { copiedManifestFile }), dotnetRoot);
installer.WorkloadResolver = workloadResolver;
var nugetDownloader = new MockNuGetPackageDownloader(dotnetRoot);
var manifestUpdater = new MockWorkloadManifestUpdater(manifestUpdates, _manifestPath);