Skip to content

Commit d585d81

Browse files
authored
[release/8.0.4xx] Fix defaulting of which Runtime(s) to containerize that led to always publishing multiple containers (#46067)
2 parents 07b9ce2 + 44a6547 commit d585d81

File tree

2 files changed

+125
-16
lines changed

2 files changed

+125
-16
lines changed

src/Containers/packaging/build/Microsoft.NET.Build.Containers.targets

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,19 @@
3434
<Target Name="ComputeContainerBaseImage"
3535
Returns="$(ContainerBaseImage)">
3636
<PropertyGroup>
37-
<ContainerRuntimeIdentifiers Condition="'$(BuildingInsideVisualStudio)' != 'true' and '$(ContainerRuntimeIdentifiers)' == '' and '$(IsRidAgnostic)' != 'true'">$(RuntimeIdentifiers)</ContainerRuntimeIdentifiers>
3837
<!-- The Container RID should default to the RID used for the entire build (to ensure things run on the platform they are built for), but the user knows best and so should be able to set it explicitly.
3938
For builds that have a RID, we default to that RID. Otherwise, we default to the Linux RID matching the architecture of the currently-executing SDK. -->
40-
<ContainerRuntimeIdentifier Condition="'$(ContainerRuntimeIdentifier)' == '' and '$(ContainerRuntimeIdentifiers)' == '' and '$(IsRidAgnostic)' != 'true'">$(RuntimeIdentifier)</ContainerRuntimeIdentifier>
39+
<ContainerRuntimeIdentifier Condition="'$(ContainerRuntimeIdentifier)' == '' and '$(RuntimeIdentifier)' != ''">$(RuntimeIdentifier)</ContainerRuntimeIdentifier>
40+
<ContainerRuntimeIdentifiers Condition="'$(BuildingInsideVisualStudio)' != 'true' and '$(ContainerRuntimeIdentifiers)' == '' and '$(IsRidAgnostic)' != 'true'">$(RuntimeIdentifiers)</ContainerRuntimeIdentifiers>
4141
<ContainerRuntimeIdentifier Condition="'$(ContainerRuntimeIdentifier)' == '' and '$(ContainerRuntimeIdentifiers)' == ''">linux-$(NETCoreSdkPortableRuntimeIdentifier.Split('-')[1])</ContainerRuntimeIdentifier>
4242

4343
<_ContainerIsUsingMicrosoftDefaultImages Condition="'$(ContainerBaseImage)' == ''">true</_ContainerIsUsingMicrosoftDefaultImages>
4444
<_ContainerIsUsingMicrosoftDefaultImages Condition="'$(ContainerBaseImage)' != ''">false</_ContainerIsUsingMicrosoftDefaultImages>
4545
</PropertyGroup>
4646

4747
<ItemGroup>
48-
<_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifiers)" Condition="'$(ContainerRuntimeIdentifiers)' != ''" />
49-
<_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifier)" Condition="'$(ContainerRuntimeIdentifiers)' == ''" />
48+
<_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifier)" Condition="'$(ContainerRuntimeIdentifier)' != ''" />
49+
<_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifiers)" Condition="@(_TargetRuntimeIdentifiers->Count()) == 0" />
5050
</ItemGroup>
5151

5252
<ComputeDotnetBaseImageAndTag
@@ -297,9 +297,9 @@
297297

298298
<Target Name="_PublishMultiArchContainers" DependsOnTargets="$(PublishContainerDependsOn)" >
299299
<Error Text="ContainerArchiveOutputPath is invalid. It can only be a directory in multi-arch scenario because the runtime identifier is appended in the end of the filename."
300-
Condition="'$(ContainerArchiveOutputPath)' != '' and
301-
!$(ContainerArchiveOutputPath.EndsWith('/')) and
302-
!$(ContainerArchiveOutputPath.EndsWith('\\')) and
300+
Condition="'$(ContainerArchiveOutputPath)' != '' and
301+
!$(ContainerArchiveOutputPath.EndsWith('/')) and
302+
!$(ContainerArchiveOutputPath.EndsWith('\\')) and
303303
$(ContainerArchiveOutputPath.EndsWith('.tar.gz'))" />
304304

305305
<ItemGroup>
@@ -399,7 +399,14 @@
399399
Condition="'$(IsPublishable)' == 'true' AND '$(EnableSdkContainerSupport)' == 'true'">
400400
<PropertyGroup>
401401
<_IsMultiTFMBuild Condition="'$(TargetFrameworks)' != '' and '$(TargetFramework)' == ''">true</_IsMultiTFMBuild>
402-
<_IsMultiRIDBuild Condition="'$(BuildingInsideVisualStudio)' != 'true' and (('$(RuntimeIdentifiers)' != '' and '$(RuntimeIdentifier)' == '') or ('$(ContainerRuntimeIdentifiers)' != '' and '$(ContainerRuntimeIdentfier)' == ''))">true</_IsMultiRIDBuild>
402+
<!-- we are multi-RID if:
403+
* we have CRIDs and no CRID
404+
* we have RIDs and no (CRIDs or CRID or RID)
405+
-->
406+
<_HasCRIDsAndNoCRID Condition="'$(ContainerRuntimeIdentifiers)' != '' and '$(ContainerRuntimeIdentifier)' == ''">true</_HasCRIDsAndNoCRID>
407+
<_HasRIDs Condition="'$(RuntimeIdentifiers)' != ''">true</_HasRIDs>
408+
<_NoCRIDsOrCRIDorRID Condition="'$(ContainerRuntimeIdentifiers)' == '' and '$(ContainerRuntimeIdentifier)' == '' and '$(RuntimeIdentifier)' == ''">true</_NoCRIDsOrCRIDorRID>
409+
<_IsMultiRIDBuild Condition="'$(BuildingInsideVisualStudio)' != 'true' and ('$(_HasCRIDsAndNoCRID)' == true or ('$(_HasRIDs)' == 'true' and '$(_NoCRIDsOrCRIDorRID)' == 'true'))">true</_IsMultiRIDBuild>
403410
<_IsSingleRIDBuild Condition="'$(_IsMultiRIDBuild)' == ''">true</_IsSingleRIDBuild>
404411
</PropertyGroup>
405412

src/Tests/Microsoft.NET.Build.Containers.IntegrationTests/EndToEndTests.cs

Lines changed: 110 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ public async Task ApiEndToEndWithArchiveWritingAndLoad()
181181

182182
[DockerAvailableFact]
183183
public async Task TarballsHaveCorrectStructure()
184-
{
184+
{
185185
var archiveFile = Path.Combine(TestSettings.TestArtifactsDirectory,
186186
nameof(TarballsHaveCorrectStructure), "app.tar.gz");
187187

@@ -190,7 +190,7 @@ public async Task TarballsHaveCorrectStructure()
190190
await BuildDockerImageWithArciveDestinationAsync(archiveFile, ["latest"], nameof(TarballsHaveCorrectStructure));
191191

192192
await destinationReference.LocalRegistry!.LoadAsync(dockerImage, sourceReference, destinationReference, default).ConfigureAwait(false);
193-
193+
194194
Assert.True(File.Exists(archiveFile), $"File.Exists({archiveFile})");
195195

196196
CheckDockerTarballStructure(archiveFile);
@@ -778,6 +778,108 @@ public void EndToEndMultiArch_LocalRegistry()
778778
newProjectDir.Delete(true);
779779
}
780780

781+
[DockerAvailableFact]
782+
public void MultiArchStillAllowsSingleRID()
783+
{
784+
string imageName = NewImageName();
785+
string imageTag = "1.0";
786+
string qualifiedImageName = $"{imageName}:{imageTag}";
787+
788+
// Create a new console project
789+
DirectoryInfo newProjectDir = CreateNewProject("console");
790+
791+
// Run PublishContainer for multi-arch-capable, but single-arch actual
792+
CommandResult commandResult = new DotnetCommand(
793+
_testOutput,
794+
"publish",
795+
"/t:PublishContainer",
796+
// make it so the app is _able_ to target both linux TFMs
797+
"/p:RuntimeIdentifiers=\"linux-x64;linux-arm64\"",
798+
// and that it opts into to multi-targeting containers for both of those linux TFMs
799+
"/p:ContainerRuntimeIdentifiers=\"linux-x64;linux-arm64\"",
800+
// but then only actually publishes for one of them
801+
"/p:ContainerRuntimeIdentifier=linux-x64",
802+
$"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}",
803+
$"/p:ContainerRepository={imageName}",
804+
$"/p:ContainerImageTag={imageTag}",
805+
"/p:EnableSdkContainerSupport=true",
806+
"/bl")
807+
.WithWorkingDirectory(newProjectDir.FullName)
808+
.Execute();
809+
810+
// Check that the app was published for each RID,
811+
// images were created locally for each RID
812+
// and image index was NOT created
813+
commandResult.Should().Pass()
814+
// no rid-specific path because we didn't pass RuntimeIdentifier
815+
.And.NotHaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-x64"))
816+
.And.HaveStdOutContaining($"Pushed image '{qualifiedImageName}' to local registry")
817+
.And.NotHaveStdOutContaining("Pushed image index");
818+
819+
// Check that the containers can be run
820+
CommandResult processResultX64 = ContainerCli.RunCommand(
821+
_testOutput,
822+
"--rm",
823+
"--name",
824+
$"test-container-{imageName}",
825+
qualifiedImageName)
826+
.Execute();
827+
processResultX64.Should().Pass().And.HaveStdOut("Hello, World!");
828+
829+
// Cleanup
830+
newProjectDir.Delete(true);
831+
}
832+
833+
[DockerAvailableFact]
834+
public void MultiArchStillAllowsSingleRIDUsingJustRIDProperties()
835+
{
836+
string imageName = NewImageName();
837+
string imageTag = "1.0";
838+
string qualifiedImageName = $"{imageName}:{imageTag}";
839+
840+
// Create a new console project
841+
DirectoryInfo newProjectDir = CreateNewProject("console");
842+
843+
// Run PublishContainer for multi-arch-capable, but single-arch actual
844+
CommandResult commandResult = new DotnetCommand(
845+
_testOutput,
846+
"publish",
847+
"/t:PublishContainer",
848+
// make it so the app is _able_ to target both linux TFMs
849+
"/p:RuntimeIdentifiers=\"linux-x64;linux-arm64\"",
850+
// but then only actually publishes for one of them
851+
"-r", "linux-x64",
852+
$"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}",
853+
$"/p:ContainerRepository={imageName}",
854+
$"/p:ContainerImageTag={imageTag}",
855+
"/p:EnableSdkContainerSupport=true",
856+
"/bl")
857+
.WithWorkingDirectory(newProjectDir.FullName)
858+
.Execute();
859+
860+
// Check that the app was published for each RID,
861+
// images were created locally for each RID
862+
// and image index was NOT created
863+
commandResult.Should().Pass()
864+
.And.HaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-x64", configuration: "Release"))
865+
.And.NotHaveStdOutContaining(GetPublishArtifactsPath(newProjectDir.FullName, "linux-arm64", configuration: "Release"))
866+
.And.HaveStdOutContaining($"Pushed image '{qualifiedImageName}' to local registry")
867+
.And.NotHaveStdOutContaining("Pushed image index");
868+
869+
// Check that the containers can be run
870+
CommandResult processResultX64 = ContainerCli.RunCommand(
871+
_testOutput,
872+
"--rm",
873+
"--name",
874+
$"test-container-{imageName}-x64",
875+
qualifiedImageName)
876+
.Execute();
877+
processResultX64.Should().Pass().And.HaveStdOut("Hello, World!");
878+
879+
// Cleanup
880+
newProjectDir.Delete(true);
881+
}
882+
781883
private DirectoryInfo CreateNewProject(string template, [CallerMemberName] string callerMemberName = "")
782884
{
783885
DirectoryInfo newProjectDir = new DirectoryInfo(Path.Combine(TestSettings.TestArtifactsDirectory, callerMemberName));
@@ -798,8 +900,8 @@ private DirectoryInfo CreateNewProject(string template, [CallerMemberName] strin
798900
return newProjectDir;
799901
}
800902

801-
private string GetPublishArtifactsPath(string projectDir, string rid)
802-
=> Path.Combine(projectDir, "bin", "Debug", ToolsetInfo.CurrentTargetFramework, rid, "publish");
903+
private string GetPublishArtifactsPath(string projectDir, string rid, string configuration = "Debug")
904+
=> Path.Combine(projectDir, "bin", configuration, ToolsetInfo.CurrentTargetFramework, rid, "publish");
803905

804906
[DockerSupportsArchFact("linux/arm64")]
805907
public void EndToEndMultiArch_ArchivePublishing()
@@ -839,8 +941,8 @@ public void EndToEndMultiArch_ArchivePublishing()
839941
.And.HaveStdOutContaining($"Pushed image '{imageArm64}' to local archive at '{imageArm64Tarball}'")
840942
.And.NotHaveStdOutContaining("Pushed image index");
841943

842-
// Check that tarballs were created
843-
File.Exists(imageX64Tarball).Should().BeTrue();
944+
// Check that tarballs were created
945+
File.Exists(imageX64Tarball).Should().BeTrue();
844946
File.Exists(imageArm64Tarball).Should().BeTrue();
845947

846948
// Load the images from the tarballs
@@ -886,7 +988,7 @@ public void EndToEndMultiArch_RemoteRegistry()
886988

887989
// Create a new console project
888990
DirectoryInfo newProjectDir = CreateNewProject("console");
889-
991+
890992
// Run PublishContainer for multi-arch with ContainerRegistry
891993
CommandResult commandResult = new DotnetCommand(
892994
_testOutput,
@@ -1174,7 +1276,7 @@ public void EndToEndMultiArch_Labels()
11741276
// Run PublishContainer for multi-arch with ContainerGenerateLabels
11751277
new DotnetCommand(
11761278
_testOutput,
1177-
"build",
1279+
"publish",
11781280
"/t:PublishContainer",
11791281
"/p:RuntimeIdentifiers=\"linux-x64;linux-arm64\"",
11801282
$"/p:ContainerBaseImage={DockerRegistryManager.FullyQualifiedBaseImageAspNet}",

0 commit comments

Comments
 (0)