Create and publish VerticalAssetManifest (#19062)

Co-authored-by: Matt Mitchell <mmitche@microsoft.com>
Co-authored-by: Viktor Hofer <viktor.hofer@microsoft.com>
This commit is contained in:
Djuradj Kurepa 2024-03-26 19:01:39 +01:00 committed by GitHub
parent a2f8bbc1f9
commit ca9773f69a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 183 additions and 0 deletions

View file

@ -441,3 +441,24 @@ jobs:
mergeTestResults: true
publishRunAttachments: true
testRunTitle: SourceBuild_SmokeTests_$(Agent.JobName)
- task: CopyFiles@2
inputs:
SourceFolder: $(sourcesPath)/artifacts
Contents: |
VerticalManifest.xml
assets/**
TargetFolder: $(Build.ArtifactStagingDirectory)/publishing
displayName: Copy artifacts to Artifact Staging Directory
# When building from source, the Private.SourceBuilt.Artifacts archive already contains the nuget packages
- ${{ if ne(parameters.buildSourceOnly, 'true') }}:
- task: CopyFiles@2
inputs:
SourceFolder: $(sourcesPath)/artifacts/packages
TargetFolder: $(Build.ArtifactStagingDirectory)/publishing/packages
displayName: Copy packages to Artifact Staging Directory
- publish: $(Build.ArtifactStagingDirectory)/publishing
artifact: $(Agent.JobName)_Artifacts
displayName: Publish Artifacts

View file

@ -206,6 +206,7 @@
<XPlatSourceBuildTasksAssembly>$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Microsoft.DotNet.SourceBuild.Tasks.XPlat', '$(Configuration)', 'Microsoft.DotNet.SourceBuild.Tasks.XPlat.dll'))</XPlatSourceBuildTasksAssembly>
<LeakDetectionTasksAssembly>$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Microsoft.DotNet.SourceBuild.Tasks.LeakDetection', '$(Configuration)', 'Microsoft.DotNet.SourceBuild.Tasks.LeakDetection.dll'))</LeakDetectionTasksAssembly>
<SdkArchiveDiffTasksAssembly>$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Microsoft.DotNet.SourceBuild.Tasks.SdkArchiveDiff', '$(Configuration)', 'Microsoft.DotNet.SourceBuild.Tasks.SdkArchiveDiff.dll'))</SdkArchiveDiffTasksAssembly>
<MergeAssetManifestsAssembly>$([MSBuild]::NormalizePath('$(ArtifactsBinDir)', 'Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests', '$(Configuration)', 'Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests.dll'))</MergeAssetManifestsAssembly>
</PropertyGroup>
<PropertyGroup Condition="'$(EnablePoison)' == 'true'">
@ -214,6 +215,12 @@
<PoisonedReportFile>$(PackageReportDir)poisoned.txt</PoisonedReportFile>
</PropertyGroup>
<!-- The predefined environmental variable `BUILD_BUILDNUMBER` is getting overwritten in repo-projects,
so save it in a different varialbe-->
<PropertyGroup>
<VmrBuildNumber>$(BUILD_BUILDNUMBER)"</VmrBuildNumber>
</PropertyGroup>
<Import Project="$(GitInfoAllRepoPropsFile)" />
</Project>

View file

@ -9,6 +9,8 @@
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<UsingTask AssemblyFile="$(MergeAssetManifestsAssembly)" TaskName="Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests" />
<Target Name="Build">
<PropertyGroup>
<BuildModeInfoText Condition="'$(DotNetBuildSourceOnly)' == 'true'">source-build</BuildModeInfoText>
@ -25,6 +27,21 @@
StopOnFirstFailure="true" />
</Target>
<Target Name="MergeAssetManifests" AfterTargets="Build">
<PropertyGroup>
<MergedAssetManifestOutputPath>$(ArtifactsDir)VerticalManifest.xml</MergedAssetManifestOutputPath>
</PropertyGroup>
<ItemGroup>
<RepoAssetManifest Include="$(AssetManifestsIntermediateDir)\**\*.xml" />
</ItemGroup>
<Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests
AssetManifest="@(RepoAssetManifest)"
MergedAssetManifestOutputPath="$(MergedAssetManifestOutputPath)"
VmrBuildNumber="$(VmrBuildNumber)" />
</Target>
<Import Project="$(RepositoryEngineeringDir)build.sourcebuild.targets" Condition="'$(DotNetBuildSourceOnly)' == 'true'" />
<!-- Intentionally below the import to appear at the end. -->

View file

@ -17,6 +17,7 @@
BuildMSBuildSdkResolver;
BuildSdkArchiveDiff;
BuildLeakDetection;
BuildMergeAssetManifests;
ExtractToolPackage;
GenerateRootFs;
PoisonPrebuiltPackages" />
@ -126,6 +127,24 @@
Targets="Build" />
</Target>
<Target Name="BuildMergeAssetManifests"
DependsOnTargets="ExtractToolPackage;BuildMSBuildSdkResolver"
Inputs="$(MSBuildProjectFullPath)"
Outputs="$(BaseIntermediateOutputPath)MergeAssetManifests.complete">
<MSBuild Projects="tasks\Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests\Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests.csproj"
Targets="Restore"
Properties="MSBuildRestoreSessionId=$([System.Guid]::NewGuid())" />
<MSBuild Projects="tasks\Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests\Microsoft.DotNet.SourceBuild.Tasks.MergeAssetManifests.csproj"
Targets="Build" />
<MakeDir Directories="$(BaseIntermediateOutputPath)" />
<Touch Files="$(BaseIntermediateOutputPath)MergeAssetManifests.complete" AlwaysCreate="true">
<Output TaskParameter="TouchedFiles" ItemName="FileWrites" />
</Touch>
</Target>
<Target Name="GenerateRootFs"
Condition="'$(BuildOS)' != 'windows' and '$(CrossBuild)' == 'true' and '$(ROOTFS_DIR)' == ''">
<PropertyGroup>

View file

@ -0,0 +1,103 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Build.Utilities;
using Microsoft.Build.Framework;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Linq;
namespace Microsoft.DotNet.SourceBuild.Tasks
{
public class MergeAssetManifests : Task
{
/// <summary>
/// AssetManifest paths
/// </summary>
[Required]
public required ITaskItem[] AssetManifest { get; init; }
/// <summary>
/// Merged asset manifest output path
/// </summary>
[Required]
public required string MergedAssetManifestOutputPath { get; init; }
/// <summary>
/// Azure DevOps build number
/// </summary>
[Required]
public required string VmrBuildNumber { get; init; }
private static readonly string _buildIdAttribute = "BuildId";
private static readonly string _azureDevOpsBuildNumberAttribute = "AzureDevOpsBuildNumber";
private static readonly string[] _ignoredAttributes = [_buildIdAttribute, _azureDevOpsBuildNumberAttribute, "IsReleaseOnlyPackageVersion"];
public override bool Execute()
{
List<XDocument> assetManifestXmls = AssetManifest.Select(xmlPath => XDocument.Load(xmlPath.ItemSpec)).ToList();
VerifyAssetManifests(assetManifestXmls);
XElement mergedManifestRoot = assetManifestXmls.First().Root
?? throw new ArgumentException("The root element of the asset manifest is null.");
// Set the BuildId and AzureDevOpsBuildNumber attributes to the value of VmrBuildNumber
mergedManifestRoot.SetAttributeValue(_buildIdAttribute, VmrBuildNumber);
mergedManifestRoot.SetAttributeValue(_azureDevOpsBuildNumberAttribute, VmrBuildNumber);
List<XElement> packageElements = new();
List<XElement> blobElements = new();
foreach (var assetManifestXml in assetManifestXmls)
{
packageElements.AddRange(assetManifestXml.Descendants("Package"));
blobElements.AddRange(assetManifestXml.Descendants("Blob"));
}
packageElements = packageElements.OrderBy(packageElement => packageElement.Attribute("Id")?.Value).ToList();
blobElements = blobElements.OrderBy(blobElement => blobElement.Attribute("Id")?.Value).ToList();
XDocument verticalManifest = new(new XElement(mergedManifestRoot.Name, mergedManifestRoot.Attributes(), packageElements, blobElements));
File.WriteAllText(MergedAssetManifestOutputPath, verticalManifest.ToString());
return !Log.HasLoggedErrors;
}
private static void VerifyAssetManifests(IReadOnlyList<XDocument> assetManifestXmls)
{
if (assetManifestXmls.Count == 0)
{
throw new ArgumentException("No asset manifests were provided.");
}
HashSet<string> rootAttributes = assetManifestXmls
.First()
.Root?
.Attributes()
.Select(attribute => attribute.ToString())
.ToHashSet()
?? throw new ArgumentException("The root element of the asset manifest is null.");
if (assetManifestXmls.Skip(1).Any(manifest => manifest.Root?.Attributes().Count() != rootAttributes.Count))
{
throw new ArgumentException("The asset manifests do not have the same number of root attributes.");
}
if (assetManifestXmls.Skip(1).Any(assetManifestXml =>
!assetManifestXml.Root?.Attributes().Select(attribute => attribute.ToString())
.All(attribute =>
// Ignore BuildId and AzureDevOpsBuildNumber attributes, they're different for different repos,
// TODO this should be fixed with https://github.com/dotnet/source-build/issues/3934
_ignoredAttributes.Any(ignoredAttribute => attribute.StartsWith(ignoredAttribute)) || rootAttributes.Contains(attribute))
?? false))
{
throw new ArgumentException("The asset manifests do not have the same root attributes.");
}
}
}
}

View file

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>$(NetCurrent)</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Build.Utilities.Core" Version="$(MicrosoftBuildVersion)" />
</ItemGroup>
<ItemGroup>
<ReferencePath Include="@(SdkAssembly)" />
</ItemGroup>
</Project>