<Project>
  <PropertyGroup>
    <_IsSDKContainerAllowedVersion>false</_IsSDKContainerAllowedVersion>
    <!-- Anything newer than 7.0.100-preview.7 is supported -->
    <_IsSDKContainerAllowedVersion
        Condition="$([MSBuild]::VersionGreaterThan($(NetCoreSdkVersion), 7.0.100))
                       OR ( $([MSBuild]::VersionEquals($(NetCoreSdkVersion), 7.0.100))
                            AND (
                                 $(NETCoreSdkVersion.Contains('-preview.7'))
                                 OR $(NETCoreSdkVersion.Contains('-rc'))
                                 OR $(NETCoreSdkVersion.Contains('-')) == false
                                )
                          )">true</_IsSDKContainerAllowedVersion>
    <_ContainerIsTargetingNet8TFM>false</_ContainerIsTargetingNet8TFM>
    <_ContainerIsTargetingNet8TFM Condition="'$(TargetFrameworkIdentifier)' == '.NETCoreApp' And $([MSBuild]::VersionGreaterThanOrEquals($(_TargetFrameworkVersionWithoutV), '8.0'))">true</_ContainerIsTargetingNet8TFM>
    <_ContainerIsSelfContained>false</_ContainerIsSelfContained>
    <_ContainerIsSelfContained Condition="'$(SelfContained)' == 'true' or '$(PublishSelfContained)' == 'true'">true</_ContainerIsSelfContained>

    <EnableSdkContainerSupport Condition="'$(EnableSdkContainerSupport)' == '' and '$(OutputType)' != 'Library'" >true</EnableSdkContainerSupport>
  </PropertyGroup>

  <ItemGroup>
    <ProjectCapability Include="NetSdkOCIImageBuild" />
  </ItemGroup>

  <Target Name="_ContainerVerifySDKVersion"
      Condition="'$(WebPublishMethod)' == 'Container' or '$(PublishProfile)' == 'DefaultContainer'"
      BeforeTargets="AfterPublish">
    <!-- If the user has opted into container publishing via their own profile (WebPublishMethod = Container) or
            via the default Profile (PublishProfile = DefaultContainer), make sure they're on a supported SDK version.
            We do the explicit profile name check here because for preview6 for example the profile didn't exist, so we
            can't rely only on the WebPublishMethod. -->
    <Error Condition="'$(_IsSDKContainerAllowedVersion)' != 'true'" Code="CONTAINER002" Text="The current .NET SDK ($(NETCoreSdkVersion)) doesn't support containerization. Please use version 7.0.100 or higher to enable containerization." />
  </Target>

  <Target Name="ComputeContainerBaseImage"
          Returns="$(ContainerBaseImage)">
    <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. -->
      <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>
      <_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifier)" Condition="'$(ContainerRuntimeIdentifier)' != ''" />
      <_TargetRuntimeIdentifiers Include="$(ContainerRuntimeIdentifiers)" Condition="@(_TargetRuntimeIdentifiers->Count()) == 0" />
    </ItemGroup>

    <ComputeDotnetBaseImageAndTag
      UserBaseImage="$(ContainerBaseImage)"
      SdkVersion="$(NetCoreSdkVersion)"
      TargetFrameworkVersion="$(_TargetFrameworkVersionWithoutV).0"
      FrameworkReferences="@(FrameworkReference)"
      IsSelfContained="$(_ContainerIsSelfContained)"
      IsAotPublished="$(PublishAot)"
      IsTrimmed="$(PublishTrimmed)"
      UsesInvariantGlobalization="$(InvariantGlobalization)"
      TargetRuntimeIdentifiers="@(_TargetRuntimeIdentifiers)"
      ContainerFamily="$(ContainerFamily)">
        <Output TaskParameter="ComputedContainerBaseImage" PropertyName="ContainerBaseImage" />
    </ComputeDotnetBaseImageAndTag>

    <ItemGroup>
      <_TargetRuntimeIdentifiers Remove ="$(_TargetRuntimeIdentifiers)" />
    </ItemGroup>
  </Target>

  <Target Name="ComputeContainerConfig" DependsOnTargets="ComputeContainerBaseImage">
    <PropertyGroup Label="VS defaults">
      <!-- RegistryUrl is used by existing VS targets for Docker builds - this lets us fill that void -->
      <ContainerRegistry Condition="'$(RegistryUrl)' != ''">$(RegistryUrl)</ContainerRegistry>
      <!-- PublishImageTag is used by existing VS targets for Docker builds - this lets us fill that void -->
      <ContainerImageTag Condition="'$(PublishImageTag)' != ''">$(PublishImageTag)</ContainerImageTag>
      <!-- This line is a compatibility shim for VS support - the VS container targets define a container tag using this property and format. This lets us be a drop-in replacement for them. -->
      <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 -->
      <!-- <ContainerRegistry></ContainerRegistry> -->

      <!-- An empty LocalRegistry implies detecting the local registry. LocalRegistry can be set explicity to Docker/Podman. -->
      <!-- <LocalRegistry></LocalRegistry> -->

      <!-- 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)' == ''">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)"
                              ContainerRegistry="$(ContainerRegistry)"
                              ContainerRepository="$(ContainerRepository)"
                              ContainerImageTag="$(ContainerImageTag)"
                              ContainerImageTags="$(ContainerImageTags)"
                              ContainerEnvironmentVariables="@(ContainerEnvironmentVariable)">

      <Output TaskParameter="ParsedContainerRegistry" PropertyName="ContainerBaseRegistry" />
      <Output TaskParameter="ParsedContainerImage" PropertyName="ContainerBaseName" />
      <Output TaskParameter="ParsedContainerTag" PropertyName="ContainerBaseTag" />
      <Output TaskParameter="ParsedContainerDigest" PropertyName="ContainerBaseDigest" />
      <Output TaskParameter="NewContainerRegistry" PropertyName="ContainerRegistry" />
      <Output TaskParameter="NewContainerRepository" PropertyName="ContainerRepository" />
      <Output TaskParameter="NewContainerTags" ItemName="ContainerImageTags" />
      <Output TaskParameter="NewContainerEnvironmentVariables" ItemName="ContainerEnvironmentVariables" />
    </ParseContainerProperties>

    <PropertyGroup>
      <ContainerGenerateLabels Condition="'$(ContainerGenerateLabels)' == ''">true</ContainerGenerateLabels>
      <ContainerGenerateLabelsImageCreated Condition="'$(ContainerGenerateLabelsImageCreated)' == ''">true</ContainerGenerateLabelsImageCreated>
      <ContainerGenerateLabelsImageDescription Condition="'$(ContainerGenerateLabelsImageDescription)' == ''">true</ContainerGenerateLabelsImageDescription>
      <ContainerGenerateLabelsImageAuthors Condition="'$(ContainerGenerateLabelsImageAuthors)' == ''">true</ContainerGenerateLabelsImageAuthors>
      <ContainerGenerateLabelsImageUrl Condition="'$(ContainerGenerateLabelsImageUrl)' == ''">true</ContainerGenerateLabelsImageUrl>
      <ContainerGenerateLabelsImageDocumentation Condition="'$(ContainerGenerateLabelsImageDocumentation)' == ''">true</ContainerGenerateLabelsImageDocumentation>
      <ContainerGenerateLabelsImageSource Condition="'$(ContainerGenerateLabelsImageSource)' == ''">true</ContainerGenerateLabelsImageSource>
      <ContainerGenerateLabelsImageVersion Condition="'$(ContainerGenerateLabelsImageVersion)' == ''">true</ContainerGenerateLabelsImageVersion>
      <ContainerGenerateLabelsImageRevision Condition="'$(ContainerGenerateLabelsImageRevision)' == ''">true</ContainerGenerateLabelsImageRevision>
      <ContainerGenerateLabelsImageVendor Condition="'$(ContainerGenerateLabelsImageVendor)' == ''">true</ContainerGenerateLabelsImageVendor>
      <ContainerGenerateLabelsImageLicenses Condition="'$(ContainerGenerateLabelsImageLicenses)' == ''">true</ContainerGenerateLabelsImageLicenses>
      <ContainerGenerateLabelsImageTitle Condition="'$(ContainerGenerateLabelsImageTitle)' == ''">true</ContainerGenerateLabelsImageTitle>
      <ContainerGenerateLabelsImageBaseDigest Condition="'$(ContainerGenerateLabelsImageBaseDigest)' == ''">true</ContainerGenerateLabelsImageBaseDigest>
      <ContainerGenerateLabelsImageBaseName Condition="'$(ContainerGenerateLabelsImageBaseName)' == ''">true</ContainerGenerateLabelsImageBaseName>
      <ContainerGenerateLabelsDotnetToolset Condition="'$(ContainerGenerateLabelsDotnetToolset)' == ''">true</ContainerGenerateLabelsDotnetToolset>
    </PropertyGroup>

    <PropertyGroup Label="Defaults for Container Labels">
      <ContainerDescription Condition="'$(ContainerDescription)' == '' and '$(Description)' != ''">$(Description)</ContainerDescription>
      <ContainerAuthors Condition="'$(ContainerAuthors)' == '' and '$(Authors)' != ''">$(Authors)</ContainerAuthors>
      <ContainerInformationUrl Condition="'$(ContainerInformationUrl)' == '' and '$(PackageProjectUrl)' != ''">$(PackageProjectUrl)</ContainerInformationUrl>
      <ContainerDocumentationUrl Condition="'$(ContainerDocumentationUrl)' == '' and '$(PackageProjectUrl)' != ''">$(PackageProjectUrl)</ContainerDocumentationUrl>
      <ContainerVersion Condition="'$(ContainerVersion)' == '' and '$(PackageVersion)' != ''">$(PackageVersion)</ContainerVersion>
      <ContainerLicenseExpression Condition="'$(ContainerLicenseExpression)' == '' and '$(PackageLicenseExpression)' != ''">$(PackageLicenseExpression)</ContainerLicenseExpression>
      <ContainerTitle Condition="'$(ContainerTitle)' == '' and '$(Title)' != ''">$(Title)</ContainerTitle>
    </PropertyGroup>

    <!-- Labels generated from descriptions from the spec at https://github.com/opencontainers/image-spec/blob/main/annotations.md#pre-defined-annotation-keys -->
    <ItemGroup Label="Conventional Label assignment" Condition="'$(ContainerGenerateLabels)' == 'true'">
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageCreated)' == 'true'" Include="org.opencontainers.image.created;org.opencontainers.artifact.created" Value="$([System.DateTime]::UtcNow.ToString('o'))" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageDescription)' == 'true' and '$(ContainerDescription)' != ''" Include="org.opencontainers.artifact.description;org.opencontainers.image.description" Value="$(ContainerDescription)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageAuthors)' == 'true' and '$(ContainerAuthors)' != ''" Include="org.opencontainers.image.authors" Value="$(ContainerAuthors)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageUrl)' == 'true' and '$(ContainerInformationUrl)' != ''" Include="org.opencontainers.image.url" Value="$(ContainerInformationUrl)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageDocumentation)' == 'true' and '$(ContainerDocumentationUrl)' != ''" Include="org.opencontainers.image.documentation" Value="$(ContainerDocumentationUrl)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageVersion)' == 'true' and '$(ContainerVersion)' != ''" Include="org.opencontainers.image.version" Value="$(ContainerVersion)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageVendor)' == 'true' and '$(ContainerVendor)' != ''" Include="org.opencontainers.image.vendor" Value="$(ContainerVendor)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageLicenses)' == 'true' and '$(ContainerLicenseExpression)' != ''" Include="org.opencontainers.image.licenses" Value="$(ContainerLicenseExpression)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageTitle)' == 'true' and '$(ContainerTitle)' != ''" Include="org.opencontainers.image.title" Value="$(ContainerTitle)" />
      <!-- Need to compute digests, not just names, before we can light this up. This suggests we need a task where all of the 'read' steps are done. -->
      <!-- <ContainerLabel Condition="'$(ContainerGenerateLabelsImageBaseDigest)' == 'true' and '$(ContainerBaseImageDigest)' != ''" Include="org.opencontainers.image.base.digest" Value="$(ContainerBaseImageDigest)" /> -->
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageBaseName)' == 'true' and '$(ContainerBaseImage)' != ''" Include="org.opencontainers.image.base.name" Value="$(ContainerBaseImage)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsDotnetToolset)' == 'true' and '$(TargetFrameworkIdentifier)' == '.NETCoreApp'" Include="net.dot.runtime.majorminor" Value="$(_TargetFrameworkVersionWithoutV)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsDotnetToolset)' == 'true'" Include="net.dot.sdk.version" Value="$(NETCoreSdkVersion)" />
    </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.  -->
    <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>
      <_TrimmedRepositoryUrl Condition="'$(_TrimmedRepositoryUrl)' == '' and '$(PrivateRepositoryUrl)' != ''">$(PrivateRepositoryUrl)</_TrimmedRepositoryUrl>
    </PropertyGroup>
    <ItemGroup Label="Source control label assignment" Condition="'$(ContainerGenerateLabels)' == 'true' and '$(PublishRepositoryUrl)' == 'true'">
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageSource)' == 'true' and '$(_TrimmedRepositoryUrl)' != ''" Include="org.opencontainers.image.source" Value="$(_TrimmedRepositoryUrl)" />
      <ContainerLabel Condition="'$(ContainerGenerateLabelsImageRevision)' == 'true' and '$(SourceRevisionId)' != ''" Include="org.opencontainers.image.revision" Value="$(SourceRevisionId)" />
    </ItemGroup>
  </Target>

  <PropertyGroup>
    <PublishContainerDependsOn>
      _ContainerVerifySDKVersion;
      ComputeContainerConfig;
      _CheckContainersPackage
    </PublishContainerDependsOn>
  </PropertyGroup>

  <Target Name="_CheckContainersPackage" AfterTargets="Build">
    <PropertyGroup>
      <!-- facts to base on comparisons on -->
      <_ContainersPackageIdentity>Microsoft.NET.Build.Containers</_ContainersPackageIdentity>
      <_WebDefaultSdkVersion>7.0.300</_WebDefaultSdkVersion>
      <_WorkerDefaultSdkVersion>8.0.100</_WorkerDefaultSdkVersion>
      <_ConsoleDefaultSdkVersion>8.0.200</_ConsoleDefaultSdkVersion>

      <!-- capability detection for the executing SDK -->
      <_SdkCanPublishWeb>$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '$(_WebDefaultSdkVersion)'))</_SdkCanPublishWeb>
      <_SdkCanPublishWorker>$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '$(_WorkerDefaultSdkVersion)'))</_SdkCanPublishWorker>
      <_SdkCanPublishConsole>$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '$(_ConsoleDefaultSdkVersion)'))</_SdkCanPublishConsole>

      <!-- capability detection for the executing project -->
      <_ContainerPackageIsPresent>false</_ContainerPackageIsPresent>
      <_ContainerPackageIsPresent Condition="@(PackageReference->AnyHaveMetadataValue('Identity', '$(_ContainersPackageIdentity)'))">true</_ContainerPackageIsPresent>
      <_IsWebProject>false</_IsWebProject>
      <_IsWebProject Condition="@(ProjectCapability->AnyHaveMetadataValue('Identity', 'DotNetCoreWeb'))">true</_IsWebProject>
      <_IsWorkerProject>false</_IsWorkerProject>
      <_IsWorkerProject Condition="@(ProjectCapability->AnyHaveMetadataValue('Identity', 'DotNetCoreWorker'))">true</_IsWorkerProject>
    </PropertyGroup>

    <Warning
      Condition="$(_ContainerPackageIsPresent)
        and (
          ($(_SdkCanPublishWeb) and $(_IsWebProject)) or
          ($(_SdkCanPublishWorker) and $(_IsWorkerProject)) or
          ($(_SdkCanPublishConsole) and '$(EnableSdkContainerSupport)' == 'true')
        )"
      Code="CONTAINER005"
      Text="The $(_ContainersPackageIdentity) NuGet package is explicitly referenced but the current SDK can natively publish the project as a container. Consider removing the package reference to $(_ContainersPackageIdentity) because it is no longer needed." />
  </Target>

  <Target Name="_PublishSingleContainer"
          Returns="@(GeneratedContainers)">
    <PropertyGroup Condition="'$(DOTNET_HOST_PATH)' == ''">
      <DotNetHostDirectory>$(NetCoreRoot)</DotNetHostDirectory>
      <DotNetHostFileName>dotnet</DotNetHostFileName>
      <DotNetHostFileName Condition="'$(OS)' == 'Windows_NT'">dotnet.exe</DotNetHostFileName>
    </PropertyGroup>

    <CreateNewImage ContainerizeDirectory="$(ContainerizeFolder)"
                    ToolPath="$(DotNetHostDirectory)"
                    ToolExe="$(DotNetHostFileName)"
                    BaseRegistry="$(ContainerBaseRegistry)"
                    BaseImageName="$(ContainerBaseName)"
                    BaseImageTag="$(ContainerBaseTag)"
                    BaseImageDigest="$(ContainerBaseDigest)"
                    ImageFormat="$(ContainerImageFormat)"
                    LocalRegistry="$(LocalRegistry)"
                    OutputRegistry="$(ContainerRegistry)"
                    ArchiveOutputPath="$(ContainerArchiveOutputPath)"
                    Repository="$(ContainerRepository)"
                    ImageTags="@(ContainerImageTags)"
                    PublishDirectory="$(PublishDir)"
                    WorkingDirectory="$(ContainerWorkingDirectory)"
                    Entrypoint="@(ContainerEntrypoint)"
                    EntrypointArgs="@(ContainerEntrypointArgs)"
                    AppCommand="@(ContainerAppCommand)"
                    AppCommandArgs="@(ContainerAppCommandArgs)"
                    AppCommandInstruction="$(ContainerAppCommandInstruction)"
                    DefaultArgs="@(ContainerDefaultArgs)"
                    Labels="@(ContainerLabel)"
                    ExposedPorts="@(ContainerPort)"
                    ContainerEnvironmentVariables="@(ContainerEnvironmentVariables)"
                    ContainerRuntimeIdentifier="$(ContainerRuntimeIdentifier)"
                    ContainerUser="$(ContainerUser)"
                    RuntimeIdentifierGraphPath="$(RuntimeIdentifierGraphPath)"
                    SkipPublishing="$(_SkipContainerPublishing)"
                    GenerateLabels="$(ContainerGenerateLabels)"
                    GenerateDigestLabel="$(ContainerGenerateLabelsImageBaseDigest)"> <!-- The RID graph path is provided as a property by the SDK. -->

      <Output TaskParameter="GeneratedContainerManifest" PropertyName="GeneratedContainerManifest" />
      <Output TaskParameter="GeneratedContainerConfiguration" PropertyName="GeneratedContainerConfiguration" />
      <Output TaskParameter="GeneratedContainerDigest" PropertyName="GeneratedContainerDigest" />
      <Output TaskParameter="GeneratedArchiveOutputPath" PropertyName="GeneratedArchiveOutputPath" />
      <Output TaskParameter="GeneratedContainerMediaType" PropertyName="GeneratedContainerMediaType" />
      <Output TaskParameter="GeneratedContainerNames" ItemName="GeneratedContainerName" />
    </CreateNewImage>

    <ItemGroup>
      <GeneratedContainers Include="GeneratedContainer">
        <Manifest>$(GeneratedContainerManifest)</Manifest>
        <Configuration>$(GeneratedContainerConfiguration)</Configuration>
        <ManifestDigest>$(GeneratedContainerDigest)</ManifestDigest>
        <ManifestMediaType>$(GeneratedContainerMediaType)</ManifestMediaType>
      </GeneratedContainers>
    </ItemGroup>
  </Target>

  <Target Name="_PublishMultiArchContainers" DependsOnTargets="$(PublishContainerDependsOn)" >
    <PropertyGroup>
      <!--We want to skip publishing individual images in case of multi-arch tarball publishing or local daemon (only docker) publishing because all images are published in one tarball.-->
      <!--We don't want to skip publishing individual images in case of remote registry because the individual images should be available in the registry before image index is pushed.-->
      <!--We don't want to skip publishing individual images in case of local daemon podman because podman loads multi-arch tarball differently - only individual image for the current platform.-->
      <_SkipContainerPublishing>false</_SkipContainerPublishing>
      <_SkipContainerPublishing Condition="$(ContainerArchiveOutputPath) != '' or ( $(ContainerRegistry) == '' and ( $(LocalRegistry) == '' or $(LocalRegistry) == 'Docker' ) )">true</_SkipContainerPublishing>

      <!--We want to skip CreateImageIndex task in case of local daemon podman because it is not supported.-->
      <_SkipCreateImageIndex>false</_SkipCreateImageIndex>
      <_SkipCreateImageIndex Condition="$(ContainerArchiveOutputPath) == '' and $(ContainerRegistry) == '' and $(LocalRegistry) == 'Podman'">true</_SkipCreateImageIndex>

      <!-- Figure out what format the inner images should be coerced to -->
      <!-- If a user had an opinion, use that -->
      <_SingleImageContainerFormat Condition="'$(ContainerImageFormat)' != ''">$(ContainerImageFormat)</_SingleImageContainerFormat>
      <!-- If we are publishing to local tarball or to local Docker, force OCI to prevent mismatches between inner images and the outer manifest -->
      <_SingleImageContainerFormat Condition="$(_SkipContainerPublishing) == 'true' ">OCI</_SingleImageContainerFormat>
    </PropertyGroup>

    <ItemGroup>
      <_rids Include="$(ContainerRuntimeIdentifiers)" Condition="'$(ContainerRuntimeIdentifiers)' != ''" />
      <_rids Include="$(RuntimeIdentifiers)" Condition="'$(ContainerRuntimeIdentifiers)' == '' and '$(RuntimeIdentifiers)' != ''" />
      <_InnerBuild
        Include="$(MSBuildProjectFullPath)"
        AdditionalProperties="
          ContainerRuntimeIdentifier=%(_rids.Identity);
          RuntimeIdentifier=%(_rids.Identity);
          ContainerBaseRegistry=$(ContainerBaseRegistry);
          ContainerBaseName=$(ContainerBaseName);
          ContainerBaseTag=$(ContainerBaseTag);
          ContainerBaseDigest=$(ContainerBaseDigest);
          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);
          _SkipContainerPublishing=$(_SkipContainerPublishing);
          ContainerImageFormat=$(_SingleImageContainerFormat)
        "/>
      <_rids Remove ="$(_rids)" />
    </ItemGroup>

    <MSBuild
        Projects="@(_InnerBuild)"
        Targets="Publish;_ParseItemsForPublishingSingleContainer;_PublishSingleContainer"
        BuildInParallel="$([MSBuild]::ValueOrDefault('$(ContainerPublishInParallel)', 'true'))">
        <Output TaskParameter="TargetOutputs" ItemName="GeneratedContainers" />
    </MSBuild>

    <CreateImageIndex Condition="'$(_SkipCreateImageIndex)' == 'false' "
                      GeneratedContainers="@(GeneratedContainers)"
                      LocalRegistry="$(LocalRegistry)"
                      OutputRegistry="$(ContainerRegistry)"
                      ArchiveOutputPath="$(ContainerArchiveOutputPath)"
                      Repository="$(ContainerRepository)"
                      ImageTags="@(ContainerImageTags)"
                      BaseRegistry="$(ContainerBaseRegistry)"
                      BaseImageName="$(ContainerBaseName)"
                      BaseImageTag="$(ContainerBaseTag)"
                      BaseImageDigest="$(ContainerBaseDigest)">
      <Output TaskParameter="GeneratedImageIndex" PropertyName="GeneratedImageIndex" />
      <Output TaskParameter="GeneratedArchiveOutputPath" PropertyName="GeneratedArchiveOutputPath" />
    </CreateImageIndex>
  </Target>

  <Target Name="_ParseItemsForPublishingSingleContainer">
    <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)' != ':'"
        Include="$(_ContainerLabel)"/>
      <ContainerLabel
        Condition="@(_ParsedContainerLabel->Count()) > 0 "
        Include="$([System.String]::Copy('%(_ParsedContainerLabel.Identity)').Split(':')[0])"
        Value="$([System.String]::Copy('%(_ParsedContainerLabel.Identity)').Split(':')[1])" />

      <_ParsedContainerPort
        Condition="'$(_ContainerPort)' != ':'"
        Include="$(_ContainerPort)"/>
      <ContainerPort
        Condition="@(_ParsedContainerPort->Count()) > 0 "
        Include="$([System.String]::Copy('%(_ParsedContainerPort.Identity)').Split(':')[0])"
        Type="$([System.String]::Copy('%(_ParsedContainerPort.Identity)').Split(':')[1])" />

      <_ParsedContainerEnvironmentVariables
        Condition="'$(_ContainerEnvironmentVariables)' != ':'"
        Include="$(_ContainerEnvironmentVariables)"/>
      <ContainerEnvironmentVariables
        Condition="@(_ParsedContainerEnvironmentVariables->Count()) > 0 "
        Include="$([System.String]::Copy('%(_ParsedContainerEnvironmentVariables.Identity)').Split(':')[0])"
        Value="$([System.String]::Copy('%(_ParsedContainerEnvironmentVariables.Identity)').Split(':')[1])" />
    </ItemGroup>
  </Target>

  <Target Name="PublishContainer"
  DependsOnTargets="$(PublishContainerDependsOn)"
  Condition="'$(IsPublishable)' == 'true' AND '$(EnableSdkContainerSupport)' == 'true'">
    <PropertyGroup>
      <_IsMultiTFMBuild Condition="'$(TargetFrameworks)' != '' and '$(TargetFramework)' == ''">true</_IsMultiTFMBuild>
      <!-- we are multi-RID if:
          * we have CRIDs and no CRID
          * we have RIDs and no (CRIDs or CRID or RID)
      -->
      <_HasCRIDsAndNoCRID Condition="'$(ContainerRuntimeIdentifiers)' != '' and '$(ContainerRuntimeIdentifier)' == ''">true</_HasCRIDsAndNoCRID>
      <_HasRIDs Condition="'$(RuntimeIdentifiers)' != ''">true</_HasRIDs>
      <_NoCRIDsOrCRIDorRID Condition="'$(ContainerRuntimeIdentifiers)' == '' and '$(ContainerRuntimeIdentifier)' == '' and '$(RuntimeIdentifier)' == ''">true</_NoCRIDsOrCRIDorRID>
      <_IsMultiRIDBuild Condition="'$(BuildingInsideVisualStudio)' != 'true' and ('$(_HasCRIDsAndNoCRID)' == true or ('$(_HasRIDs)' == 'true' and '$(_NoCRIDsOrCRIDorRID)' == 'true'))">true</_IsMultiRIDBuild>
      <_IsSingleRIDBuild Condition="'$(_IsMultiRIDBuild)' == ''">true</_IsSingleRIDBuild>
    </PropertyGroup>

    <!-- Call _PublishMultiArchContainers if we are in a multi-rid build, and call _PublishSingleContainer if we are in a single-RID build -->
    <CallTarget Condition="'$(_IsMultiRIDBuild)' == 'true' " Targets="_PublishMultiArchContainers" />
    <CallTarget Condition="'$(_IsSingleRIDBuild)' == 'true' " Targets="_PublishSingleContainer" />

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

</Project>
