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
|
<Project Sdk="Microsoft.Build.NoTargets">
<PropertyGroup>
<!-- Set IsStableBuild to mimic https://github.com/dotnet/arcade/blob/694d59f090b743f894779d04a7ffe11cbaf352e7/src/Microsoft.DotNet.Arcade.Sdk/tools/Publish.proj#L30-L31 -->
<IsStableBuild>false</IsStableBuild>
<IsStableBuild Condition="'$(DotNetFinalVersionKind)' == 'release'">true</IsStableBuild>
<ChecksumExtension>.sha512</ChecksumExtension>
<DownloadDirectory>$(ArtifactsDir)PackageDownload/</DownloadDirectory>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.DotNet.Build.Tasks.Feed" Version="$(MicrosoftDotNetBuildTasksFeedVersion)" />
<PackageReference Include="Microsoft.DotNet.VersionTools.Tasks" Version="$(MicrosoftDotNetVersionToolsTasksVersion)" />
</ItemGroup>
<!-- When doing post build sign, pull in the arcade sign.props file, which will
create some initial sign groups and then pulls in the repo's custom Signing.props overrides.
Before importing the signing props. Set PrepareArtifactst=true. Depending on context (SDK project vs. not),
the initial imports of livebuilds.targets and Configuration.props are already imported and thus cannot
be imported again. Without those imports, the globbing of files to sign will not work properly. -->
<PropertyGroup>
<PrepareArtifacts>true</PrepareArtifacts>
</PropertyGroup>
<Import Project="../tools/Sign.props" Sdk="Microsoft.DotNet.Arcade.Sdk" />
<UsingTask TaskName="GenerateChecksums" AssemblyFile="$(InstallerTasksAssemblyPath)" />
<PropertyGroup>
<SuppressFinalPackageVersion>true</SuppressFinalPackageVersion>
</PropertyGroup>
<!-- Pulled from arcade's publish.proj see https://github.com/dotnet/arcade/issues/5790 for
issue on making this common in arcade so it doesn't have to be duplicated here -->
<PropertyGroup>
<CollectionUri>$(SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)</CollectionUri>
<!-- When we have dev.azure.com/<account>/ -->
<AzureDevOpsAccount Condition="$(CollectionUri.IndexOf('dev.azure.com')) >= 0">$(CollectionUri.Split('/')[3])</AzureDevOpsAccount>
<!-- When we have <account>.visualstudio.com -->
<AzureDevOpsAccount Condition="$(CollectionUri.IndexOf('visualstudio.com')) >= 0">$(CollectionUri.Split('.')[0].Split('/')[2])</AzureDevOpsAccount>
</PropertyGroup>
<!--
The new Maestro/BAR build model keeps separate Azure DevOps and GitHub build information.
The GitHub information will be extracted based on the Azure DevOps repository.
-->
<ItemGroup>
<ManifestBuildData Include="InitialAssetsLocation=$(SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$(SYSTEM_TEAMPROJECT)/_apis/build/builds/$(BUILD_BUILDID)/artifacts" />
<ManifestBuildData Include="AzureDevOpsBuildId=$(BUILD_BUILDID)" />
<ManifestBuildData Include="AzureDevOpsBuildDefinitionId=$(SYSTEM_DEFINITIONID)" />
<ManifestBuildData Include="AzureDevOpsAccount=$(AzureDevOpsAccount)" />
<ManifestBuildData Include="AzureDevOpsProject=$(SYSTEM_TEAMPROJECT)" />
<ManifestBuildData Include="AzureDevOpsBuildNumber=$(BUILD_BUILDNUMBER)" />
<ManifestBuildData Include="AzureDevOpsRepository=$(BUILD_REPOSITORY_URI)" />
<ManifestBuildData Include="AzureDevOpsBranch=$(BUILD_SOURCEBRANCH)" />
</ItemGroup>
<!--
Take assets from the build jobs, prepare them for publishing (signing, arrangement) then upload
them to the pipeline for Arcade and custom steps to publish.
-->
<Target Name="PreparePublishToAzureBlobFeed"
AfterTargets="Build"
DependsOnTargets="GetProductVersions;FindDownloadedArtifacts;CreateChecksums">
<PropertyGroup>
<AssetManifestFilename>Manifest.xml</AssetManifestFilename>
<AssetManifestFile>$(ArtifactsLogDir)AssetManifest/$(AssetManifestFilename)</AssetManifestFile>
<!-- Create temp dir to store generated asset manifest, per Arcade guidance. -->
<TempWorkingDir>$(ArtifactsObjDir)TempWorkingDir\$([System.Guid]::NewGuid())\</TempWorkingDir>
<ProductVersionTxtContents Condition="'$(StabilizePackageVersion)'=='true'">$(ProductionVersion)</ProductVersionTxtContents>
<ProductVersionTxtContents Condition="'$(StabilizePackageVersion)'!='true'">$(ProductVersion)</ProductVersionTxtContents>
</PropertyGroup>
<!-- Generate productVersion.txt containing the value of $(PackageVersion) -->
<WriteLinesToFile
File="$(ArtifactsShippingPackagesDir)productVersion.txt"
Lines="$(ProductVersionTxtContents)"
Overwrite="true"
Encoding="ASCII" />
<!-- Generate runtime-productVersion.txt containing the value of $(PackageVersion) -->
<WriteLinesToFile
File="$(ArtifactsShippingPackagesDir)runtime-productVersion.txt"
Lines="$(ProductVersionTxtContents)"
Overwrite="true"
Encoding="ASCII" />
<ItemGroup>
<ItemsToPush Remove="@(ItemsToPush)" />
<ItemsToPush Include="@(ShippingNupkgToPublishFile)" />
<ItemsToPush Include="@(NonShippingNupkgToPublishFile)" ManifestArtifactData="NonShipping=true" />
<ItemsToPush Include="@(SymbolNupkgToPublishFile)" />
<ItemsToPush
Include="@(UploadToBlobStorageFile)"
Exclude="@(NupkgToPublishFile);@(SymbolNupkgToPublishFile)">
<RelativeBlobPath>$(InstallersRelativePath)%(Filename)%(Extension)</RelativeBlobPath>
<PublishFlatContainer>true</PublishFlatContainer>
</ItemsToPush>
<ItemsToPush Include="@(GeneratedChecksumFile)">
<RelativeBlobPath>$(InstallersRelativePath)%(Filename)%(Extension)</RelativeBlobPath>
<Category>Checksum</Category>
<PublishFlatContainer>true</PublishFlatContainer>
</ItemsToPush>
<ItemsToPush Include="$(ArtifactsShippingPackagesDir)productVersion.txt">
<RelativeBlobPath>$(InstallersRelativePath)productVersion.txt</RelativeBlobPath>
<PublishFlatContainer>true</PublishFlatContainer>
</ItemsToPush>
<ItemsToPush Include="$(ArtifactsShippingPackagesDir)runtime-productVersion.txt">
<RelativeBlobPath>$(InstallersRelativePath)runtime-productVersion.txt</RelativeBlobPath>
<PublishFlatContainer>true</PublishFlatContainer>
</ItemsToPush>
<ItemsToPush Include="@(WorkloadsVSInsertionFile)">
<RelativeBlobPath>$(InstallersRelativePath)workloads/$(SdkBandVersion)/%(Filename)%(Extension)</RelativeBlobPath>
<PublishFlatContainer>true</PublishFlatContainer>
</ItemsToPush>
<!-- Source build intermediated packages will be pushed and signed by the sourcebuild leg. -->
<ItemsToPush Remove="@(ItemsToPush)" Condition="$([System.String]::new('%(Identity)').Contains('Microsoft.SourceBuild.Intermediate'))" />
<ItemsToSignPostBuild Remove="@(ItemsToSignPostBuild)" Condition="$([System.String]::new('%(Identity)').Contains('Microsoft.SourceBuild.Intermediate'))" />
</ItemGroup>
<!-- Push items to AzDO as build artifacts, generating the asset manifest as a side effect. -->
<PushToAzureDevOpsArtifacts
AzureDevOpsCollectionUri="$(SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)"
AzureDevOpsProject="$(SYSTEM_TEAMPROJECT)"
AzureDevOpsBuildId="$(BUILD_BUILDID)"
ItemsToSign="@(ItemsToSignPostBuild)"
StrongNameSignInfo="@(StrongNameSignInfo)"
FileSignInfo="@(FileSignInfo)"
FileExtensionSignInfo="@(FileExtensionSignInfo)"
ItemsToPush="@(ItemsToPush)"
ManifestBuildData="@(ManifestBuildData)"
ManifestRepoUri="$(BUILD_REPOSITORY_NAME)"
ManifestBranch="$(BUILD_SOURCEBRANCH)"
ManifestBuildId="$(BUILD_BUILDNUMBER)"
ManifestCommit="$(BUILD_SOURCEVERSION)"
IsStableBuild="$(IsStableBuild)"
AssetManifestPath="$(AssetManifestFile)"
AssetsTemporaryDirectory="$(TempWorkingDir)"
PublishingVersion ="3" />
<!-- Copy the generated manifest to the build's artifacts -->
<Copy SourceFiles="$(AssetManifestFile)" DestinationFolder="$(TempWorkingDir)" />
<Message Importance="High" Text="Uploading $(AssetManifestFilename) to pipeline" />
<Message
Text="##vso[artifact.upload containerfolder=AssetManifests;artifactname=AssetManifests]$(TempWorkingDir)$(AssetManifestFilename)"
Importance="High" />
<Message Importance="High" Text="Complete!" />
</Target>
<!--
Look through the downloaded artifacts to figure out how to ship them. Creates item groups for
other types of publishing to use.
DownloadDirectory is expected to have some directory inside, which then contains a dir for each
build job name. For example, this nupkg would be found:
$(DownloadDirectory)IntermediateUnsignedArtifacts\Windows_x64\Shipping\a.nupkg
-->
<Target Name="FindDownloadedArtifacts">
<ItemGroup>
<DownloadedArtifactFile Include="$(DownloadDirectory)**" />
<Error
Condition="'@(DownloadedArtifactFile)' == ''"
Text="No downloaded artifacts found." />
<DownloadedSymbolNupkgFile Include="$(DownloadDirectory)**\*.symbols.nupkg" />
<DownloadedWixPdbFile Include="$(DownloadDirectory)**\*.wixpdb" />
<DownloadedWorkloadsVSInsertionFile Include="$(DownloadDirectory)*\workloads-vs\**\*" />
<DownloadedNupkgFile
Include="$(DownloadDirectory)**\*.nupkg"
Exclude="@(DownloadedSymbolNupkgFile)" />
<!-- Add files that are not affected by filtering. -->
<UploadToBlobStorageFile
Include="@(DownloadedArtifactFile)"
Exclude="@(DownloadedSymbolNupkgFile);@(DownloadedNupkgFile);@(DownloadedWixPdbFile);@(DownloadedWorkloadsVSInsertionFile)" />
<!--
Filter out the RID-specific (Runtime) nupkgs and RID-agnostic nupkgs. RID-specific packages
are published from every job. RID-agnostic nupkgs are built with the same ID/version by
every job, so one specific job's outputs must be picked to sign and publish.
-->
<!-- RID-specific framework packs. -->
<RuntimeNupkgFile
Include="
$(DownloadDirectory)**\Microsoft.*.Runtime.*.nupkg;
$(DownloadDirectory)**\Microsoft.*.App.Host.*.nupkg;
$(DownloadDirectory)**\Microsoft.*.App.Crossgen2.*.nupkg"
Exclude="@(DownloadedSymbolNupkgFile)" />
<!-- VS insertion packages, carrying RID-specific installers. -->
<RuntimeNupkgFile
Include="$(DownloadDirectory)**\VS.Redist.Common.*.nupkg"
Exclude="@(DownloadedSymbolNupkgFile)" />
<!-- Workloads VS insertion artifacts produced by src/workloads/workloads.csproj -->
<WorkloadsVSInsertionFile
Include="
$(DownloadDirectory)*\workloads-vs\**\*.json;
$(DownloadDirectory)*\workloads-vs\**\*.msi" />
<!--
Runtime packages associated with some identity packages. Need to exclude "runtime.native.*"
because Libraries produces some "runtime.native.Foo" packages with
"runtime.<rid>.runtime.native.Foo" identity packages.
-->
<RuntimeNupkgFile
Include="$(DownloadDirectory)**\runtime.*.nupkg"
Exclude="
$(DownloadDirectory)**\runtime.native.*.nupkg;
@(DownloadedSymbolNupkgFile)" />
<!--
Packages that aren't matched above as RID-specific are considered RID-agnostic. Also include
the AllConfigurations packages from the Libraries build.
-->
<RidAgnosticNupkgToPublishFile
Include="
$(DownloadDirectory)**\Microsoft.NET.Workload.Mono.Toolchain.Manifest-*.nupkg;
$(DownloadDirectory)*\$(PublishRidAgnosticPackagesFromPlatform)\**\*.nupkg;
$(DownloadDirectory)*\*AllConfigurations\**\*.nupkg"
Exclude="@(RuntimeNupkgFile);@(DownloadedSymbolNupkgFile)" />
<TransportPackagesToPublishFile
Include="$(DownloadDirectory)**\*Transport*.nupkg"
Exclude="@(RuntimeNupkgFile);@(RidAgnosticNupkgToPublishFile);@(DownloadedSymbolNupkgFile)" />
<NupkgToPublishFile Include="@(RuntimeNupkgFile);@(RidAgnosticNupkgToPublishFile);@(TransportPackagesToPublishFile)" />
<!--
Assuming all symbol packages ship and can be found by turning .nupkg => .symbols.nupkg, find
them. Don't check for missing symbol packages here: some nupkgs don't have them for valid
reasons, such as the VS insertion packages that transport MSIs. Symbol package validation
will check for symbol completeness with file-by-file granularity rather than looking for
missing symbols.nupkg files: https://github.com/dotnet/arcade/issues/2499.
Handles several conventions:
* NonShipping packages have symbol nupkgs that are Shipping.
* Shipping packages have symbol packages in a "symbols" subdirectory.
-->
<PotentialSymbolNupkgToPublishFile
Include="
@(NupkgToPublishFile->Replace('\NonShipping\', '\Shipping\')->Replace('.nupkg', '.symbols.nupkg'));
@(NupkgToPublishFile->Replace('\NonShipping\', '\NonShipping\symbols\')->Replace('.nupkg', '.symbols.nupkg'));
@(NupkgToPublishFile->Replace('\Shipping\', '\Shipping\symbols\')->Replace('.nupkg', '.symbols.nupkg'))" />
<SymbolNupkgToPublishFile
Include="@(PotentialSymbolNupkgToPublishFile -> Distinct())"
Condition="Exists('%(Identity)')" />
<!-- Split nupkgs into shipping/nonshipping for BAR categorization. -->
<ShippingNupkgToPublishFile
Include="@(NupkgToPublishFile)"
Condition="$([System.String]::new('%(Identity)').Contains('\Shipping\'))" />
<NonShippingNupkgToPublishFile
Include="@(NupkgToPublishFile)"
Exclude="@(ShippingNupkgToPublishFile)" />
</ItemGroup>
<Error
Condition="'@(SymbolNupkgToPublishFile)' == ''"
Text="No symbol packages found." />
<!--
Duplicate RuntimeNupkgFile items mean artifact upload will fail, but only after another hour
of signing. Detect this early. It's possible to automatically "fix" this with Distinct(),
however the patterns should be fairly specific: this is likely a build infra mistake that
should be corrected.
-->
<Error
Text="Duplicate RuntimeNupkgFile entries for: %(RuntimeNupkgFile.Identity)"
Condition="@(RuntimeNupkgFile->Count()) > 1" />
</Target>
<Target Name="CreateChecksums">
<ItemGroup>
<ArtifactsForGeneratingChecksums Include="@(UploadToBlobStorageFile)"
DestinationPath="%(FullPath)$(ChecksumExtension)" />
<GeneratedChecksumFile Include="@(ArtifactsForGeneratingChecksums -> '%(DestinationPath)')" />
</ItemGroup>
<GenerateChecksums Items="@(ArtifactsForGeneratingChecksums)" />
</Target>
</Project>
|