Use artifact info to correctly analyze the packages produced from a repository

This commit is contained in:
Nate McMaster 2017-09-15 13:17:49 -07:00
parent 8276bd163e
commit a43fb2271e
5 changed files with 98 additions and 43 deletions

View File

@ -108,7 +108,14 @@
<Target Name="BuildRepositories" <Target Name="BuildRepositories"
DependsOnTargets="_PrepareRepositories;_CreateRepositoriesListWithCommits;_UpdateNuGetConfig;Graph;_BuildRepositories" /> DependsOnTargets="_PrepareRepositories;_CreateRepositoriesListWithCommits;_UpdateNuGetConfig;Graph;_BuildRepositories" />
<Target Name="ResolveSolutions" DependsOnTargets="_PrepareRepositories"> <Target Name="ResolveRepoInfo" DependsOnTargets="_PrepareRepositories">
<MSBuild Projects="$(MSBuildProjectFullPath)"
Targets="GetArtifactInfo"
Properties="RepositoryRoot=$(_CloneRepositoryRoot)%(Repository.Identity)\;Configuration=$(Configuration);BuildNumber=$(BuildNumber)"
ContinueOnError="WarnAndContinue">
<Output TaskParameter="TargetOutputs" ItemName="ArtifactInfo" />
</MSBuild>
<MSBuild Projects="$(MSBuildProjectFullPath)" <MSBuild Projects="$(MSBuildProjectFullPath)"
Targets="ResolveSolutions" Targets="ResolveSolutions"
Properties="RepositoryRoot=$(_CloneRepositoryRoot)%(Repository.Identity)\;Configuration=$(Configuration);BuildNumber=$(BuildNumber)" Properties="RepositoryRoot=$(_CloneRepositoryRoot)%(Repository.Identity)\;Configuration=$(Configuration);BuildNumber=$(BuildNumber)"
@ -132,16 +139,16 @@
<Error Text="No solutions were found in '$(_CloneRepositoryRoot)'" Condition="@(Solution->Count()) == 0" /> <Error Text="No solutions were found in '$(_CloneRepositoryRoot)'" Condition="@(Solution->Count()) == 0" />
</Target> </Target>
<Target Name="Graph" DependsOnTargets="ResolveSolutions"> <Target Name="Graph" DependsOnTargets="ResolveRepoInfo">
<RepoTasks.AnalyzeBuildGraph <RepoTasks.AnalyzeBuildGraph
Solutions="@(Solution)" Solutions="@(Solution)"
Artifacts="@(ArtifactInfo)"
Properties="Configuration=$(Configuration);BuildNumber=$(BuildNumber)"> Properties="Configuration=$(Configuration);BuildNumber=$(BuildNumber)">
<Output TaskParameter="PackagesProduced" ItemName="PackagesProduced" />
<Output TaskParameter="RepositoryBuildOrder" ItemName="RepositoryBuildOrder" /> <Output TaskParameter="RepositoryBuildOrder" ItemName="RepositoryBuildOrder" />
</RepoTasks.AnalyzeBuildGraph> </RepoTasks.AnalyzeBuildGraph>
<Message Text="Packages that will be produced:" Importance="High" /> <Message Text="Packages that will be produced:" Importance="High" />
<Message Text=" - %(PackagesProduced.Identity)/%(Version)" Importance="High" /> <Message Text=" - %(ArtifactInfo.PackageId)/%(Version)" Importance="High" Condition="'%(ArtifactType)' == 'NuGetPackage'" />
</Target> </Target>
<Target Name="_UpdateNuGetConfig"> <Target Name="_UpdateNuGetConfig">

View File

@ -9,6 +9,7 @@ using System.IO;
using System.Threading; using System.Threading;
using Microsoft.Build.Framework; using Microsoft.Build.Framework;
using Microsoft.Build.Utilities; using Microsoft.Build.Utilities;
using NuGet.Frameworks;
using RepoTools.BuildGraph; using RepoTools.BuildGraph;
using RepoTasks.ProjectModel; using RepoTasks.ProjectModel;
using RepoTasks.Utilities; using RepoTasks.Utilities;
@ -25,17 +26,14 @@ namespace RepoTasks
[Required] [Required]
public ITaskItem[] Solutions { get; set; } public ITaskItem[] Solutions { get; set; }
[Required]
public ITaskItem[] Artifacts { get; set; }
[Required] [Required]
public string Properties { get; set; } public string Properties { get; set; }
public string StartGraphAt { get; set; } public string StartGraphAt { get; set; }
/// <summary>
/// New packages we are compiling. Used in the pin tool.
/// </summary>
[Output]
public ITaskItem[] PackagesProduced { get; set; }
/// <summary> /// <summary>
/// The order in which to build repositories /// The order in which to build repositories
/// </summary> /// </summary>
@ -49,6 +47,8 @@ namespace RepoTasks
public override bool Execute() public override bool Execute()
{ {
var packageArtifacts = GetPackageInfo(Artifacts);
var factory = new SolutionInfoFactory(Log, BuildEngine5); var factory = new SolutionInfoFactory(Log, BuildEngine5);
var props = MSBuildListSplitter.GetNamedProperties(Properties); var props = MSBuildListSplitter.GetNamedProperties(Properties);
@ -63,8 +63,7 @@ namespace RepoTasks
} }
EnsureConsistentGraph(solutions); EnsureConsistentGraph(solutions);
PackagesProduced = GetPackagesProduced(solutions); RepositoryBuildOrder = GetRepositoryBuildOrder(packageArtifacts, solutions.Where(s => s.ShouldBuild));
RepositoryBuildOrder = GetRepositoryBuildOrder(solutions.Where(s => s.ShouldBuild));
return !Log.HasLoggedErrors; return !Log.HasLoggedErrors;
} }
@ -74,43 +73,47 @@ namespace RepoTasks
// TODO // TODO
} }
private ITaskItem[] GetPackagesProduced(IEnumerable<SolutionInfo> solutions) private IEnumerable<(PackageInfo, string repoName)> GetPackageInfo(IEnumerable<ITaskItem> items)
{ {
return solutions return items
.Where(s => s.ShouldBuild) .Where(a => "NuGetPackage".Equals(a.GetMetadata("ArtifactType"), StringComparison.OrdinalIgnoreCase))
.SelectMany(p => p.Projects) .Select(a =>
.Where(p => p.IsPackable)
.Select(p => new TaskItem(p.PackageId, new Hashtable
{ {
["Version"] = p.PackageVersion var info = new PackageInfo(
})) a.GetMetadata("PackageId"),
.ToArray(); a.GetMetadata("Version"),
string.IsNullOrEmpty(a.GetMetadata("TargetFramework"))
? MSBuildListSplitter.SplitItemList(a.GetMetadata("TargetFramework")).Select(s => NuGetFramework.Parse(s)).ToArray()
: new [] { NuGetFramework.Parse(a.GetMetadata("TargetFramework")) },
Path.GetDirectoryName(a.ItemSpec),
a.GetMetadata("PackageType"));
var repoName = Path.GetFileName(a.GetMetadata("RepositoryRoot").TrimEnd(new [] { '\\', '/' }));
return (info, repoName);
});
} }
private ITaskItem[] GetRepositoryBuildOrder(IEnumerable<SolutionInfo> solutions) private ITaskItem[] GetRepositoryBuildOrder(IEnumerable<(PackageInfo pkg, string repoName)> artifacts, IEnumerable<SolutionInfo> solutions)
{ {
var repositories = solutions.Select(s => var repositories = solutions.Select(s =>
{ {
var repoName = Path.GetFileName(Path.GetDirectoryName(s.FullPath)); var repoName = Path.GetFileName(Path.GetDirectoryName(s.FullPath));
var repo = new Repository(repoName); var repo = new Repository(repoName);
repo.Projects = s.Projects var packages = artifacts.Where(a => a.repoName.Equals(repoName, StringComparison.OrdinalIgnoreCase)).ToList();
.Where(p => p.IsPackable)
.Select(p => foreach (var proj in s.Projects)
new Project(p.PackageId) {
{ var projectGroup = packages.Any(p => p.pkg.Id == proj.PackageId)
Repository = repo, ? repo.Projects
PackageReferences = new HashSet<string>(p.Frameworks.SelectMany(f => f.Dependencies.Keys), StringComparer.OrdinalIgnoreCase), : repo.SupportProjects;
})
.ToList(); projectGroup.Add(new Project(proj.PackageId)
repo.SupportProjects = s.Projects {
.Where(p => !p.IsPackable) Repository = repo,
.Select(p => PackageReferences = new HashSet<string>(proj.Frameworks.SelectMany(f => f.Dependencies.Keys), StringComparer.OrdinalIgnoreCase),
new Project(p.PackageId) });
{ }
Repository = repo,
PackageReferences = new HashSet<string>(p.Frameworks.SelectMany(f => f.Dependencies.Keys), StringComparer.OrdinalIgnoreCase),
})
.ToList();
return repo; return repo;
}).ToList(); }).ToList();

View File

@ -22,9 +22,9 @@ namespace RepoTools.BuildGraph
public string Name { get; private set; } public string Name { get; private set; }
public IList<Project> Projects { get; set; } = new List<Project>(); public IList<Project> Projects { get; } = new List<Project>();
public IList<Project> SupportProjects { get; set; } = new List<Project>(); public IList<Project> SupportProjects { get; } = new List<Project>();
public IEnumerable<Project> AllProjects => Projects.Concat(SupportProjects); public IEnumerable<Project> AllProjects => Projects.Concat(SupportProjects);

View File

@ -0,0 +1,45 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.IO;
using NuGet.Frameworks;
namespace RepoTasks.ProjectModel
{
internal class PackageInfo
{
public PackageInfo(string id,
string version,
IReadOnlyList<NuGetFramework> frameworks,
string source,
string packageType = "Dependency")
{
if (string.IsNullOrEmpty(id))
{
throw new ArgumentException(nameof(id));
}
if (string.IsNullOrEmpty(version))
{
throw new ArgumentException(nameof(version));
}
Id = id;
Version = version;
Frameworks = frameworks;
PackageType = packageType;
Source = source;
}
public string Id { get; }
public string Version { get; }
public string PackageType { get; }
/// <summary>
/// Can be a https feed or a file path. May be null.
/// </summary>
public string Source { get; }
public IReadOnlyList<NuGetFramework> Frameworks { get; }
}
}

View File

@ -98,7 +98,7 @@ namespace RepoTasks.ProjectModel
}); });
timer.Stop(); timer.Stop();
_logger.LogMessage(MessageImportance.Normal, $"Finished design-time build in {timer.ElapsedMilliseconds}ms"); _logger.LogMessage(MessageImportance.High, $"Finished design-time build in {timer.ElapsedMilliseconds}ms");
return solutions.ToArray(); return solutions.ToArray();
} }