PVP flow support (#15267)
Co-authored-by: Michael Simons <msimons@microsoft.com>
This commit is contained in:
parent
9962c6a686
commit
987040517a
7 changed files with 389 additions and 202 deletions
|
@ -119,9 +119,6 @@
|
|||
<SourceBuiltToolsetDir>$(LocalBlobStorageRoot)Sdk/</SourceBuiltToolsetDir>
|
||||
<SourceBuiltRuntimeDir>$(LocalBlobStorageRoot)Runtime/</SourceBuiltRuntimeDir>
|
||||
<SourceBuiltAspNetCoreRuntime>$(LocalBlobStorageRoot)aspnetcore/Runtime/</SourceBuiltAspNetCoreRuntime>
|
||||
<RestoreSourcePropsPath>$(IntermediatePath)RestoreSources.props</RestoreSourcePropsPath>
|
||||
<PackageVersionPropsPath>$(IntermediatePath)PackageVersions.props</PackageVersionPropsPath>
|
||||
<CurrentSourceBuiltPackageVersionPropsPath>$(IntermediatePath)CurrentSourceBuiltPackageVersions.props</CurrentSourceBuiltPackageVersionPropsPath>
|
||||
<LoggingDir>$(BaseOutputPath)logs/</LoggingDir>
|
||||
<MSBuildDebugPathTargetDir>$(BaseOutputPath)msbuild-debug/</MSBuildDebugPathTargetDir>
|
||||
<RoslynDebugPathTargetDir>$(BaseOutputPath)roslyn-debug/</RoslynDebugPathTargetDir>
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="NuGetPack" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ZipFileExtractToDirectory" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ReplaceTextInFile" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ReplaceRegexInFiles" />
|
||||
|
||||
<ItemGroup>
|
||||
<BuildTasksTarget Include="Restore;Build;InstallResolver" />
|
||||
|
@ -23,7 +22,6 @@
|
|||
<CallTarget Targets="
|
||||
UnpackTarballs;
|
||||
BuildXPlatTasks;
|
||||
PatchPackageVersions;
|
||||
BuildLeakDetection;
|
||||
ExtractToolPackage;
|
||||
GenerateRootFs;
|
||||
|
@ -67,25 +65,6 @@
|
|||
|
||||
<Copy SourceFiles="@(UnpackedSourceBuildReferencePackages)" DestinationFiles="$(ReferencePackagesDir)%(Filename)%(Extension)" />
|
||||
|
||||
<!-- Setup the PackageVersions.props file to be a combination of source built and previously source built packages -->
|
||||
<Copy SourceFiles="$(PrebuiltSourceBuiltPackagesPath)PackageVersions.props" DestinationFiles="$(IntermediatePath)PreviouslySourceBuiltPackageVersions.props" />
|
||||
|
||||
<PropertyGroup>
|
||||
<PackageVersionsPropsFile>$(IntermediatePath)PackageVersions.props</PackageVersionsPropsFile>
|
||||
<PackageVersionsPropsContents>
|
||||
<![CDATA[<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="PreviouslySourceBuiltPackageVersions.props" Condition="Exists('PreviouslySourceBuiltPackageVersions.props')" />
|
||||
<Import Project="CurrentSourceBuiltPackageVersions.props" Condition="Exists('CurrentSourceBuiltPackageVersions.props')" />
|
||||
</Project>
|
||||
]]>
|
||||
</PackageVersionsPropsContents>
|
||||
</PropertyGroup>
|
||||
|
||||
<WriteLinesToFile File="$(PackageVersionsPropsFile)"
|
||||
Lines="$(PackageVersionsPropsContents)"
|
||||
Overwrite="true" />
|
||||
|
||||
<WriteLinesToFile File="$(CompletedSemaphorePath)UnpackTarballs.complete" Overwrite="true" />
|
||||
</Target>
|
||||
|
||||
|
@ -107,16 +86,6 @@
|
|||
<WriteLinesToFile File="$(CompletedSemaphorePath)BuildXPlatTasks.complete" Overwrite="true" />
|
||||
</Target>
|
||||
|
||||
<!-- TODO: Remove this when the .NET 8 artifacts tarball no longer includes MicrosoftAspNetCoreAppRuntimePackageVersion -->
|
||||
<Target Name="PatchPackageVersions">
|
||||
<!-- Rename MicrosoftAspNetCoreAppRuntimePackageVersion so it isn't used
|
||||
Fixes https://github.com/dotnet/installer/issues/14492 -->
|
||||
<ReplaceRegexInFiles
|
||||
InputFiles="$(IntermediatePath)PreviouslySourceBuiltPackageVersions.props"
|
||||
OldTextRegex="\bMicrosoftAspNetCoreAppRuntimePackageVersion\b"
|
||||
NewText="__unused" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildLeakDetection"
|
||||
DependsOnTargets="ExtractToolPackage"
|
||||
Inputs="$(MSBuildProjectFullPath)"
|
||||
|
|
|
@ -16,8 +16,8 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.UsageReport
|
|||
{
|
||||
public class WriteUsageReports : Task
|
||||
{
|
||||
private const string SnapshotPrefix = "PackageVersions.props.pre.";
|
||||
private const string SnapshotSuffix = ".xml";
|
||||
private const string SnapshotPrefix = "PackageVersions.";
|
||||
private const string SnapshotSuffix = ".Current.props";
|
||||
|
||||
/// <summary>
|
||||
/// Source usage data JSON file.
|
||||
|
@ -26,7 +26,7 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.UsageReport
|
|||
public string DataFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A set of "PackageVersions.props.pre.{repo}.xml" files. They are analyzed to find
|
||||
/// A set of "PackageVersions.{repo}.Current.props" files. They are analyzed to find
|
||||
/// packages built during source-build, and which repo built them. This info is added to the
|
||||
/// report. New packages are associated to a repo by going through each PVP in ascending
|
||||
/// file modification order.
|
||||
|
@ -114,7 +114,7 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.UsageReport
|
|||
string id = usage.PackageIdentity.Id;
|
||||
string version = usage.PackageIdentity.Version.OriginalVersion;
|
||||
|
||||
string pvpIdent = WriteBuildOutputProps.GetPropertyName(id);
|
||||
string pvpIdent = WritePackageVersionsProps.GetPropertyName(id, WritePackageVersionsProps.VersionPropertySuffix);
|
||||
|
||||
var sourceBuildCreator = new StringBuilder();
|
||||
foreach (RepoOutput output in sourceBuildRepoOutputs)
|
||||
|
@ -200,7 +200,7 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.UsageReport
|
|||
// Get the creation time element.
|
||||
?.Element(snapshot.Xml
|
||||
.GetDefaultNamespace()
|
||||
.GetName(WriteBuildOutputProps.CreationTimePropertyName))
|
||||
.GetName(WritePackageVersionsProps.CreationTimePropertyName))
|
||||
?.Value;
|
||||
|
||||
if (string.IsNullOrEmpty(creationTime))
|
||||
|
|
|
@ -1,142 +0,0 @@
|
|||
// 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.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Versioning;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Microsoft.DotNet.Build.Tasks
|
||||
{
|
||||
public class WriteBuildOutputProps : Task
|
||||
{
|
||||
private static readonly Regex InvalidElementNameCharRegex = new Regex(@"(^|[^A-Za-z0-9])(?<FirstPartChar>.)");
|
||||
|
||||
public const string CreationTimePropertyName = "BuildOutputPropsCreationTime";
|
||||
|
||||
[Required]
|
||||
public ITaskItem[] NuGetPackages { get; set; }
|
||||
|
||||
[Required]
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a second PropertyGroup to the output XML containing a property with the time of
|
||||
/// creation in UTC DateTime Ticks. This can be used to track creation time in situations
|
||||
/// where file metadata isn't reliable or preserved.
|
||||
/// </summary>
|
||||
public bool IncludeCreationTimeProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Properties to add to the build output props, which may not exist as nupkgs.
|
||||
/// FOr example, this is used to pass the version of the CLI toolset archives.
|
||||
///
|
||||
/// %(Identity): Package identity.
|
||||
/// %(Version): Package version.
|
||||
/// </summary>
|
||||
public ITaskItem[] ExtraProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Additional assets to be added to the build output props.
|
||||
/// i.e. /bin/obj/x64/Release/blobs/Toolset/3.0.100
|
||||
/// This parameter is the <pathToAsset>/<assetName> portion only, and the asset
|
||||
/// must be in a <AdditionalAssetDir>/<assetVersion> folder.
|
||||
/// </summary>
|
||||
public string[] AdditionalAssetDirs { get; set; }
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
PackageIdentity[] latestPackages = NuGetPackages
|
||||
.Select(item =>
|
||||
{
|
||||
using (var reader = new PackageArchiveReader(item.GetMetadata("FullPath")))
|
||||
{
|
||||
return reader.GetIdentity();
|
||||
}
|
||||
})
|
||||
.GroupBy(identity => identity.Id)
|
||||
.Select(g => g.OrderBy(id => id.Version).Last())
|
||||
.OrderBy(id => id.Id)
|
||||
.ToArray();
|
||||
|
||||
var additionalAssets = (AdditionalAssetDirs ?? new string[0])
|
||||
.Where(Directory.Exists)
|
||||
.Where(dir => Directory.GetDirectories(dir).Count() > 0)
|
||||
.Select(dir => new {
|
||||
Name = new DirectoryInfo(dir).Name + "Version",
|
||||
Version = new DirectoryInfo(Directory.EnumerateDirectories(dir).OrderBy(s => s).Last()).Name
|
||||
}).ToArray();
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));
|
||||
|
||||
using (var outStream = File.Open(OutputPath, FileMode.Create))
|
||||
using (var sw = new StreamWriter(outStream, new UTF8Encoding(false)))
|
||||
{
|
||||
sw.WriteLine(@"<?xml version=""1.0"" encoding=""utf-8""?>");
|
||||
sw.WriteLine(@"<Project ToolsVersion=""14.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">");
|
||||
sw.WriteLine(@" <PropertyGroup>");
|
||||
foreach (PackageIdentity packageIdentity in latestPackages)
|
||||
{
|
||||
string propertyName = GetPropertyName(packageIdentity.Id);
|
||||
sw.WriteLine($" <{propertyName}>{packageIdentity.Version}</{propertyName}>");
|
||||
|
||||
propertyName = GetAlternatePropertyName(packageIdentity.Id);
|
||||
sw.WriteLine($" <{propertyName}>{packageIdentity.Version}</{propertyName}>");
|
||||
}
|
||||
foreach (var extraProp in ExtraProperties ?? Enumerable.Empty<ITaskItem>())
|
||||
{
|
||||
string propertyName = extraProp.GetMetadata("Identity");
|
||||
bool doNotOverwrite = false;
|
||||
string overwriteCondition = string.Empty;
|
||||
if (bool.TryParse(extraProp.GetMetadata("DoNotOverwrite"), out doNotOverwrite) && doNotOverwrite)
|
||||
{
|
||||
overwriteCondition = $" Condition=\"'$({propertyName})' == ''\"";
|
||||
}
|
||||
sw.WriteLine($" <{propertyName}{overwriteCondition}>{extraProp.GetMetadata("Version")}</{propertyName}>");
|
||||
}
|
||||
foreach (var additionalAsset in additionalAssets)
|
||||
{
|
||||
sw.WriteLine($" <{additionalAsset.Name}>{additionalAsset.Version}</{additionalAsset.Name}>");
|
||||
}
|
||||
sw.WriteLine(@" </PropertyGroup>");
|
||||
if (IncludeCreationTimeProperty)
|
||||
{
|
||||
sw.WriteLine(@" <PropertyGroup>");
|
||||
sw.WriteLine($@" <{CreationTimePropertyName}>{DateTime.UtcNow.Ticks}</{CreationTimePropertyName}>");
|
||||
sw.WriteLine(@" </PropertyGroup>");
|
||||
}
|
||||
sw.WriteLine(@"</Project>");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static string GetPropertyName(string id)
|
||||
{
|
||||
string formattedId = InvalidElementNameCharRegex.Replace(
|
||||
id,
|
||||
match => match.Groups?["FirstPartChar"].Value.ToUpperInvariant()
|
||||
?? string.Empty);
|
||||
|
||||
return $"{formattedId}PackageVersion";
|
||||
}
|
||||
|
||||
public static string GetAlternatePropertyName(string id)
|
||||
{
|
||||
string formattedId = InvalidElementNameCharRegex.Replace(
|
||||
id,
|
||||
match => match.Groups?["FirstPartChar"].Value.ToUpperInvariant()
|
||||
?? string.Empty);
|
||||
|
||||
return $"{formattedId}Version";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,326 @@
|
|||
// 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.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using NuGet.Packaging;
|
||||
using NuGet.Packaging.Core;
|
||||
using NuGet.Versioning;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Xml;
|
||||
|
||||
namespace Microsoft.DotNet.Build.Tasks
|
||||
{
|
||||
public class VersionEntry
|
||||
{
|
||||
public string Name;
|
||||
public string Version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a props file that is used as the input for a repo-level build. The props file
|
||||
/// includes package version numbers that should be used by the repo build and additional special properties.
|
||||
///
|
||||
/// There are two types of input props that can be written:
|
||||
/// - Versions of union of all packages produced by the builds are added. (AllPackages)
|
||||
/// - Only versions of packages that are listed as dependencies of a repo are added. (DependenciesOnly)
|
||||
///
|
||||
/// The former represents the current way that source build works for most repos. The latter represents the desired
|
||||
/// methodology (PVP Flow). PVP flow closely matches how the product is built in non-source-build mode.
|
||||
/// </summary>
|
||||
public class WritePackageVersionsProps : Microsoft.Build.Utilities.Task
|
||||
{
|
||||
private static readonly Regex InvalidElementNameCharRegex = new Regex(@"(^|[^A-Za-z0-9])(?<FirstPartChar>.)");
|
||||
|
||||
public const string CreationTimePropertyName = "BuildOutputPropsCreationTime";
|
||||
public const string VersionPropertySuffix = "Version";
|
||||
private const string VersionPropertyAlternateSuffix = "PackageVersion";
|
||||
private const string PinnedAttributeName = "Pinned";
|
||||
private const string DependencyAttributeName = "Dependency";
|
||||
private const string NameAttributeName = "Name";
|
||||
|
||||
private const string AllPackagesVersionPropsFlowType = "AllPackages";
|
||||
private const string DependenciesOnlyVersionPropsFlowType = "DependenciesOnly";
|
||||
private const string DefaultVersionPropsFlowType = AllPackagesVersionPropsFlowType;
|
||||
|
||||
/// <summary>
|
||||
/// Set of input nuget package files to generate version properties for.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public ITaskItem[] NuGetPackages { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// File where the version properties should be written.
|
||||
/// </summary>
|
||||
[Required]
|
||||
public string OutputPath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds a second PropertyGroup to the output XML containing a property with the time of
|
||||
/// creation in UTC DateTime Ticks. This can be used to track creation time in situations
|
||||
/// where file metadata isn't reliable or preserved.
|
||||
/// </summary>
|
||||
public bool IncludeCreationTimeProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Properties to add to the build output props, which may not exist as nupkgs.
|
||||
/// FOr example, this is used to pass the version of the CLI toolset archives.
|
||||
///
|
||||
/// %(Identity): Package identity.
|
||||
/// %(Version): Package version.
|
||||
/// </summary>
|
||||
public ITaskItem[] ExtraProperties { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Additional assets to be added to the build output props.
|
||||
/// i.e. /bin/obj/x64/Release/blobs/Toolset/3.0.100
|
||||
/// This parameter is the <pathToAsset>/<assetName> portion only, and the asset
|
||||
/// must be in a <AdditionalAssetDir>/<assetVersion> folder.
|
||||
/// </summary>
|
||||
public string[] AdditionalAssetDirs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Indicates which properties will be written into the Version props file.
|
||||
/// If AllPackages (Default), all packages from previously built repos will be written.
|
||||
/// If DependenciesOnly, then only those packages appearing as dependencies in
|
||||
/// Version.Details.xml will show up. The VersionsDetails property must be set to a
|
||||
/// valid Version.Details.xml path when DependenciesOnly is used.
|
||||
/// </summary>
|
||||
public string VersionPropsFlowType { get; set; } = DefaultVersionPropsFlowType;
|
||||
|
||||
/// <summary>
|
||||
/// If VersionPropsFlowType is set to DependenciesOnly, should be the path to the Version.Detail.xml file for the repo.
|
||||
/// </summary>
|
||||
public string VersionDetails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the set of the dependencies from the repo's Version.Details.Xml file.
|
||||
/// </summary>
|
||||
/// <returns>Hash set of dependency names. </returns>
|
||||
private HashSet<string> GetDependences()
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
|
||||
try
|
||||
{
|
||||
document.Load(VersionDetails);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.LogErrorFromException(e);
|
||||
return null;
|
||||
}
|
||||
|
||||
HashSet<string> dependencyNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
// Load the nodes, filter those that are not pinned, and
|
||||
XmlNodeList dependencyNodes = document.DocumentElement.SelectNodes($"//{DependencyAttributeName}");
|
||||
|
||||
foreach (XmlNode dependency in dependencyNodes)
|
||||
{
|
||||
if (dependency.NodeType == XmlNodeType.Comment || dependency.NodeType == XmlNodeType.Whitespace)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isPinned = false;
|
||||
XmlAttribute pinnedAttribute = dependency.Attributes[PinnedAttributeName];
|
||||
if (pinnedAttribute != null && !bool.TryParse(pinnedAttribute.Value, out isPinned))
|
||||
{
|
||||
Log.LogError($"The '{PinnedAttributeName}' attribute is set but the value " +
|
||||
$"'{pinnedAttribute.Value}' is not a valid boolean...");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (isPinned)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var name = dependency.Attributes[NameAttributeName]?.Value?.Trim();
|
||||
|
||||
if (string.IsNullOrEmpty(name))
|
||||
{
|
||||
Log.LogError($"The '{NameAttributeName}' attribute must be specified.");
|
||||
return null;
|
||||
}
|
||||
|
||||
dependencyNames.Add(name);
|
||||
}
|
||||
|
||||
return dependencyNames;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Filter a set of input dependencies to those that appear in <paramref name="dependencies"/>
|
||||
/// </summary>
|
||||
/// <param name="input">Input set of entries</param>
|
||||
/// <param name="dependencies">Set of dependencies</param>
|
||||
/// <returns>Set of <paramref name="input"/> that appears in <paramref name="dependencies"/></returns>
|
||||
private IEnumerable<VersionEntry> FilterNonDependencies(IEnumerable<VersionEntry> input, HashSet<string> dependencies)
|
||||
{
|
||||
return input.Where(entry => dependencies.Contains(entry.Name));
|
||||
}
|
||||
|
||||
public override bool Execute()
|
||||
{
|
||||
if (VersionPropsFlowType != AllPackagesVersionPropsFlowType &&
|
||||
VersionPropsFlowType != DependenciesOnlyVersionPropsFlowType)
|
||||
{
|
||||
Log.LogError($"Valid version flow types are '{DependenciesOnlyVersionPropsFlowType}' and '{AllPackagesVersionPropsFlowType}'");
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
if (VersionPropsFlowType == DependenciesOnlyVersionPropsFlowType && (string.IsNullOrEmpty(VersionDetails) || !File.Exists(VersionDetails)))
|
||||
{
|
||||
Log.LogError($"When version flow type is DependenciesOnly, the VersionDetails task parameter must point to a valid path to the Version.Details.xml file for the repo. " +
|
||||
"Provided file path '{VersionDetails}' does not exist.");
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
// First, obtain version information from the packages and additional assets that
|
||||
// are provided.
|
||||
var latestPackages = NuGetPackages
|
||||
.Select(item =>
|
||||
{
|
||||
using (var reader = new PackageArchiveReader(item.GetMetadata("FullPath")))
|
||||
{
|
||||
return reader.GetIdentity();
|
||||
}
|
||||
})
|
||||
.GroupBy(identity => identity.Id)
|
||||
.Select(g => g.OrderBy(id => id.Version).Last())
|
||||
.OrderBy(id => id.Id)
|
||||
.Select(identity => new VersionEntry()
|
||||
{
|
||||
Name = identity.Id,
|
||||
Version = identity.Version.ToString()
|
||||
});
|
||||
|
||||
var additionalAssets = (AdditionalAssetDirs ?? new string[0])
|
||||
.Where(Directory.Exists)
|
||||
.Where(dir => Directory.GetDirectories(dir).Count() > 0)
|
||||
.Select(dir => new VersionEntry()
|
||||
{
|
||||
Name = new DirectoryInfo(dir).Name,
|
||||
Version = new DirectoryInfo(Directory.EnumerateDirectories(dir).OrderBy(s => s).Last()).Name
|
||||
});
|
||||
|
||||
var packageElementsToWrite = latestPackages;
|
||||
var additionalAssetElementsToWrite = additionalAssets;
|
||||
|
||||
// Then, if version flow type is "DependenciesOnly", filter those
|
||||
// dependencies that do not appear in the version.details.xml file.
|
||||
if (VersionPropsFlowType == DependenciesOnlyVersionPropsFlowType)
|
||||
{
|
||||
var dependencies = GetDependences();
|
||||
|
||||
if (Log.HasLoggedErrors)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
packageElementsToWrite = FilterNonDependencies(packageElementsToWrite, dependencies);
|
||||
additionalAssetElementsToWrite = FilterNonDependencies(additionalAssetElementsToWrite, dependencies);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(OutputPath));
|
||||
|
||||
using (var outStream = File.Open(OutputPath, FileMode.Create))
|
||||
using (var sw = new StreamWriter(outStream, new UTF8Encoding(false)))
|
||||
{
|
||||
sw.WriteLine(@"<?xml version=""1.0"" encoding=""utf-8""?>");
|
||||
sw.WriteLine(@"<Project ToolsVersion=""14.0"" xmlns=""http://schemas.microsoft.com/developer/msbuild/2003"">");
|
||||
|
||||
WriteVersionEntries(sw, packageElementsToWrite, "packages");
|
||||
WriteExtraProperties(sw);
|
||||
WriteVersionEntries(sw, additionalAssetElementsToWrite, "additional assets");
|
||||
|
||||
if (IncludeCreationTimeProperty)
|
||||
{
|
||||
sw.WriteLine(@" <PropertyGroup>");
|
||||
sw.WriteLine($@" <{CreationTimePropertyName}>{DateTime.UtcNow.Ticks}</{CreationTimePropertyName}>");
|
||||
sw.WriteLine(@" </PropertyGroup>");
|
||||
}
|
||||
|
||||
sw.WriteLine(@"</Project>");
|
||||
}
|
||||
|
||||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write properties specified in the "ExtraProperties task parameter
|
||||
/// </summary>
|
||||
/// <param name="sw">Stream writer</param>
|
||||
private void WriteExtraProperties(StreamWriter sw)
|
||||
{
|
||||
if (ExtraProperties == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sw.WriteLine(@" <!-- Extra properties -->");
|
||||
sw.WriteLine(@" <PropertyGroup>");
|
||||
|
||||
foreach (var extraProp in ExtraProperties ?? Enumerable.Empty<ITaskItem>())
|
||||
{
|
||||
string propertyName = extraProp.GetMetadata("Identity");
|
||||
bool doNotOverwrite = false;
|
||||
string overwriteCondition = string.Empty;
|
||||
if (bool.TryParse(extraProp.GetMetadata("DoNotOverwrite"), out doNotOverwrite) && doNotOverwrite)
|
||||
{
|
||||
overwriteCondition = $" Condition=\"'$({propertyName})' == ''\"";
|
||||
}
|
||||
sw.WriteLine($" <{propertyName}{overwriteCondition}>{extraProp.GetMetadata("Version")}</{propertyName}>");
|
||||
}
|
||||
|
||||
sw.WriteLine(@" </PropertyGroup>");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write properties for the version numbers required for this repo.
|
||||
/// </summary>
|
||||
/// <param name="sw">Stream writer</param>
|
||||
/// <param name="entries">Version entries</param>
|
||||
private void WriteVersionEntries(StreamWriter sw, IEnumerable<VersionEntry> entries, string entryType)
|
||||
{
|
||||
if (!entries.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sw.WriteLine($" <!-- Versions of {entryType} produced by earlier stages of the build -->");
|
||||
if (VersionPropsFlowType == DependenciesOnlyVersionPropsFlowType)
|
||||
{
|
||||
sw.WriteLine(@" <!-- Only those packages/assets that are explicit dependencies of this repo are included. -->");
|
||||
}
|
||||
sw.WriteLine(@" <PropertyGroup>");
|
||||
foreach (var package in entries)
|
||||
{
|
||||
string propertyName = GetPropertyName(package.Name, VersionPropertySuffix);
|
||||
string alternatePropertyName = GetPropertyName(package.Name, VersionPropertyAlternateSuffix);
|
||||
|
||||
sw.WriteLine($" <{propertyName}>{package.Version}</{propertyName}>");
|
||||
sw.WriteLine($" <{alternatePropertyName}>{package.Version}</{alternatePropertyName}>");
|
||||
}
|
||||
sw.WriteLine(@" </PropertyGroup>");
|
||||
}
|
||||
|
||||
public static string GetPropertyName(string id, string suffix)
|
||||
{
|
||||
string formattedId = InvalidElementNameCharRegex.Replace(
|
||||
id,
|
||||
match => match.Groups?["FirstPartChar"].Value.ToUpperInvariant()
|
||||
?? string.Empty);
|
||||
|
||||
return $"{formattedId}{suffix}";
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,6 +22,12 @@
|
|||
Repo specific semaphore path for incremental build
|
||||
-->
|
||||
<RepoCompletedSemaphorePath>$(CompletedSemaphorePath)$(RepositoryName)/</RepoCompletedSemaphorePath>
|
||||
|
||||
<!-- Paths to the version props files -->
|
||||
<CurrentSourceBuiltPackageVersionPropsPath>$(IntermediatePath)PackageVersions.$(RepositoryName).Current.props</CurrentSourceBuiltPackageVersionPropsPath>
|
||||
<PreviouslySourceBuiltPackageVersionPropsPath>$(IntermediatePath)PackageVersions.$(RepositoryName).Previous.props</PreviouslySourceBuiltPackageVersionPropsPath>
|
||||
<PackageVersionPropsPath>$(IntermediatePath)PackageVersions.$(RepositoryName).props</PackageVersionPropsPath>
|
||||
<PackageVersionPropsFlowType>AllPackages</PackageVersionPropsFlowType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(OS)' == 'Windows_NT'">
|
||||
|
|
|
@ -13,12 +13,13 @@
|
|||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="UpdateJson" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="UpdateNuGetConfigPackageSourcesMappings" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ValidateUsageAgainstBaseline" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="WriteBuildOutputProps" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="WritePackageVersionsProps" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="WritePackageUsageData" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="WriteUsageReports" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="WriteVersionsFile" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ZipFileExtractToDirectory" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ReplaceTextInFile" />
|
||||
<UsingTask AssemblyFile="$(XPlatSourceBuildTasksAssembly)" TaskName="ReplaceRegexInFiles" />
|
||||
|
||||
<!--
|
||||
Central property to define that a repo doesn't implement any of the Repo API. If a repo adds an
|
||||
|
@ -169,7 +170,6 @@
|
|||
<ExtraSourcesNuGetSourceName>ExtraSources</ExtraSourcesNuGetSourceName>
|
||||
<SourceBuildSources>$(PrebuiltNuGetSourceName);$(PreviouslySourceBuiltNuGetSourceName);$(ReferencePackagesNuGetSourceName);$(SourceBuiltNuGetSourceName)</SourceBuildSources>
|
||||
<SourceBuildSources Condition="'$(ExtraRestoreSourcePath)' != ''">$(SourceBuildSources);$(ExtraSourcesNuGetSourceName)</SourceBuildSources>
|
||||
<SourceBuildSources Condition="'$(VSS_NUGET_EXTERNAL_FEED_ENDPOINTS)' != '' and '$(SetUpInternalTransportFeed)' == 'true'">$(SourceBuildSources);$(DotNet5InternalTransportNuGetSourceName)</SourceBuildSources>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Update the detected or manually specified NuGetConfigFile, but also allow multiple. -->
|
||||
|
@ -232,36 +232,67 @@
|
|||
<WriteLinesToFile File="$(RepoCompletedSemaphorePath)UpdateGlobalJsonVersions.complete" Overwrite="true" />
|
||||
</Target>
|
||||
|
||||
<Target Name="CreateBuildOutputProps"
|
||||
<!-- Before a repository builds, set up the version property files that override the repo's defaults.
|
||||
There are 3 files generated -->
|
||||
<Target Name="CreateBuildInputProps"
|
||||
BeforeTargets="Build"
|
||||
Inputs="$(MSBuildProjectFullPath)"
|
||||
Outputs="$(RepoCompletedSemaphorePath)CreateBuildOutputProps.complete">
|
||||
<PropertyGroup>
|
||||
<_PackageVersionPropsBackupPath>$(PackageVersionPropsPath).pre.$(RepositoryName).xml</_PackageVersionPropsBackupPath>
|
||||
</PropertyGroup>
|
||||
Outputs="$(RepoCompletedSemaphorePath)CreateBuildInputProps.complete">
|
||||
|
||||
<ItemGroup>
|
||||
<PreviouslySourceBuiltPackages Include="$(SourceBuiltPackagesPath)*.nupkg"
|
||||
Exclude="$(SourceBuiltPackagesPath)*.symbols.nupkg" />
|
||||
<_AdditionalAssetDirs Include="$(SourceBuiltToolsetDir)" Condition="Exists('$(SourceBuiltToolsetDir)')" />
|
||||
<_CurrentSourceBuiltPackages Include="$(SourceBuiltPackagesPath)*.nupkg"
|
||||
Exclude="$(SourceBuiltPackagesPath)*.symbols.nupkg" />
|
||||
<_PreviouslyBuiltSourceBuiltPackages Include="$(PrebuiltSourceBuiltPackagesPath)*.nupkg" />
|
||||
|
||||
<_CurrentAdditionalAssetDirs Include="$(SourceBuiltToolsetDir)" Condition="Exists('$(SourceBuiltToolsetDir)')" />
|
||||
</ItemGroup>
|
||||
|
||||
<WriteBuildOutputProps NuGetPackages="@(PreviouslySourceBuiltPackages)"
|
||||
<Error Condition="'$(PackageVersionPropsFlowType)' != 'AllPackages' and '$(PackageVersionPropsFlowType)' != 'DependenciesOnly'"
|
||||
Text="Invalid PackageVersionPropsFlowType '$(PackageVersionPropsFlowType)'. Must be 'AllPackages' or 'DependenciesOnly'." />
|
||||
|
||||
<PropertyGroup>
|
||||
<_VersionDetailsXml Condition="'$(PackageVersionPropsFlowType)' == 'DependenciesOnly'">$(ProjectDirectory)/eng/Version.Details.xml</_VersionDetailsXml>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Write the build input properties, then save off a copy that will be used for generating usage reports later -->
|
||||
<WritePackageVersionsProps NuGetPackages="@(_CurrentSourceBuiltPackages)"
|
||||
ExtraProperties="@(ExtraPackageVersionPropsPackageInfo)"
|
||||
AdditionalAssetDirs="@(_AdditionalAssetDirs)"
|
||||
VersionPropsFlowType="$(PackageVersionPropsFlowType)"
|
||||
VersionDetails="$(_VersionDetailsXml)"
|
||||
AdditionalAssetDirs="@(_CurrentAdditionalAssetDirs)"
|
||||
OutputPath="$(CurrentSourceBuiltPackageVersionPropsPath)" />
|
||||
|
||||
<WriteBuildOutputProps NuGetPackages="@(PreviouslySourceBuiltPackages)"
|
||||
IncludeCreationTimeProperty="true"
|
||||
OutputPath="$(_PackageVersionPropsBackupPath)" />
|
||||
<!-- Create previously source-built inputs info -->
|
||||
<WritePackageVersionsProps NuGetPackages="@(_PreviouslyBuiltSourceBuiltPackages)"
|
||||
VersionPropsFlowType="$(PackageVersionPropsFlowType)"
|
||||
VersionDetails="$(_VersionDetailsXml)"
|
||||
OutputPath="$(PreviouslySourceBuiltPackageVersionPropsPath)" />
|
||||
|
||||
<Message Importance="High" Text="$(RepositoryName) using package version properties saved at $(_PackageVersionPropsBackupPath) " />
|
||||
<!-- Rename MicrosoftAspNetCoreAppRuntimePackageVersion so it isn't used
|
||||
Fixes https://github.com/dotnet/installer/issues/14492 -->
|
||||
<ReplaceRegexInFiles InputFiles="$(PreviouslySourceBuiltPackageVersionPropsPath)"
|
||||
OldTextRegex="\bMicrosoftAspNetCoreAppRuntimePackageVersion\b"
|
||||
NewText="__unused" />
|
||||
|
||||
<ReadNuGetPackageInfos PackagePaths="@(PreviouslySourceBuiltPackages)">
|
||||
<Output TaskParameter="PackageInfoItems" ItemName="_PreviouslySourceBuiltPackageInfos" />
|
||||
</ReadNuGetPackageInfos>
|
||||
<!-- Write a single file that contains imports for both the current and previously built packages -->
|
||||
<PropertyGroup>
|
||||
<PackageVersionsPropsContents>
|
||||
<![CDATA[<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(PreviouslySourceBuiltPackageVersionPropsPath)" />
|
||||
<Import Project="$(CurrentSourceBuiltPackageVersionPropsPath)" />
|
||||
</Project>
|
||||
]]>
|
||||
</PackageVersionsPropsContents>
|
||||
</PropertyGroup>
|
||||
|
||||
<WriteLinesToFile File="$(RepoCompletedSemaphorePath)CreateBuildOutputProps.complete" Overwrite="true" />
|
||||
<WriteLinesToFile File="$(PackageVersionPropsPath)"
|
||||
Lines="$(PackageVersionsPropsContents)"
|
||||
Overwrite="true" />
|
||||
|
||||
<Message Importance="High" Text="$(RepositoryName) using package version properties saved at $(CurrentSourceBuiltPackageVersionPropsPath) and $(PreviouslySourceBuiltPackageVersionPropsPath)" />
|
||||
|
||||
<WriteLinesToFile File="$(RepoCompletedSemaphorePath)CreateBuildInputProps.complete" Overwrite="true" />
|
||||
</Target>
|
||||
|
||||
<Target Name="Build"
|
||||
|
@ -547,7 +578,7 @@
|
|||
<ItemGroup>
|
||||
<_PackagesNotCreatedReason Include="^ There may have been a silent failure in the submodule build. To confirm, check the build log file for undetected errors that may have prevented package creation: $(RepoConsoleLogFile)" />
|
||||
<_PackagesNotCreatedReason Include="^ This error might be a false positive if $(RepositoryName) intentionally builds no nuget packages. If so, set the SkipEnsurePackagesCreated property to true in $(MSBuildProjectFullPath)" />
|
||||
<_PackagesNotCreatedReason Include="^ The 'bin' directory might be dirty from a previous build and the package files already existed. If so, perform a clean build, or check which packages were already in 'bin' by opening $(_PackageVersionPropsBackupPath)" />
|
||||
<_PackagesNotCreatedReason Include="^ The 'bin' directory might be dirty from a previous build and the package files already existed. If so, perform a clean build, or check which packages were already in 'bin' by opening $(CurrentSourceBuiltPackageVersionPropsPath)" />
|
||||
<_PackagesNotCreatedReason Include="^ The packages may have been written to an unexpected directory. For example, some repos used bin/ and changed to artifacts/ to match Arcade. Check PackagesOutput in $(MSBuildProjectFullPath) (currently '$(PackagesOutput)')" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Loading…
Reference in a new issue