-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
Copy pathMicrosoft.NET.Build.Containers.targets
442 lines (396 loc) · 32.7 KB
/
Microsoft.NET.Build.Containers.targets
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
<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>
</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>
<!-- This Target is called early on in the chain for both single-RID and multi-RID containers - but for single-RID it's important
that we ensure all of the data necessary to create a single-RID container is computed after we exit this target. -->
<Target Name="ComputeContainerConfig" DependsOnTargets="ComputeContainerBaseImage;_ComputeContainerExecutionArgs">
<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>
</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;
_ContainerEstablishRIDNess;
ComputeContainerConfig;
_CheckContainersPackage
</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, multi-RID build layer. -->
<Target Name="_ComputeContainerExecutionArgs" Condition="'$(_IsSingleRIDBuild)' == 'true'">
<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 -->
<_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>
<!-- There is an implicit dependency here in that both of ComputeContainerConfig and _ComputeContainerExecutionArgs must have been run, but because we call this Target
in a few different ways we can't express that dependency directly here. -->
<Target Name="_PublishSingleContainer" Returns="@(GeneratedContainer)">
<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" />
<Output TaskParameter="GeneratedDigestLabel" ItemName="ContainerLabel" />
</CreateNewImage>
<ItemGroup>
<GeneratedContainer Include="GeneratedContainer">
<Manifest>$(GeneratedContainerManifest)</Manifest>
<Configuration>$(GeneratedContainerConfiguration)</Configuration>
<ManifestDigest>$(GeneratedContainerDigest)</ManifestDigest>
<ManifestMediaType>$(GeneratedContainerMediaType)</ManifestMediaType>
</GeneratedContainer>
</ItemGroup>
</Target>
<Target Name="_PublishMultiArchContainers" DependsOnTargets="$(PublishContainerDependsOn)" Returns="@(GeneratedContainer)" >
<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);
_ContainerLabel=@(ContainerLabel->'%(Identity):%(Value)');
_ContainerPort=@(ContainerPort->'%(Identity):%(Type)');
_ContainerEnvironmentVariables=@(ContainerEnvironmentVariable->'%(Identity):%(Value)');
ContainerGenerateLabels=$(ContainerGenerateLabels);
ContainerGenerateLabelsImageBaseDigest=$(ContainerGenerateLabelsImageBaseDigest);
_SkipContainerPublishing=$(_SkipContainerPublishing);
ContainerImageFormat=$(_SingleImageContainerFormat);
_IsMultiRIDBuild=false;
_IsSingleRIDBuild=true
"/>
<_rids Remove ="$(_rids)" />
</ItemGroup>
<MSBuild
Projects="@(_InnerBuild)"
Targets="Publish;_ParseItemsForPublishingSingleContainer;_ComputeContainerExecutionArgs;_PublishSingleContainer"
BuildInParallel="$([MSBuild]::ValueOrDefault('$(ContainerPublishInParallel)', 'true'))">
<Output TaskParameter="TargetOutputs" ItemName="GeneratedContainer" />
</MSBuild>
<CreateImageIndex Condition="'$(_SkipCreateImageIndex)' == 'false' "
GeneratedContainers="@(GeneratedContainer)"
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)')" />
<_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="_ContainerEstablishRIDNess">
<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>
<!-- these two are load-bearing for other comparisons - see _ComputeContainerExecutionArgs -->
<_IsMultiRIDBuild Condition="'$(BuildingInsideVisualStudio)' != 'true' and ('$(_HasCRIDsAndNoCRID)' == true or ('$(_HasRIDs)' == 'true' and '$(_NoCRIDsOrCRIDorRID)' == 'true'))">true</_IsMultiRIDBuild>
<_IsSingleRIDBuild Condition="'$(_IsMultiRIDBuild)' == ''">true</_IsSingleRIDBuild>
</PropertyGroup>
</Target>
<Target Name="PublishContainer"
DependsOnTargets="$(PublishContainerDependsOn)"
Condition="'$(IsPublishable)' == 'true' AND '$(EnableSdkContainerSupport)' == 'true'"
Returns="@(GeneratedContainer)"
>
<!-- 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">
<Output TaskParameter="TargetOutputs" ItemName="GeneratedContainer" />
</CallTarget>
<CallTarget Condition="'$(_IsSingleRIDBuild)' == 'true' " Targets="_PublishSingleContainer">
<Output TaskParameter="TargetOutputs" ItemName="GeneratedContainer" />
</CallTarget>
<Error Condition="'$(_IsMultiTFMBuild)' == 'true'" Code="CONTAINERS0666" Text="Containers cannot be published for multiple TargetFrameworks at this time. Please specify a TargetFramework." />
</Target>
</Project>