Skip to content

[release/9.0.3xx] make container app/entrypoint argument defaults only happen on the RID-specific builds, not the outer RID-less build #47458

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ public static class Properties

public static readonly string ComputeContainerBaseImage = nameof(ComputeContainerBaseImage);
public static readonly string ComputeContainerConfig = nameof(ComputeContainerConfig);
public static readonly string _ComputeContainerExecutionArgs = nameof(_ComputeContainerExecutionArgs);
public static readonly string AssemblyName = nameof(AssemblyName);
public static readonly string ContainerBaseRegistry = nameof(ContainerBaseRegistry);
public static readonly string ContainerBaseName = nameof(ContainerBaseName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@
<ContainerRuntimeIdentifier Condition="'$(ContainerRuntimeIdentifier)' == '' and '$(RuntimeIdentifier)' != ''">$(RuntimeIdentifier)</ContainerRuntimeIdentifier>
<ContainerRuntimeIdentifiers Condition="'$(BuildingInsideVisualStudio)' != 'true' and '$(ContainerRuntimeIdentifiers)' == '' and '$(IsRidAgnostic)' != 'true'">$(RuntimeIdentifiers)</ContainerRuntimeIdentifiers>
<ContainerRuntimeIdentifier Condition="'$(ContainerRuntimeIdentifier)' == '' and '$(ContainerRuntimeIdentifiers)' == ''">linux-$(NETCoreSdkPortableRuntimeIdentifier.Split('-')[1])</ContainerRuntimeIdentifier>

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

<ItemGroup>
Expand Down Expand Up @@ -97,27 +94,6 @@
<!-- Only default a tag name if no tag names at all are provided -->
<ContainerImageTag Condition="'$(ContainerImageTag)' == '' and '$(ContainerImageTags)' == ''">latest</ContainerImageTag>
<ContainerImageTag Condition="'$(AutoGenerateImageTag)' == 'true' and '$(ContainerImageTags)' == ''">$([System.DateTime]::UtcNow.ToString('yyyyMMddhhmmss'))</ContainerImageTag>

<!-- 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.
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. -->
<_ContainerIsTargetingWindows>false</_ContainerIsTargetingWindows>
<_ContainerIsTargetingWindows Condition="$(ContainerRuntimeIdentifier.StartsWith('win'))">true</_ContainerIsTargetingWindows>

<!-- Set the WorkingDirectory depending on the RID -->
<ContainerWorkingDirectory Condition="'$(ContainerWorkingDirectory)' == '' and !$(_ContainerIsTargetingWindows)">/app/</ContainerWorkingDirectory>
<ContainerWorkingDirectory Condition="'$(ContainerWorkingDirectory)' == '' and $(_ContainerIsTargetingWindows)">C:\app\</ContainerWorkingDirectory>
</PropertyGroup>

<ItemGroup Label="AppCommand Assignment" Condition="'$(ContainerAppCommandInstruction)' != 'None'">
<!-- For self-contained, invoke the native executable as a single arg -->
<ContainerAppCommand Condition="@(ContainerAppCommand->Count()) == 0 and $(_ContainerIsSelfContained)" Include="$(ContainerWorkingDirectory)$(AssemblyName)$(_NativeExecutableExtension)" />
<!-- For non self-contained, invoke `dotnet` `app.dll` as separate args -->
<ContainerAppCommand Condition="@(ContainerAppCommand->Count()) == 0 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 -->
<PropertyGroup Label="ContainerUser Assignment" Condition="$(_ContainerIsUsingMicrosoftDefaultImages) and $(_ContainerIsTargetingNet8TFM) and '$(ContainerUser)' == ''">
<ContainerUser Condition="$(_ContainerIsTargetingWindows)">ContainerUser</ContainerUser>
</PropertyGroup>

<ParseContainerProperties FullyQualifiedBaseImageName="$(ContainerBaseImage)"
Expand Down Expand Up @@ -184,7 +160,7 @@
</ItemGroup>

<!-- These sourcelink-derived properties are only allowed to flow to generated artifacts if `PublishRepositoryUrl` is set as a user signal for opt-in.
In addition, the 'nice' property names are currently set by NuGet Pack targets and so we have to use the private/generic names here. -->
In addition, the 'nice' property names are currently set by NuGet Pack targets and so we have to use the private/generic names here. -->
<PropertyGroup Label="Source control label assignment" Condition="'$(ContainerGenerateLabels)' == 'true' and '$(PublishRepositoryUrl)' == 'true'">
<!-- Sourcelink gives us the .git suffix, but scanning tools aren't looking for that so we trim it off here. -->
<_TrimmedRepositoryUrl Condition="'$(RepositoryType)' == 'git' and '$(PrivateRepositoryUrl)' != '' and $(PrivateRepositoryUrl.EndsWith('.git'))">$(PrivateRepositoryUrl.Substring(0, $(PrivateRepositoryUrl.LastIndexOf('.git'))))</_TrimmedRepositoryUrl>
Expand All @@ -204,6 +180,36 @@
</PublishContainerDependsOn>
</PropertyGroup>

<!-- These args are relevant to container execution and are per-RID by nature. Therefore they're a direct dependency of the _PublishSingleContainer
target and not computed at the outer layer. -->
<Target Name="_ComputeContainerExecutionArgs">
<PropertyGroup>
<!-- 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.
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. -->
<_ContainerIsTargetingWindows>false</_ContainerIsTargetingWindows>
<_ContainerIsTargetingWindows Condition="$(ContainerRuntimeIdentifier.StartsWith('win'))">true</_ContainerIsTargetingWindows>

<!-- Set the WorkingDirectory depending on the RID -->
<ContainerWorkingDirectory Condition="'$(ContainerWorkingDirectory)' == '' and !$(_ContainerIsTargetingWindows)">/app/</ContainerWorkingDirectory>
<ContainerWorkingDirectory Condition="'$(ContainerWorkingDirectory)' == '' and $(_ContainerIsTargetingWindows)">C:\app\</ContainerWorkingDirectory>

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

<!-- 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 -->
<PropertyGroup Label="ContainerUser Assignment" Condition="$(_ContainerIsUsingMicrosoftDefaultImages) and $(_ContainerIsTargetingNet8TFM) and '$(ContainerUser)' == ''">
<ContainerUser Condition="$(_ContainerIsTargetingWindows)">ContainerUser</ContainerUser>
</PropertyGroup>

<ItemGroup Label="AppCommand Assignment" Condition="'$(ContainerAppCommandInstruction)' != 'None'">
<!-- For self-contained, invoke the native executable as a single arg -->
<ContainerAppCommand Condition="@(ContainerAppCommand->Count()) == 0 and $(_ContainerIsSelfContained)" Include="$(ContainerWorkingDirectory)$(AssemblyName)$(_NativeExecutableExtension)" />
<!-- For non self-contained, invoke `dotnet` `app.dll` as separate args -->
<ContainerAppCommand Condition="@(ContainerAppCommand->Count()) == 0 and !$(_ContainerIsSelfContained)" Include="dotnet;$(ContainerWorkingDirectory)$(TargetFileName)" />
</ItemGroup>
</Target>

<Target Name="_CheckContainersPackage" AfterTargets="Build">
<PropertyGroup>
<!-- facts to base on comparisons on -->
Expand Down Expand Up @@ -317,17 +323,9 @@
ContainerRegistry=$(ContainerRegistry);
_ContainerImageTags=@(ContainerImageTags, ';');
ContainerRepository=$(ContainerRepository);
ContainerWorkingDirectory=$(ContainerWorkingDirectory);
_ContainerEntrypoint=@(ContainerEntrypoint, ';');
_ContainerEntrypointArgs=@(ContainerEntrypointArgs, ';');
_ContainerAppCommand=@(ContainerAppCommand, ';');
_ContainerAppCommandArgs=@(ContainerAppCommandArgs, ';');
ContainerAppCommandInstruction=$(ContainerAppCommandInstruction);
_ContainerDefaultArgs=@(ContainerDefaultArgs, ';');
_ContainerLabel=@(ContainerLabel->'%(Identity):%(Value)');
_ContainerPort=@(ContainerPort->'%(Identity):%(Type)');
_ContainerEnvironmentVariables=@(ContainerEnvironmentVariable->'%(Identity):%(Value)');
ContainerUser=$(ContainerUser);
ContainerGenerateLabels=$(ContainerGenerateLabels);
ContainerGenerateLabelsImageBaseDigest=$(ContainerGenerateLabelsImageBaseDigest)
"/>
Expand Down Expand Up @@ -359,11 +357,6 @@
<ItemGroup>
<OriginalImageTags Include="$(_ContainerImageTags)"/>
<ContainerImageTags Include="@(OriginalImageTags->'%(Identity)-$(ContainerRuntimeIdentifier)')" />
<ContainerEntrypoint Include="$(_ContainerEntrypoint)"/>
<ContainerEntrypointArgs Include="$(_ContainerEntrypointArgs)"/>
<ContainerAppCommand Include="$(_ContainerAppCommand)"/>
<ContainerAppCommandArgs Include="$(_ContainerAppCommandArgs)"/>
<ContainerDefaultArgs Include="$(_ContainerDefaultArgs)"/>

<_ParsedContainerLabel
Condition="'$(_ContainerLabel)' != ':'"
Expand Down Expand Up @@ -417,5 +410,4 @@

<Error Condition="'$(_IsMultiTFMBuild)' == 'true'" Code="CONTAINERS0666" Text="Containers cannot be published for multiple TargetFrameworks at this time. Please specify a TargetFramework." />
</Target>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ public void CanDeferContainerAppCommand(
}, projectName: $"{nameof(CanDeferContainerAppCommand)}_{prop}_{value}_{string.Join("_", expectedAppCommandArgs)}");
using var _ = d;
var instance = project.CreateProjectInstance(ProjectInstanceSettings.None);
//Assert.True(instance.Build([ ComputeContainerConfig ], []));
instance.Build([ ComputeContainerConfig ], []);
instance.Build([ _ComputeContainerExecutionArgs ], []);
var computedAppCommand = instance.GetItems(ContainerAppCommand).Select(i => i.EvaluatedInclude);

// The test was not testing anything previously, as the list returned was zero length,
Expand All @@ -36,7 +35,6 @@ public void CanDeferContainerAppCommand(
computedAppCommand.Should().BeEquivalentTo(expectedAppCommandArgs);
}


public static TheoryData<string, string, bool, string[]> ContainerAppCommands()
{
char s = Path.DirectorySeparatorChar;
Expand Down Expand Up @@ -316,7 +314,7 @@ public void CanComputeContainerUser(string tfm, string rid, string? expectedUser
}, projectName: $"{nameof(CanComputeContainerUser)}_{tfm}_{rid}_{expectedUser}");
using var _ = d;
var instance = project.CreateProjectInstance(ProjectInstanceSettings.None);
instance.Build(new[] { ComputeContainerConfig }, new[] { logger }, null, out var outputs).Should().BeTrue(String.Join(Environment.NewLine, logger.Errors));
instance.Build(new[] { _ComputeContainerExecutionArgs }, new[] { logger }, null, out var outputs).Should().BeTrue(String.Join(Environment.NewLine, logger.Errors));
var computedTag = instance.GetProperty("ContainerUser")?.EvaluatedValue;
computedTag.Should().Be(expectedUser);
}
Expand Down