Update to MSBuild
This commit is contained in:
parent
c598f1918d
commit
471f48f56e
|
|
@ -14,56 +14,7 @@ artifacts
|
||||||
StyleCop.Cache
|
StyleCop.Cache
|
||||||
node_modules
|
node_modules
|
||||||
*.snk
|
*.snk
|
||||||
.nuget/NuGet.exe
|
|
||||||
project.lock.json
|
|
||||||
.build
|
.build
|
||||||
.nuget/
|
.nuget
|
||||||
|
.r
|
||||||
# repo folders
|
.deps
|
||||||
/Antiforgery/
|
|
||||||
/AzureIntegration/
|
|
||||||
/BasicMiddleware/
|
|
||||||
/BrowserLink/
|
|
||||||
/CORS/
|
|
||||||
/Caching/
|
|
||||||
/Common/
|
|
||||||
/Configuration/
|
|
||||||
/DataProtection/
|
|
||||||
/DependencyInjection/
|
|
||||||
/Diagnostics/
|
|
||||||
/DotNetTools/
|
|
||||||
/EntityFramework.Tools/
|
|
||||||
/EntityFramework/
|
|
||||||
/Entropy/
|
|
||||||
/EventNotification/
|
|
||||||
/FileSystem/
|
|
||||||
/Hosting/
|
|
||||||
/HtmlAbstractions/
|
|
||||||
/HttpAbstractions/
|
|
||||||
/HttpSysServer/
|
|
||||||
/IISIntegration/
|
|
||||||
/Identity/
|
|
||||||
/IdentityService/
|
|
||||||
/JsonPatch/
|
|
||||||
/KestrelHttpServer/
|
|
||||||
/Localization/
|
|
||||||
/Logging/
|
|
||||||
/MetaPackages/
|
|
||||||
/Microsoft.Data.Sqlite/
|
|
||||||
/MusicStore/
|
|
||||||
/Mvc/
|
|
||||||
/MvcPrecompilation/
|
|
||||||
/Options/
|
|
||||||
/PlatformAbstractions/
|
|
||||||
/Proxy/
|
|
||||||
/Razor/
|
|
||||||
/ResponseCaching/
|
|
||||||
/Routing/
|
|
||||||
/Scaffolding/
|
|
||||||
/Security/
|
|
||||||
/ServerTests/
|
|
||||||
/Session/
|
|
||||||
/SignalR/
|
|
||||||
/StaticFiles/
|
|
||||||
/Testing/
|
|
||||||
/WebSockets/
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 15
|
||||||
|
VisualStudioVersion = 15.0.26228.0
|
||||||
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildGraph", "tools\BuildGraph\BuildGraph.csproj", "{B0621D49-4770-4552-9425-D6BD2CF0FB50}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PinVersions", "tools\PinVersions\PinVersions.csproj", "{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "shared", "shared", "{085280EC-7055-426A-BF9C-1B692B9599AB}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
tools\shared\DependencyGraphSpecProvider.cs = tools\shared\DependencyGraphSpecProvider.cs
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B0621D49-4770-4552-9425-D6BD2CF0FB50}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{0DC180DF-D87B-448A-BCDE-2A648F41103E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{DACA9DFB-508E-45EA-A5CF-C0F5C2BA181B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
||||||
|
|
@ -1,243 +0,0 @@
|
||||||
#update-release
|
|
||||||
-// Merge dev branch to release
|
|
||||||
@{
|
|
||||||
Parallel.ForEach(GetAllRepos(), CloneOrUpdate);
|
|
||||||
|
|
||||||
Log.Info("************************************* Checking repos for diffs *************************");
|
|
||||||
|
|
||||||
foreach (var repo in GetAllRepos())
|
|
||||||
{
|
|
||||||
Log.Info("Checking repo: " + repo);
|
|
||||||
// Check if the repo previously had a release branch
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GitCommand(repo, "rev-parse --verify --quiet origin/release");
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Log.Info("Repository " + repo + " does not have a release branch.");
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GitCommand(repo, "log -1 --exit-code origin/dev..origin/release");
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
Log.Warn("Unmerged changes in repository " + repo);
|
|
||||||
GitCommand(repo, "log origin/dev..origin/release");
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Info("No conflicts in repos, continuing with creating release branch.");
|
|
||||||
|
|
||||||
foreach (var repo in GetAllRepos())
|
|
||||||
{
|
|
||||||
GitCommand(repo, "checkout origin/dev -B release");
|
|
||||||
var filesChanged = false;
|
|
||||||
|
|
||||||
// Update NuGet.Config
|
|
||||||
var nugetConfigPath = Path.Combine(repo, "NuGet.config");
|
|
||||||
if (File.Exists(nugetConfigPath))
|
|
||||||
{
|
|
||||||
var original = File.ReadAllText(nugetConfigPath);
|
|
||||||
var modified = original
|
|
||||||
.Replace("https://dotnet.myget.org/F/aspnetcore-ci-dev", "https://dotnet.myget.org/F/aspnetcore-ci-release");
|
|
||||||
|
|
||||||
if (!string.Equals(original, modified, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
File.WriteAllText(nugetConfigPath, modified);
|
|
||||||
GitCommand(repo, "add NuGet.config");
|
|
||||||
filesChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var buildPs1Path = Path.Combine(repo, "build.ps1");
|
|
||||||
if (File.Exists(buildPs1Path))
|
|
||||||
{
|
|
||||||
var original = File.ReadAllText(buildPs1Path);
|
|
||||||
var modified = original
|
|
||||||
.Replace("https://github.com/aspnet/KoreBuild/archive/dev.zip", "https://github.com/aspnet/KoreBuild/archive/release.zip");
|
|
||||||
|
|
||||||
if (!string.Equals(original, modified, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
File.WriteAllText(buildPs1Path, modified);
|
|
||||||
GitCommand(repo, "add build.ps1");
|
|
||||||
filesChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var buildShPath = Path.Combine(repo, "build.sh");
|
|
||||||
if (File.Exists(buildShPath))
|
|
||||||
{
|
|
||||||
var original = File.ReadAllText(buildShPath);
|
|
||||||
var modified = original
|
|
||||||
.Replace("https://github.com/aspnet/KoreBuild/archive/dev.zip", "https://github.com/aspnet/KoreBuild/archive/release.zip");
|
|
||||||
|
|
||||||
if (!string.Equals(original, modified, StringComparison.Ordinal))
|
|
||||||
{
|
|
||||||
File.WriteAllText(buildShPath, modified);
|
|
||||||
GitCommand(repo, "add build.sh");
|
|
||||||
filesChanged = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (filesChanged)
|
|
||||||
{
|
|
||||||
GitCommand(repo, "commit -m \"Updating to release.\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
GitCommand(repo, "push origin release:release");
|
|
||||||
GitCommand(repo, "checkout origin/dev -B dev");
|
|
||||||
GitCommand(repo, "merge release -s ours");
|
|
||||||
GitCommand(repo, "push origin dev:dev");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#update-master .pull-all
|
|
||||||
-// Merge release branch to master
|
|
||||||
-// Pin versions of packages in project.json and updated project.lock.json
|
|
||||||
-// More information https://github.com/aspnet/Universe/wiki/%23pin-version-:-Pinning-package-version-for-a-particular-release-in-project.json
|
|
||||||
@{
|
|
||||||
var koreBuildTag = GetEnvironmentParameter("KOREBUILD_TAG");
|
|
||||||
var coherenceFeed = GetEnvironmentParameter("COHERENCE_FEED");
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(coherenceFeed))
|
|
||||||
{
|
|
||||||
throw new Exception("COHERENCE_FEED not specified. Usually this is Packages-NoTimestamp directory of Coherence-Signed.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(koreBuildTag))
|
|
||||||
{
|
|
||||||
throw new Exception("KOREBUILD_TAG environment variable is not specified.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var excludeReposForJson = new[]
|
|
||||||
{
|
|
||||||
"Coherence",
|
|
||||||
"Coherence-Signed",
|
|
||||||
"dnvm",
|
|
||||||
"Entropy",
|
|
||||||
"Setup",
|
|
||||||
"libuv-build",
|
|
||||||
};
|
|
||||||
|
|
||||||
Exec("dotnet", "restore", "tools/PinVersion");
|
|
||||||
|
|
||||||
foreach (var repo in GetAllRepos())
|
|
||||||
{
|
|
||||||
GitCommand(repo, "checkout origin/release -B master");
|
|
||||||
|
|
||||||
if (File.Exists(Path.Combine(repo, "NuGet.config")))
|
|
||||||
{
|
|
||||||
File.Copy(Path.Combine("build-template", "NuGet.master.config"),
|
|
||||||
Path.Combine(repo, "NuGet.config"),
|
|
||||||
overwrite: true);
|
|
||||||
GitCommand(repo, "add NuGet.*");
|
|
||||||
GitCommand(repo, "commit -m \"Updating NuGet.config\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var reposToPin = GetAllRepos().Except(excludeReposForJson);
|
|
||||||
var repositoryNamesFile = Path.GetTempFileName();
|
|
||||||
|
|
||||||
File.WriteAllLines(repositoryNamesFile, reposToPin.Select(r => Path.Combine(Directory.GetCurrentDirectory(), r)));
|
|
||||||
var pinToolsArgs = string.Format(@"run -p tools/PinVersion ""{0}"" ""{1}"" ""{2}""",
|
|
||||||
coherenceFeed,
|
|
||||||
koreBuildTag,
|
|
||||||
repositoryNamesFile);
|
|
||||||
Exec("dotnet", pinToolsArgs, "");
|
|
||||||
try
|
|
||||||
{
|
|
||||||
File.Delete(repositoryNamesFile);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var repo in reposToPin)
|
|
||||||
{
|
|
||||||
var repoPath = Path.Combine(Directory.GetCurrentDirectory(), repo);
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GitCommand(repo, "commit -am \"Updating json files to pin versions and build files to pin KoreBuild\"");
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Don't fail if there was nothing to add.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var repo in GetAllRepos())
|
|
||||||
{
|
|
||||||
GitCommand(repo, "push origin +master:master");
|
|
||||||
}
|
|
||||||
|
|
||||||
CallTarget("update-prerelease-tags");
|
|
||||||
}
|
|
||||||
|
|
||||||
#update-prerelease-tags
|
|
||||||
-// Update tags on each repo to have the latest release tag
|
|
||||||
@{
|
|
||||||
var preReleaseTag = GetEnvironmentParameter("PRERELEASETAG");
|
|
||||||
if (string.IsNullOrEmpty(preReleaseTag))
|
|
||||||
{
|
|
||||||
throw new Exception("PRERELEASETAG tag not defined");
|
|
||||||
}
|
|
||||||
|
|
||||||
var versionFile = "version.txt";
|
|
||||||
|
|
||||||
foreach (var repo in GetAllRepos())
|
|
||||||
{
|
|
||||||
GitCommand(repo, "pull --tags");
|
|
||||||
string version = null;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
GitCommand(repo, string.Format("describe --tags > ..\\{0}", versionFile));
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
version = "1.0.0-" + preReleaseTag;
|
|
||||||
Log.Warn(string.Format("{0} repo not tagged. Using default version {1}.", repo, version));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (version == null)
|
|
||||||
{
|
|
||||||
version = File.ReadAllText(versionFile);
|
|
||||||
File.Delete(versionFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Info(string.Format("Current version on repo {0} is {1}", repo, version));
|
|
||||||
|
|
||||||
var majorVersion = version.Split(new string[]{"-"}, StringSplitOptions.None)[0];
|
|
||||||
|
|
||||||
var newVersion = majorVersion + string.Format("-{0}", preReleaseTag);
|
|
||||||
|
|
||||||
Log.Info(string.Format("New version for repo is {0}", newVersion));
|
|
||||||
|
|
||||||
GitCommand(repo, string.Format("tag -f -a {0} -m \"Tag for new release {0}\"", newVersion));
|
|
||||||
|
|
||||||
GitCommand(repo, "push origin --tags +" + newVersion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
functions
|
|
||||||
@{
|
|
||||||
IEnumerable<string> GetAllRepos()
|
|
||||||
{
|
|
||||||
var nonDefaultRepos = new[]
|
|
||||||
{
|
|
||||||
"CoreCLR",
|
|
||||||
"Coherence",
|
|
||||||
"Coherence-Signed",
|
|
||||||
"KoreBuild",
|
|
||||||
"Universe",
|
|
||||||
"libuv-build",
|
|
||||||
};
|
|
||||||
|
|
||||||
return Enumerable.Concat(nonDefaultRepos, repositories);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<configuration>
|
|
||||||
<packageSources>
|
|
||||||
<clear />
|
|
||||||
<add key="AspNetVNext" value="https://www.myget.org/f/aspnetmaster/api/v3/index.json" />
|
|
||||||
<add key="NuGet" value="https://api.nuget.org/v3/index.json" />
|
|
||||||
</packageSources>
|
|
||||||
</configuration>
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<Project>
|
||||||
|
<ItemDefinitionGroup>
|
||||||
|
<Repository>
|
||||||
|
<Branch>dev</Branch>
|
||||||
|
<CloneUrl>git@github.com:aspnet/%(Identity)</CloneUrl>
|
||||||
|
</Repository>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Repository Include="Antiforgery" Commit="" />
|
||||||
|
<Repository Include="AzureIntegration" Commit="" />
|
||||||
|
<Repository Include="BasicMiddleware" Commit="" />
|
||||||
|
<Repository Include="BrowserLink" Commit="" />
|
||||||
|
<Repository Include="Caching" Commit="" />
|
||||||
|
<Repository Include="Common" Commit="" />
|
||||||
|
<Repository Include="Configuration" Commit="" />
|
||||||
|
<Repository Include="CORS" Commit="" />
|
||||||
|
<Repository Include="DataProtection" Commit="" />
|
||||||
|
<Repository Include="DependencyInjection" Commit="" />
|
||||||
|
<Repository Include="Diagnostics" Commit="" />
|
||||||
|
<Repository Include="DotNetTools" Commit="" />
|
||||||
|
<Repository Include="EntityFramework" Commit="" />
|
||||||
|
<Repository Include="EntityFramework.Tools" Commit="" />
|
||||||
|
<Repository Include="Entropy" Commit="" />
|
||||||
|
<Repository Include="EventNotification" Commit="" />
|
||||||
|
<Repository Include="FileSystem" Commit="" />
|
||||||
|
<Repository Include="Hosting" Commit="" />
|
||||||
|
<Repository Include="HtmlAbstractions" Commit="" />
|
||||||
|
<Repository Include="HttpAbstractions" Commit="" />
|
||||||
|
<Repository Include="HttpSysServer" Commit="" />
|
||||||
|
<Repository Include="Identity" Commit="" />
|
||||||
|
<Repository Include="IdentityService" Commit="" />
|
||||||
|
<Repository Include="IISIntegration" Commit="" />
|
||||||
|
<Repository Include="JsonPatch" Commit="" />
|
||||||
|
<Repository Include="KestrelHttpServer" Commit="" />
|
||||||
|
<Repository Include="Localization" Commit="" />
|
||||||
|
<Repository Include="Logging" Commit="" />
|
||||||
|
<Repository Include="MetaPackages" Commit="" />
|
||||||
|
<Repository Include="Microsoft.Data.Sqlite" Commit="" />
|
||||||
|
<Repository Include="MusicStore" Commit="" />
|
||||||
|
<Repository Include="Mvc" Commit="" />
|
||||||
|
<Repository Include="MvcPrecompilation" Commit="" />
|
||||||
|
<Repository Include="Options" Commit="" />
|
||||||
|
<Repository Include="PlatformAbstractions" Commit="" />
|
||||||
|
<Repository Include="Proxy" Commit="" />
|
||||||
|
<Repository Include="Razor" Commit="" />
|
||||||
|
<Repository Include="ResponseCaching" Commit="" />
|
||||||
|
<Repository Include="Routing" Commit="" />
|
||||||
|
<Repository Include="Scaffolding" Commit="" />
|
||||||
|
<Repository Include="Security" Commit="" />
|
||||||
|
<Repository Include="ServerTests" Commit="" />
|
||||||
|
<Repository Include="Session" Commit="" />
|
||||||
|
<Repository Include="SignalR" Commit="" />
|
||||||
|
<Repository Include="StaticFiles" Commit="" />
|
||||||
|
<Repository Include="Testing" Commit="" />
|
||||||
|
<Repository Include="WebSockets" Commit="" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
<Project>
|
||||||
|
<Import Project="$(_BuildGraphFile)" />
|
||||||
|
|
||||||
|
<Target Name="BuildRepositories">
|
||||||
|
<ItemGroup>
|
||||||
|
<BatchedRepository Include="$(MSBuildProjectFullPath)">
|
||||||
|
<AdditionalProperties>
|
||||||
|
RepositoryToBuild=%(RepositoryToBuildInOrder.Identity);
|
||||||
|
BuildRepositoryRoot=$(_CloneRepositoryRoot)%(RepositoryToBuildInOrder.Identity)\
|
||||||
|
</AdditionalProperties>
|
||||||
|
<BuildGroup>%(RepositoryToBuildInOrder.Order)</BuildGroup>
|
||||||
|
</BatchedRepository>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<BatchBuilds Condition="$(BuildInParallel) AND '$(CompileOnly)'=='true'">true</BatchBuilds>
|
||||||
|
<BatchBuilds Condition="'$(BatchBuilds)'==''">false</BatchBuilds>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<MSBuild
|
||||||
|
Projects="@(BatchedRepository)"
|
||||||
|
BuildInParallel="$(BatchBuilds)"
|
||||||
|
Targets="_BuildRepository"
|
||||||
|
Properties="BuildGroup=%(BatchedRepository.BuildGroup)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_BuildRepository" DependsOnTargets="_PinVersions">
|
||||||
|
<PropertyGroup>
|
||||||
|
<RepositoryKoreBuildDirectory>$(BuildRepositoryRoot).build\</RepositoryKoreBuildDirectory>
|
||||||
|
<RepositoryArtifactsDirectory>$(BuildRepositoryRoot)artifacts\build\</RepositoryArtifactsDirectory>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<KoreBuildFiles Include="$(KoreBuildDirectory)**\*" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Message Text="============ Building $(RepositoryToBuild) ============" Importance="High" />
|
||||||
|
<Copy SourceFiles="@(KoreBuildFiles)" DestinationFolder="$(RepositoryKoreBuildDirectory)%(RecursiveDir)" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<RepositoryKoreBuildProject Include="$(RepositoryKoreBuildDirectory)$(KoreBuildProject)">
|
||||||
|
<AdditionalProperties>
|
||||||
|
RepositoryRoot=$(BuildRepositoryRoot);
|
||||||
|
BuildNumber=$(BuildNumber);
|
||||||
|
Configuration=$(Configuration)
|
||||||
|
</AdditionalProperties>
|
||||||
|
</RepositoryKoreBuildProject>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<MSBuild
|
||||||
|
Projects="@(RepositoryKoreBuildProject)"
|
||||||
|
Targets="Restore"
|
||||||
|
Properties="PreflightRestore=true" />
|
||||||
|
|
||||||
|
<MSBuild
|
||||||
|
Projects="@(RepositoryKoreBuildProject)"
|
||||||
|
Targets="$(_RepositoryBuildTargets)" />
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<RepositoryArtifacts Include="$(RepositoryArtifactsDirectory)*" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Copy
|
||||||
|
SourceFiles="@(RepositoryArtifacts)"
|
||||||
|
DestinationFolder="$(UniverseBuildDir)" />
|
||||||
|
|
||||||
|
<Exec
|
||||||
|
Command="$(DotNetPath) nuget push "%(RepositoryArtifacts.Identity)" -s $(NuGetFeed) -k $(APIKEY)"
|
||||||
|
Condition="'$(PublishPackages)'=='true' AND '%(RepositoryArtifacts.Extension)'=='.nupkg'" />
|
||||||
|
|
||||||
|
<Message Text="============ Done building $(RepositoryToBuild) ============" Importance="High" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_PinVersions">
|
||||||
|
<PropertyGroup>
|
||||||
|
<PinToolBinary>$(RepositoryRoot)tools\PinVersions\bin\$(Configuration)\netcoreapp1.1\PinVersions.dll</PinToolBinary>
|
||||||
|
<PinVersionArgs>$(DotNetPath) $(PinToolBinary) --graph-specs-root "$(_RestoreGraphSpecsDirectory) " -s "$(UniverseBuildDir) " "$(BuildRepositoryRoot) "</PinVersionArgs>
|
||||||
|
<PinVersionArgs Condition="Exists('$(_DependencyPackagesDirectory)')">$(PinVersionArgs) -s "$(_DependencyPackagesDirectory) "</PinVersionArgs>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Exec Command="$(PinVersionArgs)" />
|
||||||
|
</Target>
|
||||||
|
</Project>
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
<Project>
|
|
||||||
<PropertyGroup>
|
|
||||||
<DisableDefaultItems>true</DisableDefaultItems>
|
|
||||||
<DisableDefaultTargets>true</DisableDefaultTargets>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,56 +1,220 @@
|
||||||
<Project>
|
<Project>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_SakeTargets Condition="'$(Configuration)' == 'Release'">--config-release</_SakeTargets>
|
<NuGetPublishVolatileFeed>https://dotnet.myget.org/F/aspnetcore-volatile-dev/api/v2/package</NuGetPublishVolatileFeed>
|
||||||
|
|
||||||
|
<_BuildGraphFile>$(BuildDir)BuildGraph.proj</_BuildGraphFile>
|
||||||
|
<_CloneRepositoryRoot>$(RepositoryRoot).r\</_CloneRepositoryRoot>
|
||||||
|
<_DependencyPackagesDirectory>$(RepositoryRoot).deps\build\</_DependencyPackagesDirectory>
|
||||||
|
<_CommitsFile>$(RepositoryRoot).deps\build\RepositoryCommits.proj</_CommitsFile>
|
||||||
|
<_RestoreGraphSpecsDirectory>$(RepositoryRoot)obj\package-specs\</_RestoreGraphSpecsDirectory>
|
||||||
|
|
||||||
|
<_RepositoryBuildTargets Condition="'$(_RepositoryBuildTargets)'=='' AND '$(CompileOnly)'=='true'">Package;VerifyPackages</_RepositoryBuildTargets>
|
||||||
|
<_RepositoryBuildTargets Condition="'$(_RepositoryBuildTargets)'==''">Verify</_RepositoryBuildTargets>
|
||||||
|
<_RepositoriesWithCommitsFile>$(RepositoryRoot).deps\build\Repositories.props</_RepositoriesWithCommitsFile>
|
||||||
|
|
||||||
|
<PrepareDependsOn>$(PrepareDependsOn);CleanUniverseArtifacts</PrepareDependsOn>
|
||||||
|
<CleanDependsOn>$(CleanDependsOn);CleanUniverseArtifacts</CleanDependsOn>
|
||||||
|
<BuildDependsOn>$(BuildDependsOn);CloneRepositories;BuildRepositories</BuildDependsOn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!-- workaround. Using Sake as the intermediate means this property doesn't flow into repo builds. -->
|
<Import
|
||||||
<Target Name="SetBuildNumber" Condition="'$(BuildNumber)' != ''">
|
Project="$(_RepositoriesWithCommitsFile)"
|
||||||
<SetEnvironmentVariable Variable="BuildNumber" Value="$(BuildNumber)" />
|
Condition="Exists('$(_RepositoriesWithCommitsFile)')" />
|
||||||
|
<Import
|
||||||
|
Project="Repositories.props"
|
||||||
|
Condition="!Exists('$(_RepositoriesWithCommitsFile)')" />
|
||||||
|
<Import
|
||||||
|
Project="$(_CommitsFile)"
|
||||||
|
Condition="Exists('$(_CommitsFile)')" />
|
||||||
|
|
||||||
|
<Target Name="CleanUniverseArtifacts">
|
||||||
|
<RemoveDir Directories="$(RepositoryRoot)obj" Condition="Exists('$(RepositoryRoot)obj')" />
|
||||||
|
<RemoveDir Directories="$(_CloneRepositoryRoot)" Condition="Exists('$(_CloneRepositoryRoot)')" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="VerifyAll">
|
<Target Name="_FilterRepositories">
|
||||||
|
<ItemGroup Condition="'$(KOREBUILD_REPOSITORY_INCLUDE)'!=''">
|
||||||
|
<_RepositoriesToInclude Include="$(KOREBUILD_REPOSITORY_INCLUDE)" />
|
||||||
|
<Repository
|
||||||
|
Remove="@(Repository)"
|
||||||
|
Condition="'@(Repository)'!='@(_RepositoriesToInclude)' AND '%(Identity)'!=''" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(KOREBUILD_REPOSITORY_EXCLUDE)'!=''">
|
||||||
|
<RepositoriesToExclude Include="$(KOREBUILD_REPOSITORY_EXCLUDE)" />
|
||||||
|
<Repository Remove="@(RepositoriesToExclude)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<Error Text="KOREBUILD_REPOSITORY_EXCLUDE AND KOREBUILD_REPOSITORY_INCLUDE are specified."
|
||||||
|
Condition="'$(KOREBUILD_REPOSITORY_INCLUDE)' != '' AND '$(KOREBUILD_REPOSITORY_EXCLUDE)' != ''" />
|
||||||
|
|
||||||
|
<Message Text="%(Repository.CloneUrl)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="CloneRepositories" DependsOnTargets="_FilterRepositories">
|
||||||
|
<ItemGroup>
|
||||||
|
<_CloneRepository Include="$(MSBuildProjectFullPath)">
|
||||||
|
<AdditionalProperties>
|
||||||
|
CloneRepository=%(Repository.Identity);
|
||||||
|
CloneUrl=%(Repository.CloneUrl);
|
||||||
|
CloneBranch=%(Repository.Branch);
|
||||||
|
CloneRepositoryCommit=%(Repository.Commit);
|
||||||
|
UseGateBranch=$(UseGateBranch)
|
||||||
|
</AdditionalProperties>
|
||||||
|
</_CloneRepository>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<MakeDir Directories="$(_CloneRepositoryRoot)" />
|
||||||
|
|
||||||
|
<MSBuild Projects="@(_CloneRepository)"
|
||||||
|
Targets="_CloneRepository"
|
||||||
|
BuildInParallel="$(BuildInParallel)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_CloneRepository">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_SakeTargets>$(_SakeTargets):verify-all</_SakeTargets>
|
<ShallowClone Condition="'$(ShallowClone)'=='' OR '$(CloneRepositoryCommit)'!=''">false</ShallowClone>
|
||||||
|
<_CloneArguments>git clone --quiet $(CloneUrl)</_CloneArguments>
|
||||||
|
<_CloneArguments Condition="'$(ShallowClone)'=='true'">$(_CloneArguments) --depth 1</_CloneArguments>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
|
||||||
Targets="Sake"
|
<Message Text="Cloning $(CloneRepository) ..." Importance="High" />
|
||||||
Properties="SakeTargets=$(_SakeTargets);RepositoryRoot=$(RepositoryRoot)" />
|
<Exec
|
||||||
|
Command="$(_CloneArguments) --branch $(CloneBranch)-gate"
|
||||||
|
Condition="'$(UseGateBranch)'=='true'"
|
||||||
|
IgnoreExitCode="true"
|
||||||
|
IgnoreStandardErrorWarningFormat="true"
|
||||||
|
WorkingDirectory="$(_CloneRepositoryRoot)">
|
||||||
|
<Output TaskParameter="ExitCode" PropertyName="GateBranchExitCode" />
|
||||||
|
</Exec>
|
||||||
|
|
||||||
|
<Warning Text="Using $(CloneBranch)-gate for $(CloneRepository)"
|
||||||
|
Condition="'$(GateBranchExitCode)'=='0'" />
|
||||||
|
|
||||||
|
<Exec
|
||||||
|
Command="$(_CloneArguments) --branch $(CloneBranch)"
|
||||||
|
Condition="'$(GateBranchExitCode)'!='0'"
|
||||||
|
WorkingDirectory="$(_CloneRepositoryRoot)" />
|
||||||
|
|
||||||
|
<Exec
|
||||||
|
Command="git reset --quiet --hard $(CloneRepositoryCommit)"
|
||||||
|
WorkingDirectory="$(_CloneRepositoryRoot)$(CloneRepository)"
|
||||||
|
Condition="'$(CloneRepositoryCommit)'!=''" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CIBuild" DependsOnTargets="SetBuildNumber">
|
<Target Name="BuildRepositories"
|
||||||
|
DependsOnTargets="_FilterRepositories;_FindDotNetPath;_GenerateRestoreGraphSpecs;_GenerateBuildGraph;_UpdateNuGetConfig;_CreateRepositoriesListWithCommits">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<_SakeTargets>$(_SakeTargets):ci-build</_SakeTargets>
|
<_BuildRepositoryProperties>
|
||||||
|
UniverseBuildDir=$(BuildDir);
|
||||||
|
BuildInParallel=$(BuildInParallel);
|
||||||
|
BuildNumber=$(BuildNumber);
|
||||||
|
Configuration=$(Configuration);
|
||||||
|
DotNetPath=$(DotNetPath);
|
||||||
|
KoreBuildDirectory=$(MSBuildProjectDirectory)\;
|
||||||
|
KoreBuildProject=$(MSBuildProjectFile);
|
||||||
|
RepositoryRoot=$(RepositoryRoot);
|
||||||
|
_BuildGraphFile=$(_BuildGraphFile);
|
||||||
|
_CloneRepositoryRoot=$(_CloneRepositoryRoot);
|
||||||
|
_DependencyPackagesDirectory=$(_DependencyPackagesDirectory);
|
||||||
|
_RepositoryBuildTargets=$(_RepositoryBuildTargets);
|
||||||
|
_RestoreGraphSpecsDirectory=$(_RestoreGraphSpecsDirectory)
|
||||||
|
</_BuildRepositoryProperties>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
|
||||||
Targets="Sake"
|
<MSBuild
|
||||||
Properties="SakeTargets=$(_SakeTargets);RepositoryRoot=$(RepositoryRoot)" />
|
Projects="$(MSBuildThisFileDirectory)RepositoryBuild.targets"
|
||||||
|
Targets="BuildRepositories"
|
||||||
|
Properties="$(_BuildRepositoryProperties)" />
|
||||||
|
|
||||||
|
<MSBuild
|
||||||
|
Projects="$(MSBuildThisFileDirectory)PublishPackages.targets"
|
||||||
|
Condition="'$(PublishPackages)'=='true'"
|
||||||
|
Properties="
|
||||||
|
PackagesDirectory=$(ArtifactsDir);
|
||||||
|
DotNetPath=$(DotNetPath);
|
||||||
|
NuGetFeed=$(NuGetPublishFeed);
|
||||||
|
APIKey=$(APIKey)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CITest" DependsOnTargets="SetBuildNumber">
|
<Target Name="_GenerateRestoreGraphSpecs" DependsOnTargets="_FindDotNetPath">
|
||||||
<PropertyGroup>
|
<ItemGroup>
|
||||||
<_SakeTargets>$(_SakeTargets):ci-test</_SakeTargets>
|
<Solution Include="$(_CloneRepositoryRoot)%(Repository.Identity)\*.sln">
|
||||||
|
<Repository>%(Repository.Identity)</Repository>
|
||||||
|
</Solution>
|
||||||
|
|
||||||
|
<Solution>
|
||||||
|
<AdditionalProperties>RestoreGraphOutputPath=$(_RestoreGraphSpecsDirectory)%(Solution.Repository)\%(Solution.FileName)%(Solution.Extension).json</AdditionalProperties>
|
||||||
|
</Solution>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<MSBuild
|
||||||
|
Projects="@(Solution)"
|
||||||
|
Targets="GenerateRestoreGraphFile"
|
||||||
|
BuildInParallel="$(BuildInParallel)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_GenerateBuildGraph" DependsOnTargets="_FindDotNetPath">
|
||||||
|
<Exec
|
||||||
|
Command="$(DotNetPath) run -r "$(_CloneRepositoryRoot) " --graph-specs-root "$(_RestoreGraphSpecsDirectory) " "$(_BuildGraphFile)""
|
||||||
|
WorkingDirectory="$(RepositoryRoot)tools\BuildGraph\" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_UpdateNuGetConfig">
|
||||||
|
<UpdatePackageSource
|
||||||
|
NuGetConfigPath="$(_CloneRepositoryRoot)%(Repository.Identity)\NuGet.config"
|
||||||
|
SourceName="Dependencies"
|
||||||
|
SourceUri="$(_DependencyPackagesDirectory)"
|
||||||
|
Condition="Exists('$(_DependencyPackagesDirectory)')" />
|
||||||
|
|
||||||
|
<MakeDir Directories="$(BuildDir)" Condition="!Exists('$(BuildDir)')" />
|
||||||
|
|
||||||
|
<UpdatePackageSource
|
||||||
|
NuGetConfigPath="$(_CloneRepositoryRoot)%(Repository.Identity)\NuGet.config"
|
||||||
|
SourceName="Artifacts"
|
||||||
|
SourceUri="$(BuildDir)" />
|
||||||
|
</Target>
|
||||||
|
|
||||||
|
<Target Name="_CreateRepositoriesListWithCommits" DependsOnTargets="_GetRepositoryCommits">
|
||||||
|
<PropertyGroup>
|
||||||
|
<RepositoryFileWithCommit>$(BuildDir)Repositories.props</RepositoryFileWithCommit>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
<Copy
|
||||||
Targets="Sake"
|
SourceFiles="$(MSBuildThisFileDirectory)Repositories.props"
|
||||||
Properties="SakeTargets=$(_SakeTargets);RepositoryRoot=$(RepositoryRoot)" />
|
DestinationFiles="$(RepositoryFileWithCommit)" />
|
||||||
|
|
||||||
|
<XmlPoke2
|
||||||
|
XmlInputPath="$(RepositoryFileWithCommit)"
|
||||||
|
Query="//Repository[@Include='%(Repository.Identity)']/@Commit"
|
||||||
|
Value="%(Repository.Commit)" />
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CIPull">
|
<!-- Based on the solution here: http://stackoverflow.com/a/11331566 -->
|
||||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
<Target Name="_GetRepositoryCommits" Outputs="%(Repository.Identity)">
|
||||||
Targets="Sake"
|
<PropertyGroup>
|
||||||
Properties="SakeTargets=ci-pull;RepositoryRoot=$(RepositoryRoot)" />
|
<RepositoryCloneDirectory>$(_CloneRepositoryRoot)%(Repository.Identity)</RepositoryCloneDirectory>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<Error Text="%(Repository.Identity) has not been cloned."
|
||||||
|
Condition="!Exists('$(RepositoryCloneDirectory)')" />
|
||||||
|
|
||||||
|
<GetGitCommitInfo WorkingDirectory="$(RepositoryCloneDirectory)">
|
||||||
|
<Output TaskParameter="CommitHash" PropertyName="_Hash" />
|
||||||
|
</GetGitCommitInfo>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Repository Update="%(Identity)" Commit="$(_Hash)" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<_Hash></_Hash>
|
||||||
|
</PropertyGroup>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="UpdateRepos">
|
<Target Name="_FindDotNetPath">
|
||||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
<GetDotNetHost>
|
||||||
Targets="Sake"
|
<Output TaskParameter="ExecutablePath" PropertyName="DotNetPath" />
|
||||||
Properties="SakeTargets=update;RepositoryRoot=$(RepositoryRoot)" />
|
</GetDotNetHost>
|
||||||
</Target>
|
</Target>
|
||||||
|
|
||||||
<Target Name="CleanAll">
|
|
||||||
<MSBuild Projects="$(MSBuildProjectFullPath)"
|
|
||||||
Targets="Sake"
|
|
||||||
Properties="SakeTargets=git-clean;RepositoryRoot=$(RepositoryRoot)" />
|
|
||||||
</Target>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
1186
makefile.shade
1186
makefile.shade
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\shared\*.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.DotNet.Cli.Utils" Version="1.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
public class DGMLFormatter : GraphFormatter
|
||||||
|
{
|
||||||
|
public override void Format(IList<GraphNode> nodes, string outputPath)
|
||||||
|
{
|
||||||
|
var xmlns = XNamespace.Get("http://schemas.microsoft.com/vs/2009/dgml");
|
||||||
|
var xdoc = new XDocument(
|
||||||
|
new XElement(xmlns + "DirectedGraph",
|
||||||
|
new XElement(xmlns + "Nodes", GetNodes(xmlns, nodes).ToArray()),
|
||||||
|
new XElement(xmlns + "Links", GetLinks(xmlns, nodes).ToArray()),
|
||||||
|
new XElement(xmlns + "Properties", GetProperties(xmlns).ToArray())));
|
||||||
|
|
||||||
|
using (var writer = File.OpenWrite(outputPath))
|
||||||
|
{
|
||||||
|
xdoc.Save(writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<XElement> GetLinks(XNamespace xmlns, IEnumerable<GraphNode> nodes)
|
||||||
|
{
|
||||||
|
foreach (var node in nodes)
|
||||||
|
{
|
||||||
|
foreach (var outgoing in node.Outgoing)
|
||||||
|
{
|
||||||
|
yield return new XElement(xmlns + "Link",
|
||||||
|
new XAttribute("Source", node.Repository.Name),
|
||||||
|
new XAttribute("Target", outgoing.Repository.Name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<XElement> GetNodes(XNamespace xmlns, IEnumerable<GraphNode> nodes)
|
||||||
|
{
|
||||||
|
foreach (var node in nodes)
|
||||||
|
{
|
||||||
|
yield return new XElement(xmlns + "Node",
|
||||||
|
new XAttribute("Id", node.Repository.Name),
|
||||||
|
new XAttribute("Label", $"{node.Repository.Name}"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<XElement> GetProperties(XNamespace xmlns)
|
||||||
|
{
|
||||||
|
yield return new XElement(xmlns + "Property",
|
||||||
|
new XAttribute("Id", "Label"),
|
||||||
|
new XAttribute("Label", "Label"),
|
||||||
|
new XAttribute("DataType", "String"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
public static class GraphBuilder
|
||||||
|
{
|
||||||
|
public static IList<GraphNode> Generate(IList<Repository> repositories)
|
||||||
|
{
|
||||||
|
// Build global list of primary projects
|
||||||
|
var primaryProjects = repositories.SelectMany(c => c.Projects)
|
||||||
|
.ToDictionary(p => p.Name, StringComparer.OrdinalIgnoreCase);
|
||||||
|
var graphNodes = repositories.Select(r => new GraphNode { Repository = r })
|
||||||
|
.ToDictionary(r => r.Repository);
|
||||||
|
|
||||||
|
foreach (var project in repositories.SelectMany(r => r.AllProjects))
|
||||||
|
{
|
||||||
|
var thisProjectRepositoryNode = graphNodes[project.Repository];
|
||||||
|
|
||||||
|
foreach (var packageDependency in project.PackageReferences)
|
||||||
|
{
|
||||||
|
if (primaryProjects.TryGetValue(packageDependency, out var dependencyProject))
|
||||||
|
{
|
||||||
|
var dependencyRepository = dependencyProject.Repository;
|
||||||
|
var dependencyNode = graphNodes[dependencyRepository];
|
||||||
|
|
||||||
|
thisProjectRepositoryNode.Incoming.Add(dependencyNode);
|
||||||
|
dependencyNode.Outgoing.Add(thisProjectRepositoryNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return graphNodes.Values.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
public abstract class GraphFormatter
|
||||||
|
{
|
||||||
|
public abstract void Format(IList<GraphNode> nodes, string outputPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
[DebuggerDisplay("{Repository.Name}")]
|
||||||
|
public class GraphNode
|
||||||
|
{
|
||||||
|
public Repository Repository { get; set; }
|
||||||
|
|
||||||
|
public ISet<GraphNode> Incoming { get; } = new HashSet<GraphNode>();
|
||||||
|
|
||||||
|
public ISet<GraphNode> Outgoing { get; } = new HashSet<GraphNode>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
public class MSBuildGraphFormatter : GraphFormatter
|
||||||
|
{
|
||||||
|
public override void Format(IList<GraphNode> nodes, string outputPath)
|
||||||
|
{
|
||||||
|
var sortedNodes = nodes.Select(node => new { Repository = node.Repository, Order = TopologicalSort.GetOrder(node) })
|
||||||
|
.OrderBy(item => item.Order);
|
||||||
|
var projectElement = new XElement("Project",
|
||||||
|
new XElement("ItemGroup",
|
||||||
|
sortedNodes.Select(item => new XElement("RepositoryToBuildInOrder",
|
||||||
|
new XAttribute("Include", item.Repository.Name),
|
||||||
|
new XAttribute("Order", item.Order)))));
|
||||||
|
|
||||||
|
File.WriteAllText(outputPath, projectElement.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
|
using UniverseTools;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandLineApplication();
|
||||||
|
var outputTypeOption = app.Option("--output-type",
|
||||||
|
"Output type of generated graph. Valid values are: msbuild, and dgml.",
|
||||||
|
CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
var repositoriesRootOption = app.Option("-r|--repositories-root",
|
||||||
|
"Directory containing repositories to calculate graph for.",
|
||||||
|
CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
var packageSpecsDirectoryOption = app.Option("--graph-specs-root",
|
||||||
|
"Directory containing package specs. (Optional)",
|
||||||
|
CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
var outputPathArgument = app.Argument("Output path", "Output path");
|
||||||
|
|
||||||
|
app.OnExecute(() =>
|
||||||
|
{
|
||||||
|
if (!repositoriesRootOption.HasValue())
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"Option {repositoriesRootOption.Template} must have a value.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputPath = outputPathArgument.Value;
|
||||||
|
if (string.IsNullOrEmpty(outputPath))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"Output path not specified.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var outputDirectory = Path.GetDirectoryName(outputPath);
|
||||||
|
Directory.CreateDirectory(outputDirectory);
|
||||||
|
|
||||||
|
var outputType = outputTypeOption.Value() ?? "msbuild";
|
||||||
|
|
||||||
|
|
||||||
|
var graphSpecProvider = packageSpecsDirectoryOption.HasValue()
|
||||||
|
? new DependencyGraphSpecProvider(packageSpecsDirectoryOption.Value().Trim())
|
||||||
|
: DependencyGraphSpecProvider.Default;
|
||||||
|
IList<Repository> repositories;
|
||||||
|
using (graphSpecProvider)
|
||||||
|
{
|
||||||
|
repositories = Repository.ReadAllRepositories(repositoriesRootOption.Value().Trim(), graphSpecProvider);
|
||||||
|
}
|
||||||
|
|
||||||
|
var graph = GraphBuilder.Generate(repositories);
|
||||||
|
GraphFormatter formatter;
|
||||||
|
switch (outputType)
|
||||||
|
{
|
||||||
|
case "msbuild":
|
||||||
|
formatter = new MSBuildGraphFormatter();
|
||||||
|
break;
|
||||||
|
case "dgml":
|
||||||
|
formatter = new DGMLFormatter();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
app.Error.WriteLine($"Unknown output type: {outputType}.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatter.Format(graph, outputPathArgument.Value);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Execute(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
[DebuggerDisplay("{Name}")]
|
||||||
|
public class Project
|
||||||
|
{
|
||||||
|
public Project(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public Repository Repository { get; set; }
|
||||||
|
|
||||||
|
public IList<string> PackageReferences { get; set; } = Array.Empty<string>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,125 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using NuGet.LibraryModel;
|
||||||
|
using NuGet.ProjectModel;
|
||||||
|
using UniverseTools;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
[DebuggerDisplay("{Name}")]
|
||||||
|
public class Repository : IEquatable<Repository>
|
||||||
|
{
|
||||||
|
public Repository(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; private set; }
|
||||||
|
|
||||||
|
public IList<Project> Projects { get; } = new List<Project>();
|
||||||
|
|
||||||
|
public IList<Project> SupportProjects { get; } = new List<Project>();
|
||||||
|
|
||||||
|
public IEnumerable<Project> AllProjects => Projects.Concat(SupportProjects);
|
||||||
|
|
||||||
|
public static IList<Repository> ReadAllRepositories(string repositoriesRoot, DependencyGraphSpecProvider provider)
|
||||||
|
{
|
||||||
|
var directories = new DirectoryInfo(repositoriesRoot).GetDirectories();
|
||||||
|
var repositories = new Repository[directories.Length];
|
||||||
|
|
||||||
|
var sw = Stopwatch.StartNew();
|
||||||
|
Parallel.For(0, directories.Length, new ParallelOptions { MaxDegreeOfParallelism = 6 }, i =>
|
||||||
|
{
|
||||||
|
var directoryInfo = directories[i];
|
||||||
|
Console.WriteLine($"Gathering dependency information from {directoryInfo.Name}.");
|
||||||
|
|
||||||
|
var repository = Read(provider, directoryInfo.Name, directoryInfo.FullName);
|
||||||
|
repositories[i] = repository;
|
||||||
|
|
||||||
|
Console.WriteLine($"Done gathering dependency information from {directoryInfo.Name}.");
|
||||||
|
});
|
||||||
|
sw.Stop();
|
||||||
|
|
||||||
|
Console.WriteLine($"Done reading dependency information for all repos in {sw.Elapsed}.");
|
||||||
|
|
||||||
|
return repositories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Repository other) => string.Equals(Name, other.Name, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
public override int GetHashCode() => StringComparer.OrdinalIgnoreCase.GetHashCode(Name);
|
||||||
|
|
||||||
|
private static Repository Read(DependencyGraphSpecProvider provider, string name, string repositoryPath)
|
||||||
|
{
|
||||||
|
var repository = new Repository(name);
|
||||||
|
|
||||||
|
ReadSharedSourceProjects(Path.Combine(repositoryPath, "shared"), repository, repository.Projects);
|
||||||
|
var srcDirectory = Path.Combine(repositoryPath, "src");
|
||||||
|
|
||||||
|
var solutionFiles = Directory.EnumerateFiles(repositoryPath, "*.sln");
|
||||||
|
var knownProjects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var file in solutionFiles)
|
||||||
|
{
|
||||||
|
var spec = provider.GetDependencyGraphSpec(name, file);
|
||||||
|
foreach (var specProject in spec.Projects)
|
||||||
|
{
|
||||||
|
if (!knownProjects.Add(specProject.FilePath) ||
|
||||||
|
specProject.RestoreMetadata.ProjectStyle != ProjectStyle.PackageReference)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectPath = Path.GetFullPath(specProject.FilePath);
|
||||||
|
|
||||||
|
var project = new Project(specProject.Name)
|
||||||
|
{
|
||||||
|
PackageReferences = GetPackageReferences(specProject),
|
||||||
|
Repository = repository,
|
||||||
|
};
|
||||||
|
|
||||||
|
var projectGroup = projectPath.StartsWith(srcDirectory, StringComparison.OrdinalIgnoreCase) ?
|
||||||
|
repository.Projects :
|
||||||
|
repository.SupportProjects;
|
||||||
|
projectGroup.Add(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return repository;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<string> GetPackageReferences(NuGet.ProjectModel.PackageSpec specProject)
|
||||||
|
{
|
||||||
|
var allDependencies = Enumerable.Concat(
|
||||||
|
specProject.Dependencies,
|
||||||
|
specProject.TargetFrameworks.SelectMany(tfm => tfm.Dependencies))
|
||||||
|
.Distinct();
|
||||||
|
|
||||||
|
var packageReferences = allDependencies
|
||||||
|
.Where(d => d.LibraryRange.TypeConstraintAllows(LibraryDependencyTarget.Package))
|
||||||
|
.Select(d => d.Name)
|
||||||
|
.ToList();
|
||||||
|
return packageReferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ReadSharedSourceProjects(string sharedSourceProjectsRoot, Repository repository, IList<Project> projects)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(sharedSourceProjectsRoot))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var directory in new DirectoryInfo(sharedSourceProjectsRoot).EnumerateDirectories())
|
||||||
|
{
|
||||||
|
var project = new Project(directory.Name)
|
||||||
|
{
|
||||||
|
Repository = repository,
|
||||||
|
};
|
||||||
|
projects.Add(project);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace BuildGraph
|
||||||
|
{
|
||||||
|
public class TopologicalSort : IComparer<GraphNode>
|
||||||
|
{
|
||||||
|
public static readonly TopologicalSort Instance = new TopologicalSort();
|
||||||
|
|
||||||
|
public int Compare(GraphNode x, GraphNode y)
|
||||||
|
{
|
||||||
|
var xScore = GetOrder(x);
|
||||||
|
var yScore = GetOrder(y);
|
||||||
|
return xScore.CompareTo(yScore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetOrder(GraphNode node)
|
||||||
|
{
|
||||||
|
var visited = new List<GraphNode>();
|
||||||
|
return GetOrder(node, visited);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int GetOrder(GraphNode node, List<GraphNode> visited)
|
||||||
|
{
|
||||||
|
if (visited.Contains(node))
|
||||||
|
{
|
||||||
|
var cycle = string.Join(" -> ", visited.Select(v => v.Repository.Name));
|
||||||
|
throw new Exception($"Cycle detected in the build graph: {cycle} -> {node.Repository.Name}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var score = 0;
|
||||||
|
visited.Add(node);
|
||||||
|
foreach (var dependentNode in node.Incoming)
|
||||||
|
{
|
||||||
|
score = Math.Max(score, GetOrder(dependentNode, visited));
|
||||||
|
}
|
||||||
|
visited.RemoveAt(visited.Count - 1);
|
||||||
|
|
||||||
|
return score + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
|
||||||
# Visual Studio 14
|
|
||||||
VisualStudioVersion = 14.0.23107.0
|
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "PinVersion", "PinVersion\PinVersion.xproj", "{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}"
|
|
||||||
EndProject
|
|
||||||
Global
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
|
||||||
Debug|Any CPU = Debug|Any CPU
|
|
||||||
Release|Any CPU = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
|
||||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{3D3B5750-0C24-4F1C-9304-B5E4D85CF5A0}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
EndGlobal
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
|
||||||
<PropertyGroup>
|
|
||||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
|
|
||||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
|
|
||||||
<PropertyGroup Label="Globals">
|
|
||||||
<ProjectGuid>3d3b5750-0c24-4f1c-9304-b5e4d85cf5a0</ProjectGuid>
|
|
||||||
<RootNamespace>PinVersion</RootNamespace>
|
|
||||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
|
||||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath>
|
|
||||||
</PropertyGroup>
|
|
||||||
<PropertyGroup>
|
|
||||||
<SchemaVersion>2.0</SchemaVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
|
||||||
</Project>
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
// 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.Concurrent;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using NuGet.Common;
|
|
||||||
using NuGet.Protocol.Core.Types;
|
|
||||||
using NuGet.Protocol.Core.v3;
|
|
||||||
using NuGet.Versioning;
|
|
||||||
|
|
||||||
namespace PinVersion
|
|
||||||
{
|
|
||||||
public class Program
|
|
||||||
{
|
|
||||||
private static ConcurrentDictionary<string, Task<NuGetVersion>> _packageVersionLookup =
|
|
||||||
new ConcurrentDictionary<string, Task<NuGetVersion>>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
public static void Main(string[] args)
|
|
||||||
{
|
|
||||||
if (args.Length != 3)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine("Usage <package source> <Korebuild Tag> <repository-names-file>");
|
|
||||||
}
|
|
||||||
|
|
||||||
var packageSource = args[0];
|
|
||||||
var korebuildTag = args[1];
|
|
||||||
|
|
||||||
var repositoryNames = File.ReadAllLines(args[2]);
|
|
||||||
|
|
||||||
Task.WaitAll(repositoryNames
|
|
||||||
.Select(repositoryPath => ExecuteAsync(repositoryPath, packageSource, korebuildTag))
|
|
||||||
.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task ExecuteAsync(string repositoryPath, string packageSource, string korebuildTag)
|
|
||||||
{
|
|
||||||
var packageRepository = Repository.Factory.GetCoreV3(packageSource);
|
|
||||||
var metadataResource = await packageRepository.GetResourceAsync<MetadataResource>();
|
|
||||||
|
|
||||||
// Pin project.json files
|
|
||||||
foreach (var file in Directory.EnumerateFiles(repositoryPath, "project.json", SearchOption.AllDirectories))
|
|
||||||
{
|
|
||||||
var projectJson = JObject.Parse(File.ReadAllText(file));
|
|
||||||
var projectName = Path.GetFileName(Path.GetDirectoryName(file));
|
|
||||||
var latestPackageVersion = await GetOrAddVersion(metadataResource, projectName);
|
|
||||||
if (latestPackageVersion != null)
|
|
||||||
{
|
|
||||||
((JValue)projectJson["version"]).Value = latestPackageVersion.ToNormalizedString();
|
|
||||||
}
|
|
||||||
|
|
||||||
var frameworkDependencies = projectJson["frameworks"]
|
|
||||||
?.Cast<JProperty>()
|
|
||||||
?.Select(f => ((JObject)f.Value)["dependencies"])
|
|
||||||
?? Enumerable.Empty<JToken>();
|
|
||||||
var dependencies = Enumerable.Concat(new[] { projectJson["dependencies"] }, frameworkDependencies)
|
|
||||||
.Where(d => d != null)
|
|
||||||
.SelectMany(d => d)
|
|
||||||
.Cast<JProperty>();
|
|
||||||
|
|
||||||
foreach (var dependency in dependencies)
|
|
||||||
{
|
|
||||||
latestPackageVersion = await GetOrAddVersion(metadataResource, dependency.Name);
|
|
||||||
if (latestPackageVersion != null)
|
|
||||||
{
|
|
||||||
if (dependency.Value.Type == JTokenType.Object)
|
|
||||||
{
|
|
||||||
// "key": { "version": "1.0.0-*", "type": "build" }
|
|
||||||
var value = (JObject)dependency.Value;
|
|
||||||
value["version"] = latestPackageVersion.ToNormalizedString();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// "key": "version"
|
|
||||||
dependency.Value = latestPackageVersion.ToNormalizedString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using (var fileWriter = new JsonTextWriter(new StreamWriter(file)))
|
|
||||||
{
|
|
||||||
fileWriter.Formatting = Formatting.Indented;
|
|
||||||
fileWriter.Indentation = 2;
|
|
||||||
projectJson.WriteTo(fileWriter);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update KoreBuild path
|
|
||||||
|
|
||||||
var buildFiles = new[] { "build.ps1", "build.sh" };
|
|
||||||
foreach (var buildFile in buildFiles)
|
|
||||||
{
|
|
||||||
var buildFilePath = Path.Combine(repositoryPath, buildFile);
|
|
||||||
if (File.Exists(buildFilePath))
|
|
||||||
{
|
|
||||||
var content = File.ReadAllText(buildFilePath);
|
|
||||||
var replaced = content.Replace("KoreBuild/archive/release.zip", $"KoreBuild/archive/{korebuildTag}.zip");
|
|
||||||
|
|
||||||
if (content != replaced)
|
|
||||||
{
|
|
||||||
File.WriteAllText(buildFilePath, replaced);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Task<NuGetVersion> GetOrAddVersion(MetadataResource resource, string packageId)
|
|
||||||
{
|
|
||||||
return _packageVersionLookup.GetOrAdd(packageId, id =>
|
|
||||||
{
|
|
||||||
return resource.GetLatestVersion(
|
|
||||||
packageId,
|
|
||||||
includePrerelease: true,
|
|
||||||
includeUnlisted: false,
|
|
||||||
log: NullLogger.Instance,
|
|
||||||
token: default(CancellationToken));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
{
|
|
||||||
"version": "1.0.0-*",
|
|
||||||
"buildOptions": {
|
|
||||||
"emitEntryPoint": true
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"Newtonsoft.Json": "9.0.1",
|
|
||||||
"NuGet.Protocol.Core.v3": "3.5.0-beta-final"
|
|
||||||
},
|
|
||||||
"frameworks": {
|
|
||||||
"net451": { }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
using NuGet.Common;
|
||||||
|
using NuGet.Frameworks;
|
||||||
|
using NuGet.LibraryModel;
|
||||||
|
using NuGet.ProjectModel;
|
||||||
|
using NuGet.Protocol;
|
||||||
|
using NuGet.Protocol.Core.Types;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
using UniverseTools;
|
||||||
|
|
||||||
|
namespace PinVersions
|
||||||
|
{
|
||||||
|
class PinVersionUtility
|
||||||
|
{
|
||||||
|
private readonly string _repositoryRoot;
|
||||||
|
private readonly FindPackageByIdResource[] _findPackageResources;
|
||||||
|
private readonly ConcurrentDictionary<string, Task<NuGetVersion>> _exactMatches = new ConcurrentDictionary<string, Task<NuGetVersion>>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
private readonly DependencyGraphSpecProvider _provider;
|
||||||
|
private readonly SourceCacheContext _sourceCacheContext;
|
||||||
|
|
||||||
|
public PinVersionUtility(string repositoryRoot, List<string> pinSources, DependencyGraphSpecProvider provider)
|
||||||
|
{
|
||||||
|
_repositoryRoot = repositoryRoot;
|
||||||
|
_findPackageResources = new FindPackageByIdResource[pinSources.Count];
|
||||||
|
for (var i = 0; i < pinSources.Count; i++)
|
||||||
|
{
|
||||||
|
var repository = FactoryExtensionsV3.GetCoreV3(Repository.Factory, pinSources[i].Trim());
|
||||||
|
_findPackageResources[i] = repository.GetResource<FindPackageByIdResource>();
|
||||||
|
}
|
||||||
|
_provider = provider;
|
||||||
|
_sourceCacheContext = new SourceCacheContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Execute()
|
||||||
|
{
|
||||||
|
var repositoryDirectoryInfo = new DirectoryInfo(_repositoryRoot);
|
||||||
|
var knownProjects = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var slnFile in repositoryDirectoryInfo.EnumerateFiles("*.sln"))
|
||||||
|
{
|
||||||
|
var graphSpec = _provider.GetDependencyGraphSpec(repositoryDirectoryInfo.Name, slnFile.FullName);
|
||||||
|
foreach (var specProject in graphSpec.Projects)
|
||||||
|
{
|
||||||
|
if (!knownProjects.Add(specProject.FilePath) ||
|
||||||
|
specProject.RestoreMetadata.ProjectStyle != ProjectStyle.PackageReference)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var projectFileInfo = new FileInfo(specProject.FilePath);
|
||||||
|
var pinnedReferencesFile = Path.Combine(
|
||||||
|
specProject.RestoreMetadata.OutputPath,
|
||||||
|
projectFileInfo.Name + ".pinnedversions.targets");
|
||||||
|
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(pinnedReferencesFile));
|
||||||
|
|
||||||
|
var allDependencies = specProject.Dependencies.Select(dependency => new { Dependency = dependency, FrameworkName = NuGetFramework.AnyFramework })
|
||||||
|
.Concat(specProject.TargetFrameworks.SelectMany(tfm => tfm.Dependencies.Select(dependency => new { Dependency = dependency, tfm.FrameworkName })))
|
||||||
|
.Where(d => d.Dependency.LibraryRange.TypeConstraintAllows(LibraryDependencyTarget.Package));
|
||||||
|
|
||||||
|
var packageReferencesItemGroup = new XElement("ItemGroup");
|
||||||
|
foreach (var dependency in allDependencies)
|
||||||
|
{
|
||||||
|
var reference = dependency.Dependency;
|
||||||
|
var versionRange = reference.LibraryRange.VersionRange;
|
||||||
|
if (!versionRange.IsFloating)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var exactVersion = GetExactVersion(reference.Name, versionRange);
|
||||||
|
if (exactVersion == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadata = new List<XAttribute>
|
||||||
|
{
|
||||||
|
new XAttribute("Update", reference.Name),
|
||||||
|
new XAttribute("Version", exactVersion.ToNormalizedString()),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (dependency.FrameworkName != NuGetFramework.AnyFramework)
|
||||||
|
{
|
||||||
|
metadata.Add(new XAttribute("Condition", $"'$(TargetFramework)'=='{dependency.FrameworkName.GetShortFolderName()}'"));
|
||||||
|
}
|
||||||
|
|
||||||
|
packageReferencesItemGroup.Add(new XElement("PackageReference", metadata));
|
||||||
|
}
|
||||||
|
|
||||||
|
var pinnedVersionRoot = new XElement("Project", packageReferencesItemGroup);
|
||||||
|
File.WriteAllText(pinnedReferencesFile, pinnedVersionRoot.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private NuGetVersion GetExactVersion(string name, VersionRange range)
|
||||||
|
{
|
||||||
|
if (range.MinVersion == null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Unsupported version range {range}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_exactMatches.TryGetValue(name, out var versionTask))
|
||||||
|
{
|
||||||
|
versionTask = _exactMatches.GetOrAdd(name, GetExactVersionAsync(name, range.MinVersion));
|
||||||
|
}
|
||||||
|
|
||||||
|
return versionTask.Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<NuGetVersion> GetExactVersionAsync(string name, NuGetVersion floatingVersion)
|
||||||
|
{
|
||||||
|
foreach (var findPackageResource in _findPackageResources)
|
||||||
|
{
|
||||||
|
var packageVersions = await findPackageResource.GetAllVersionsAsync(name, _sourceCacheContext, NullLogger.Instance, default(CancellationToken));
|
||||||
|
|
||||||
|
var matchingVersions = packageVersions.Where(v => v.Version == floatingVersion.Version).ToList();
|
||||||
|
switch (matchingVersions.Count)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
return null;
|
||||||
|
case 1:
|
||||||
|
return matchingVersions[0];
|
||||||
|
default:
|
||||||
|
throw new Exception($"More than one version for {name} found that matches the specified version constraint: {string.Join(" ", matchingVersions)}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\shared\*.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.DotNet.Cli.Utils" Version="1.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.CommandLineUtils" Version="1.1.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.CommandLineUtils;
|
||||||
|
using UniverseTools;
|
||||||
|
|
||||||
|
namespace PinVersions
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandLineApplication();
|
||||||
|
|
||||||
|
var pinSourceOption = app.Option("-s|--source",
|
||||||
|
"Feed containing packages to pin.",
|
||||||
|
CommandOptionType.MultipleValue);
|
||||||
|
|
||||||
|
var packageSpecsDirectoryOption = app.Option("--graph-specs-root",
|
||||||
|
"Directory containing package specs. (Optional)",
|
||||||
|
CommandOptionType.SingleValue);
|
||||||
|
|
||||||
|
var repositoryArgument = app.Argument("Repository", "Repository directory");
|
||||||
|
|
||||||
|
app.OnExecute(() =>
|
||||||
|
{
|
||||||
|
if (!pinSourceOption.HasValue())
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"Option {pinSourceOption.Template} must have a value.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(repositoryArgument.Value))
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine($"Repository argument must be specified.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var graphSpecProvider = packageSpecsDirectoryOption.HasValue() ?
|
||||||
|
new DependencyGraphSpecProvider(packageSpecsDirectoryOption.Value().Trim()) :
|
||||||
|
DependencyGraphSpecProvider.Default;
|
||||||
|
|
||||||
|
using (graphSpecProvider)
|
||||||
|
{
|
||||||
|
var pinVersionUtility = new PinVersionUtility(repositoryArgument.Value.Trim(), pinSourceOption.Values, graphSpecProvider);
|
||||||
|
pinVersionUtility.Execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Execute(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.DotNet.Cli.Utils;
|
||||||
|
using NuGet.ProjectModel;
|
||||||
|
|
||||||
|
namespace UniverseTools
|
||||||
|
{
|
||||||
|
public class DependencyGraphSpecProvider : IDisposable
|
||||||
|
{
|
||||||
|
private readonly string _packageSpecDirectory;
|
||||||
|
private readonly bool _deleteSpecDirectoryOnDispose;
|
||||||
|
private readonly string _muxerPath;
|
||||||
|
|
||||||
|
public DependencyGraphSpecProvider(string packageSpecDirectory)
|
||||||
|
: this(packageSpecDirectory, deleteSpecDirectoryOnDispose: false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private DependencyGraphSpecProvider(string packageSpecDirectory, bool deleteSpecDirectoryOnDispose)
|
||||||
|
{
|
||||||
|
_packageSpecDirectory = packageSpecDirectory;
|
||||||
|
_deleteSpecDirectoryOnDispose = deleteSpecDirectoryOnDispose;
|
||||||
|
_muxerPath = new Muxer().MuxerPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DependencyGraphSpecProvider Default { get; } =
|
||||||
|
new DependencyGraphSpecProvider(Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()), deleteSpecDirectoryOnDispose: true);
|
||||||
|
|
||||||
|
public DependencyGraphSpec GetDependencyGraphSpec(string repositoryName, string solutionPath)
|
||||||
|
{
|
||||||
|
var outputFile = Path.Combine(_packageSpecDirectory, repositoryName, Path.GetFileName(solutionPath) + ".json");
|
||||||
|
|
||||||
|
if (!File.Exists(outputFile))
|
||||||
|
{
|
||||||
|
RunMSBuild(solutionPath, outputFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DependencyGraphSpec.Load(outputFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RunMSBuild(string solutionPath, string outputFile)
|
||||||
|
{
|
||||||
|
var psi = new ProcessStartInfo(_muxerPath);
|
||||||
|
|
||||||
|
var arguments = new List<string>
|
||||||
|
{
|
||||||
|
"msbuild",
|
||||||
|
$"\"{solutionPath}\"",
|
||||||
|
"/t:GenerateRestoreGraphFile",
|
||||||
|
"/nologo",
|
||||||
|
"/v:q",
|
||||||
|
"/p:BuildProjectReferences=false",
|
||||||
|
$"/p:RestoreGraphOutputPath=\"{outputFile}\"",
|
||||||
|
};
|
||||||
|
|
||||||
|
psi.Arguments = string.Join(" ", arguments);
|
||||||
|
psi.RedirectStandardOutput = true;
|
||||||
|
|
||||||
|
var process = new Process
|
||||||
|
{
|
||||||
|
StartInfo = psi,
|
||||||
|
EnableRaisingEvents = true,
|
||||||
|
};
|
||||||
|
process.OutputDataReceived += (sender, args) =>
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(args.Data))
|
||||||
|
{
|
||||||
|
Console.WriteLine(args.Data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using (process)
|
||||||
|
{
|
||||||
|
process.Start();
|
||||||
|
process.BeginOutputReadLine();
|
||||||
|
|
||||||
|
process.WaitForExit(60 * 5000);
|
||||||
|
if (process.ExitCode != 0)
|
||||||
|
{
|
||||||
|
throw new Exception($"{psi.FileName} {psi.Arguments} failed. Exit code {process.ExitCode}.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_deleteSpecDirectoryOnDispose)
|
||||||
|
{
|
||||||
|
Directory.Delete(_packageSpecDirectory, recursive: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue