diff --git a/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs b/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs
index bc68b412d7e4..a81d91cea00b 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/KnownStrings.cs
@@ -8,6 +8,8 @@ internal static class KnownStrings
public static class Properties
{
public static readonly string ContainerBaseImage = nameof(ContainerBaseImage);
+ public static readonly string ContainerFamily = nameof(ContainerFamily);
+ public static readonly string _ContainerBaseImageTag = nameof(_ContainerBaseImageTag);
public static readonly string ContainerRegistry = nameof(ContainerRegistry);
/// Note that this is deprecated in favor of
public static readonly string ContainerImageName = nameof(ContainerImageName);
@@ -22,6 +24,8 @@ public static class Properties
public static readonly string ContainerPort = nameof(ContainerPort);
public static readonly string ContainerEnvironmentVariable = nameof(ContainerEnvironmentVariable);
+ public static readonly string ComputeContainerBaseImage = nameof(ComputeContainerBaseImage);
+ public static readonly string _ComputeContainerBaseImageTag = nameof(_ComputeContainerBaseImageTag);
public static readonly string ComputeContainerConfig = nameof(ComputeContainerConfig);
public static readonly string AssemblyName = nameof(AssemblyName);
public static readonly string ContainerBaseRegistry = nameof(ContainerBaseRegistry);
diff --git a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt
index abc399bee64e..e6a9eae984b5 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt
+++ b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net472/PublicAPI.Unshipped.txt
@@ -24,6 +24,8 @@ Microsoft.NET.Build.Containers.PortType.udp = 1 -> Microsoft.NET.Build.Container
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.ComputedBaseImageTag.get -> string?
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.ComputeDotnetBaseImageTag() -> void
+Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.ContainerFamily.get -> string!
+Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.ContainerFamily.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.SdkVersion.get -> string!
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.SdkVersion.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.TargetFrameworkVersion.get -> string!
diff --git a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net8.0/PublicAPI.Unshipped.txt
index d51a607c56b9..77d32872c72e 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net8.0/PublicAPI.Unshipped.txt
+++ b/src/Containers/Microsoft.NET.Build.Containers/PublicAPI/net8.0/PublicAPI.Unshipped.txt
@@ -112,6 +112,8 @@ Microsoft.NET.Build.Containers.PortType
Microsoft.NET.Build.Containers.PortType.tcp = 0 -> Microsoft.NET.Build.Containers.PortType
Microsoft.NET.Build.Containers.PortType.udp = 1 -> Microsoft.NET.Build.Containers.PortType
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag
+Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.ContainerFamily.get -> string!
+Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.ContainerFamily.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.SdkVersion.get -> string!
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.SdkVersion.set -> void
Microsoft.NET.Build.Containers.Tasks.ComputeDotnetBaseImageTag.TargetFrameworkVersion.get -> string!
diff --git a/src/Containers/Microsoft.NET.Build.Containers/Tasks/ComputeDotnetBaseImageTag.cs b/src/Containers/Microsoft.NET.Build.Containers/Tasks/ComputeDotnetBaseImageTag.cs
index d0fdde5b930d..448daec0845b 100644
--- a/src/Containers/Microsoft.NET.Build.Containers/Tasks/ComputeDotnetBaseImageTag.cs
+++ b/src/Containers/Microsoft.NET.Build.Containers/Tasks/ComputeDotnetBaseImageTag.cs
@@ -25,6 +25,8 @@ public sealed class ComputeDotnetBaseImageTag : Microsoft.Build.Utilities.Task
[Required]
public string TargetFrameworkVersion { get; set; }
+ public string ContainerFamily { get; set; }
+
[Output]
public string? ComputedBaseImageTag { get; private set; }
@@ -32,6 +34,7 @@ public ComputeDotnetBaseImageTag()
{
SdkVersion = "";
TargetFrameworkVersion = "";
+ ContainerFamily = "";
}
public override bool Execute()
@@ -39,19 +42,24 @@ public override bool Execute()
if (SemanticVersion.TryParse(TargetFrameworkVersion, out var tfm) && tfm.Major < FirstVersionWithNewTaggingScheme)
{
ComputedBaseImageTag = $"{tfm.Major}.{tfm.Minor}";
- return true;
}
-
- if (SemanticVersion.TryParse(SdkVersion, out var version))
+ else if (SemanticVersion.TryParse(SdkVersion, out var version))
{
ComputedBaseImageTag = ComputeVersionInternal(version, tfm);
- return true;
}
else
{
Log.LogError(Resources.Strings.InvalidSdkVersion, SdkVersion);
- return false;
+ return !Log.HasLoggedErrors;
+ }
+
+ if (!string.IsNullOrWhiteSpace(ContainerFamily))
+ {
+ // for the inferred image tags, 'family' aka 'flavor' comes after the 'version' portion (including any preview/rc segments).
+ // so it's safe to just append here
+ ComputedBaseImageTag += $"-{ContainerFamily}";
}
+ return true;
}
diff --git a/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets b/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets
index 9c3d0b17e8d3..8a47d6795d5d 100644
--- a/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets
+++ b/src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets
@@ -32,7 +32,8 @@
+ TargetFrameworkVersion="$(_TargetFrameworkVersionWithoutV).0"
+ ContainerFamily="$(ContainerFamily)">
diff --git a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/TargetsTests.cs b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/TargetsTests.cs
index 7ed58d4a0df2..30f132f077f2 100644
--- a/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/TargetsTests.cs
+++ b/src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/TargetsTests.cs
@@ -222,4 +222,26 @@ public void WindowsUsersGetLinuxContainers(string sdkPortableRid, string expecte
var computedRid = instance.GetProperty(KnownStrings.Properties.ContainerRuntimeIdentifier)?.EvaluatedValue;
computedRid.Should().Be(expectedRid);
}
+
+ [InlineData("8.0.100", "v7.0", "", "7.0")]
+ [InlineData("8.0.100-preview.2", "v8.0", "", "8.0.0-preview.2")]
+ [InlineData("8.0.100-preview.2", "v8.0", "jammy", "8.0.0-preview.2-jammy")]
+ [InlineData("8.0.100-preview.2", "v8.0", "jammy-chiseled", "8.0.0-preview.2-jammy-chiseled")]
+ [InlineData("8.0.100-rc.2", "v8.0", "jammy-chiseled", "8.0.0-rc.2-jammy-chiseled")]
+ [InlineData("8.0.100", "v8.0", "jammy-chiseled", "8.0-jammy-chiseled")]
+ [Theory]
+ public void CanTakeContainerBaseFamilyIntoAccount(string sdkVersion, string tfmMajMin, string containerFamily, string expectedTag)
+ {
+ var (project, logger, d) = ProjectInitializer.InitProject(new()
+ {
+ ["NetCoreSdkVersion"] = sdkVersion,
+ ["TargetFrameworkVersion"] = tfmMajMin,
+ [KnownStrings.Properties.ContainerFamily] = containerFamily,
+ }, projectName: $"{nameof(CanTakeContainerBaseFamilyIntoAccount)}_{sdkVersion}_{tfmMajMin}_{containerFamily}_{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));
+ var computedBaseImageTag = instance.GetProperty(KnownStrings.Properties._ContainerBaseImageTag)?.EvaluatedValue;
+ computedBaseImageTag.Should().Be(expectedTag);
+ }
}