Skip to content

Commit

Permalink
Bug #559: PublishContainer Appends "dotnet <Target>.dll" to ENTRYPOIN…
Browse files Browse the repository at this point in the history
…T for Self Contained Builds

* Fixed existing integration test that tested that ContainerEntryPoint can be deferred
  (it wasn't actually testing anything, due to a bug in the test)
* Changed the test to test that we defer ContainerAppCommand instead
  (ContainerEntryPoint is not deferred anymore on .net 8)
* Added runtime identifier dimension to the test (linux vs windows)
* Fixed integration test ProjectInitializer to take into account Windows vs *nix
  when setting executable extension (.exe or nothing)
* Fixed Microsoft.NET.Build.Containers.targets so that the behaviour is as expected on
  both Windows and linux containers
  • Loading branch information
erikbra committed May 9, 2024
1 parent 8a47026 commit 3647099
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public static class Properties
public static readonly string ContainerImageTags = nameof(ContainerImageTags);
public static readonly string ContainerWorkingDirectory = nameof(ContainerWorkingDirectory);
public static readonly string ContainerEntrypoint = nameof(ContainerEntrypoint);
public static readonly string ContainerAppCommand = nameof(ContainerAppCommand);
public static readonly string UseAppHost = nameof(UseAppHost);
public static readonly string ContainerLabel = nameof(ContainerLabel);
public static readonly string SelfContained = nameof(SelfContained);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,10 @@

<ItemGroup Label="AppCommand Assignment" Condition="'$(ContainerAppCommandInstruction)' != 'None'">
<!-- For self-contained, invoke the native executable as a single arg -->
<ContainerAppCommand Condition="'$(ContainerAppCommand)' == '' and '$(_ContainerIsSelfContained)' == 'true' and !$(_ContainerIsTargetingWindows)" Include="$(ContainerWorkingDirectory)/$(AssemblyName)$(_NativeExecutableExtension)" />
<ContainerAppCommand Condition="'$(ContainerAppCommand)' == '' and '$(_ContainerIsSelfContained)' == 'true' and $(_ContainerIsTargetingWindows)" Include="$(AssemblyName)$(_NativeExecutableExtension)" />
<ContainerAppCommand Condition="'$(ContainerAppCommand)' == '' and $(_ContainerIsSelfContained)" Include="$(ContainerWorkingDirectory)/$(AssemblyName)$(_NativeExecutableExtension)" />

<!-- For non self-contained, invoke `dotnet` `app.dll` as separate args -->
<ContainerAppCommand Condition="'$(ContainerAppCommand)' == ''" Include="dotnet;$(TargetFileName)" />
<ContainerAppCommand Condition="'$(ContainerAppCommand)' == '' and !$(_ContainerIsSelfContained)" Include="dotnet;$(ContainerWorkingDirectory)/$(TargetFileName)" />
</ItemGroup>

<!-- We only set a default user when the base image is Microsoft-authored, and we're targeting a version of those images that supports a nonroot user -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Runtime.CompilerServices;
using Microsoft.Build.Evaluation;
using Microsoft.Build.Framework;
using static Microsoft.NET.Build.Containers.KnownStrings.Properties;

namespace Microsoft.NET.Build.Containers.IntegrationTests;

Expand Down Expand Up @@ -44,7 +45,7 @@ public static (Project, CapturingLogger, IDisposable) InitProject(Dictionary<str

props["TargetFrameworkIdentifier"] = ".NETCoreApp";
props["TargetFramework"] = "net7.0";
props["_NativeExecutableExtension"] = ".exe"; //TODO: windows/unix split here
props["_NativeExecutableExtension"] = ContainerIsTargetingWindows(bonusProps) ? ".exe" : "";
props["Version"] = "1.0.0"; // TODO: need to test non-compliant version strings here
props["NETCoreSdkVersion"] = "7.0.100"; // TODO: float this to current SDK?
// test setup parameters so that we can load the props/targets/tasks
Expand Down Expand Up @@ -98,4 +99,8 @@ public static (Project, CapturingLogger, IDisposable) InitProject(Dictionary<str
}
return (project, logs, collection);
}

private static bool ContainerIsTargetingWindows(Dictionary<string, string> bonusProps)
=> new [] {ContainerRuntimeIdentifier, RuntimeIdentifier}
.Any(key => bonusProps.TryGetValue(key, out var rid) && rid.StartsWith("win"));
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,36 @@ namespace Microsoft.NET.Build.Containers.Targets.IntegrationTests;
[Collection(nameof(MSBuildCollection))]
public class TargetsTests
{
[InlineData("SelfContained", true, "/app/foo.exe")]
[InlineData("SelfContained", false, "dotnet", "/app/foo.dll")]
[InlineData("PublishSelfContained", true, "/app/foo.exe")]
[InlineData("PublishSelfContained", false, "dotnet", "/app/foo.dll")]
[InlineData("win", "SelfContained", true, "C:/app/foo.exe")]
[InlineData("win", "SelfContained", false, "dotnet", "C:/app/foo.dll")]
[InlineData("win", "PublishSelfContained", true, "C:/app/foo.exe")]
[InlineData("win", "PublishSelfContained", false, "dotnet", "C:/app/foo.dll")]
[InlineData("linux", "SelfContained", true, "/app/foo")]
[InlineData("linux", "SelfContained", false, "dotnet", "/app/foo.dll")]
[InlineData("linux", "PublishSelfContained", true, "/app/foo")]
[InlineData("linux", "PublishSelfContained", false, "dotnet", "/app/foo.dll")]
[Theory]
public void CanDeferEntrypoint(string selfContainedPropertyName, bool selfContainedPropertyValue, params string[] entrypointArgs)
public void CanDeferContainerAppCommand(
string rid,
string prop,
bool value,
params string[] expectedAppCommandArgs)
{
var (project, _, d) = ProjectInitializer.InitProject(new()
{
[selfContainedPropertyName] = selfContainedPropertyValue.ToString()
}, projectName: $"{nameof(CanDeferEntrypoint)}_{selfContainedPropertyName}_{selfContainedPropertyValue}_{string.Join("_", entrypointArgs)}");
[prop] = value.ToString(),
[ContainerRuntimeIdentifier] = rid,

}, projectName: $"{nameof(CanDeferContainerAppCommand)}_{prop}_{value}_{string.Join("_", expectedAppCommandArgs)}");
using var _ = d;
Assert.True(project.Build(ComputeContainerConfig));
var computedEntrypointArgs = project.GetItems(ContainerEntrypoint).Select(i => i.EvaluatedInclude).ToArray();
foreach (var (First, Second) in entrypointArgs.Zip(computedEntrypointArgs))
{
Assert.Equal(First, Second);
}
var instance = project.CreateProjectInstance(ProjectInstanceSettings.None);
Assert.True(instance.Build([ ComputeContainerConfig ], []));
var computedAppCommand = instance.GetItems(ContainerAppCommand).Select(i => i.EvaluatedInclude);

// The test was not testing anything previously, as the list returned was zero length,
// and the Zip didn't yield any results.
// So, to make sure we actually test something, we check that we actually get the expected collection.
computedAppCommand.Should().BeEquivalentTo(expectedAppCommandArgs);
}

[Fact]
Expand Down

0 comments on commit 3647099

Please sign in to comment.