Add initial update-dependencies script.
This script can be used to automatically update dotnet/cli's dependencies on other repos like CoreFX, NuGet, etc. Currently the script supports updating the CoreFX dependencies.
This commit is contained in:
parent
6fec9ad1fa
commit
eccf44c200
10 changed files with 575 additions and 7 deletions
|
@ -79,6 +79,8 @@ Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test.UnitTests", "te
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test.Tests", "test\dotnet-test.Tests\dotnet-test.Tests.xproj", "{60C33D0A-A5D8-4AB0-9956-1F804654DF05}"
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "dotnet-test.Tests", "test\dotnet-test.Tests\dotnet-test.Tests.xproj", "{60C33D0A-A5D8-4AB0-9956-1F804654DF05}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "update-dependencies", "scripts\update-dependencies\update-dependencies.xproj", "{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -555,6 +557,22 @@ Global
|
||||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
{60C33D0A-A5D8-4AB0-9956-1F804654DF05}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.MinSizeRel|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.MinSizeRel|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.MinSizeRel|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.MinSizeRel|x64.Build.0 = Debug|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.RelWithDebInfo|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.RelWithDebInfo|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.RelWithDebInfo|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726}.RelWithDebInfo|x64.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -591,5 +609,6 @@ Global
|
||||||
{0724ED7C-56E3-4604-9970-25E600611383} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
{0724ED7C-56E3-4604-9970-25E600611383} = {ED2FE3E2-F7E7-4389-8231-B65123F2076F}
|
||||||
{857274AC-E741-4266-A7FD-14DEE0C1CC96} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
{857274AC-E741-4266-A7FD-14DEE0C1CC96} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||||
{60C33D0A-A5D8-4AB0-9956-1F804654DF05} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
{60C33D0A-A5D8-4AB0-9956-1F804654DF05} = {17735A9D-BFD9-4585-A7CB-3208CA6EA8A7}
|
||||||
|
{A28BD8AC-DF15-4F58-8299-98A9AE2B8726} = {88278B81-7649-45DC-8A6A-D3A645C5AFC3}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -24,20 +24,23 @@ namespace Microsoft.DotNet.Cli.Build.Framework
|
||||||
StdErr = stdErr;
|
StdErr = stdErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EnsureSuccessful()
|
public void EnsureSuccessful(bool suppressOutput = false)
|
||||||
{
|
{
|
||||||
if(ExitCode != 0)
|
if(ExitCode != 0)
|
||||||
{
|
{
|
||||||
StringBuilder message = new StringBuilder($"Command failed with exit code {ExitCode}: {StartInfo.FileName} {StartInfo.Arguments}");
|
StringBuilder message = new StringBuilder($"Command failed with exit code {ExitCode}: {StartInfo.FileName} {StartInfo.Arguments}");
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(StdOut))
|
if (!suppressOutput)
|
||||||
{
|
{
|
||||||
message.AppendLine($"{Environment.NewLine}Standard Output:{Environment.NewLine}{StdOut}");
|
if (!string.IsNullOrEmpty(StdOut))
|
||||||
}
|
{
|
||||||
|
message.AppendLine($"{Environment.NewLine}Standard Output:{Environment.NewLine}{StdOut}");
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(StdErr))
|
if (!string.IsNullOrEmpty(StdErr))
|
||||||
{
|
{
|
||||||
message.AppendLine($"{Environment.NewLine}Standard Error:{Environment.NewLine}{StdErr}");
|
message.AppendLine($"{Environment.NewLine}Standard Error:{Environment.NewLine}{StdErr}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new BuildFailureException(message.ToString());
|
throw new BuildFailureException(message.ToString());
|
||||||
|
|
51
scripts/update-dependencies.ps1
Normal file
51
scripts/update-dependencies.ps1
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
#
|
||||||
|
|
||||||
|
param(
|
||||||
|
[string[]]$Targets=@("Default"),
|
||||||
|
[switch]$Help)
|
||||||
|
|
||||||
|
if($Help)
|
||||||
|
{
|
||||||
|
Write-Host "Usage: .\update-dependencies.ps1 [-Targets <TARGETS...>]"
|
||||||
|
Write-Host ""
|
||||||
|
Write-Host "Options:"
|
||||||
|
Write-Host " -Targets <TARGETS...> Comma separated build targets to run (UpdateFiles, PushPR; Default is everything)"
|
||||||
|
Write-Host " -Help Display this help message"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Use a repo-local install directory (but not the artifacts directory because that gets cleaned a lot
|
||||||
|
if (!$env:DOTNET_INSTALL_DIR)
|
||||||
|
{
|
||||||
|
$env:DOTNET_INSTALL_DIR="$PSScriptRoot\..\.dotnet_stage0\Windows\$Architecture"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install a stage 0
|
||||||
|
Write-Host "Installing .NET Core CLI Stage 0"
|
||||||
|
& "$PSScriptRoot\obtain\install.ps1" -Architecture x64
|
||||||
|
|
||||||
|
# Put the stage0 on the path
|
||||||
|
$env:PATH = "$env:DOTNET_INSTALL_DIR\cli\bin;$env:PATH"
|
||||||
|
|
||||||
|
$appPath = "$PSScriptRoot\update-dependencies"
|
||||||
|
|
||||||
|
# Restore the build scripts
|
||||||
|
Write-Host "Restoring Build Script projects..."
|
||||||
|
pushd $PSScriptRoot
|
||||||
|
dotnet restore
|
||||||
|
if($LASTEXITCODE -ne 0) { throw "Failed to restore" }
|
||||||
|
popd
|
||||||
|
|
||||||
|
# Publish the app
|
||||||
|
Write-Host "Compiling App $appPath..."
|
||||||
|
dotnet publish "$appPath" -o "$appPath\bin" --framework netstandardapp1.5
|
||||||
|
if($LASTEXITCODE -ne 0) { throw "Failed to compile build scripts" }
|
||||||
|
|
||||||
|
# Run the app
|
||||||
|
Write-Host "Invoking App $appPath..."
|
||||||
|
Write-Host " Configuration: $env:CONFIGURATION"
|
||||||
|
& "$appPath\bin\update-dependencies.exe" @Targets
|
||||||
|
if($LASTEXITCODE -ne 0) { throw "Build failed" }
|
74
scripts/update-dependencies/Config.cs
Normal file
74
scripts/update-dependencies/Config.cs
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.DotNet.Cli.Build.Framework;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Scripts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Holds the configuration information for the update-dependencies script.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The following Environment Variables are required by this script:
|
||||||
|
///
|
||||||
|
/// GITHUB_USER - The user to commit the changes as.
|
||||||
|
/// GITHUB_EMAIL - The user's email to commit the changes as.
|
||||||
|
/// GITHUB_PASSWORD - The password/personal access token of the GitHub user.
|
||||||
|
///
|
||||||
|
/// The following Environment Variables can optionally be specified:
|
||||||
|
///
|
||||||
|
/// COREFX_VERSION_URL - The Url to get the current CoreFx version. (ex. "https://raw.githubusercontent.com/dotnet/versions/master/dotnet/corefx/release/1.0.0-rc2/LKG.txt")
|
||||||
|
/// GITHUB_ORIGIN_OWNER - The owner of the GitHub fork to push the commit and create the PR from. (ex. "dotnet-bot")
|
||||||
|
/// GITHUB_UPSTREAM_OWNER - The owner of the GitHub base repo to create the PR to. (ex. "dotnet")
|
||||||
|
/// GITHUB_PROJECT - The repo name under the ORIGIN and UPSTREAM owners. (ex. "cli")
|
||||||
|
/// GITHUB_UPSTREAM_BRANCH - The branch in the GitHub base repo to create the PR to. (ex. "rel/1.0.0")
|
||||||
|
/// </remarks>
|
||||||
|
public class Config
|
||||||
|
{
|
||||||
|
public static Config Instance { get; } = Read();
|
||||||
|
|
||||||
|
public string UserName { get; set; }
|
||||||
|
public string Email { get; set; }
|
||||||
|
public string Password { get; set; }
|
||||||
|
public string CoreFxVersionUrl { get; set; }
|
||||||
|
public string GitHubOriginOwner { get; set; }
|
||||||
|
public string GitHubUpstreamOwner { get; set; }
|
||||||
|
public string GitHubProject { get; set; }
|
||||||
|
public string GitHubUpstreamBranch { get; set; }
|
||||||
|
|
||||||
|
private static Config Read()
|
||||||
|
{
|
||||||
|
string userName = GetEnvironmentVariable("GITHUB_USER");
|
||||||
|
|
||||||
|
return new Config
|
||||||
|
{
|
||||||
|
UserName = userName,
|
||||||
|
Email = GetEnvironmentVariable("GITHUB_EMAIL"),
|
||||||
|
Password = GetEnvironmentVariable("GITHUB_PASSWORD"),
|
||||||
|
|
||||||
|
CoreFxVersionUrl = GetEnvironmentVariable("COREFX_VERSION_URL", "https://raw.githubusercontent.com/dotnet/versions/master/dotnet/corefx/release/1.0.0-rc2/LKG.txt"),
|
||||||
|
GitHubOriginOwner = GetEnvironmentVariable("GITHUB_ORIGIN_OWNER", userName),
|
||||||
|
GitHubUpstreamOwner = GetEnvironmentVariable("GITHUB_UPSTREAM_OWNER", "dotnet"),
|
||||||
|
GitHubProject = GetEnvironmentVariable("GITHUB_PROJECT", "cli"),
|
||||||
|
GitHubUpstreamBranch = GetEnvironmentVariable("GITHUB_UPSTREAM_BRANCH", "rel/1.0.0"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetEnvironmentVariable(string name, string defaultValue = null)
|
||||||
|
{
|
||||||
|
string value = Environment.GetEnvironmentVariable(name);
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
value = defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.IsNullOrEmpty(value))
|
||||||
|
{
|
||||||
|
throw new BuildFailureException($"Can't find environment variable '{name}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
scripts/update-dependencies/Dirs.cs
Normal file
12
scripts/update-dependencies/Dirs.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Scripts
|
||||||
|
{
|
||||||
|
public static class Dirs
|
||||||
|
{
|
||||||
|
public static readonly string RepoRoot = Directory.GetCurrentDirectory();
|
||||||
|
}
|
||||||
|
}
|
25
scripts/update-dependencies/Program.cs
Normal file
25
scripts/update-dependencies/Program.cs
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using Microsoft.DotNet.Cli.Build.Framework;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Scripts
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
DebugHelper.HandleDebugSwitch(ref args);
|
||||||
|
|
||||||
|
return BuildSetup.Create(".NET CLI Dependency Updater")
|
||||||
|
.UseTargets(new[]
|
||||||
|
{
|
||||||
|
new BuildTarget("Default", "Dependency Updater Goals", new [] { "UpdateFiles", "PushPR" }),
|
||||||
|
new BuildTarget("UpdateFiles", "Dependency Updater Goals"),
|
||||||
|
new BuildTarget("PushPR", "Dependency Updater Goals"),
|
||||||
|
})
|
||||||
|
.UseAllTargetsFromAssembly<Program>()
|
||||||
|
.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
scripts/update-dependencies/PushPRTargets.cs
Normal file
108
scripts/update-dependencies/PushPRTargets.cs
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Microsoft.DotNet.Cli.Build.Framework;
|
||||||
|
using Octokit;
|
||||||
|
|
||||||
|
using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Scripts
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a GitHub Pull Request for the current changes in the repo.
|
||||||
|
/// </summary>
|
||||||
|
public static class PushPRTargets
|
||||||
|
{
|
||||||
|
private const string PullRequestTitle = "Updating dependencies from last known good builds";
|
||||||
|
|
||||||
|
private static readonly Config s_config = Config.Instance;
|
||||||
|
|
||||||
|
[Target(nameof(CommitChanges), nameof(CreatePR))]
|
||||||
|
public static BuildTargetResult PushPR(BuildTargetContext c) => c.Success();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Commits all the current changes in the repo and pushes the commit to a remote
|
||||||
|
/// so a PR can be created for it.
|
||||||
|
/// </summary>
|
||||||
|
[Target]
|
||||||
|
public static BuildTargetResult CommitChanges(BuildTargetContext c)
|
||||||
|
{
|
||||||
|
Cmd("git", "add", ".")
|
||||||
|
.Execute()
|
||||||
|
.EnsureSuccessful();
|
||||||
|
|
||||||
|
string userName = s_config.UserName;
|
||||||
|
string email = s_config.Email;
|
||||||
|
|
||||||
|
Cmd("git", "commit", "-m", PullRequestTitle, "--author", $"{userName} <{email}>")
|
||||||
|
.EnvironmentVariable("GIT_COMMITTER_NAME", userName)
|
||||||
|
.EnvironmentVariable("GIT_COMMITTER_EMAIL", email)
|
||||||
|
.Execute()
|
||||||
|
.EnsureSuccessful();
|
||||||
|
|
||||||
|
string remoteUrl = $"github.com/{s_config.GitHubOriginOwner}/{s_config.GitHubProject}.git";
|
||||||
|
string remoteBranchName = $"UpdateDependencies{DateTime.UtcNow.ToString("yyyyMMddhhmmss")}";
|
||||||
|
string refSpec = $"HEAD:refs/heads/{remoteBranchName}";
|
||||||
|
|
||||||
|
string logMessage = $"git push https://{remoteUrl} {refSpec}";
|
||||||
|
BuildReporter.BeginSection("EXEC", logMessage);
|
||||||
|
|
||||||
|
CommandResult pushResult =
|
||||||
|
Cmd("git", "push", $"https://{userName}:{s_config.Password}@{remoteUrl}", refSpec)
|
||||||
|
.QuietBuildReporter() // we don't want secrets showing up in our logs
|
||||||
|
.CaptureStdErr() // git push will write to StdErr upon success, disable that
|
||||||
|
.CaptureStdOut()
|
||||||
|
.Execute();
|
||||||
|
|
||||||
|
var message = logMessage + $" exited with {pushResult.ExitCode}";
|
||||||
|
if (pushResult.ExitCode == 0)
|
||||||
|
{
|
||||||
|
BuildReporter.EndSection("EXEC", message.Green(), success: true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BuildReporter.EndSection("EXEC", message.Red().Bold(), success: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
pushResult.EnsureSuccessful(suppressOutput: true);
|
||||||
|
|
||||||
|
c.SetRemoteBranchName(remoteBranchName);
|
||||||
|
|
||||||
|
return c.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a GitHub PR for the remote branch created above.
|
||||||
|
/// </summary>
|
||||||
|
[Target]
|
||||||
|
public static BuildTargetResult CreatePR(BuildTargetContext c)
|
||||||
|
{
|
||||||
|
string remoteBranchName = c.GetRemoteBranchName();
|
||||||
|
|
||||||
|
NewPullRequest prInfo = new NewPullRequest(
|
||||||
|
PullRequestTitle,
|
||||||
|
s_config.GitHubOriginOwner + ":" + remoteBranchName,
|
||||||
|
s_config.GitHubUpstreamBranch);
|
||||||
|
|
||||||
|
GitHubClient gitHub = new GitHubClient(new ProductHeaderValue("dotnetDependencyUpdater"));
|
||||||
|
|
||||||
|
gitHub.Credentials = new Credentials(s_config.Password);
|
||||||
|
|
||||||
|
PullRequest createdPR = gitHub.PullRequest.Create(s_config.GitHubUpstreamOwner, s_config.GitHubProject, prInfo).Result;
|
||||||
|
c.Info($"Created Pull Request: {createdPR.HtmlUrl}");
|
||||||
|
|
||||||
|
return c.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetRemoteBranchName(this BuildTargetContext c)
|
||||||
|
{
|
||||||
|
return (string)c.BuildContext["RemoteBranchName"];
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetRemoteBranchName(this BuildTargetContext c, string value)
|
||||||
|
{
|
||||||
|
c.BuildContext["RemoteBranchName"] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
233
scripts/update-dependencies/UpdateFilesTargets.cs
Normal file
233
scripts/update-dependencies/UpdateFilesTargets.cs
Normal file
|
@ -0,0 +1,233 @@
|
||||||
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
||||||
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using Microsoft.DotNet.Cli.Build.Framework;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using NuGet.Versioning;
|
||||||
|
|
||||||
|
namespace Microsoft.DotNet.Scripts
|
||||||
|
{
|
||||||
|
public static class UpdateFilesTargets
|
||||||
|
{
|
||||||
|
private static HttpClient s_client = new HttpClient();
|
||||||
|
|
||||||
|
[Target(nameof(GetDependencies), nameof(ReplaceVersions))]
|
||||||
|
public static BuildTargetResult UpdateFiles(BuildTargetContext c) => c.Success();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all the dependency information and puts it in the build properties.
|
||||||
|
/// </summary>
|
||||||
|
[Target]
|
||||||
|
public static BuildTargetResult GetDependencies(BuildTargetContext c)
|
||||||
|
{
|
||||||
|
string coreFxLkgVersion = s_client.GetStringAsync(Config.Instance.CoreFxVersionUrl).Result;
|
||||||
|
coreFxLkgVersion = coreFxLkgVersion.Trim();
|
||||||
|
|
||||||
|
const string coreFxIdPattern = @"^(?i)((System\..*)|(NETStandard\.Library)|(Microsoft\.CSharp)|(Microsoft\.NETCore.*)|(Microsoft\.TargetingPack\.Private\.(CoreCLR|NETNative))|(Microsoft\.Win32\..*)|(Microsoft\.VisualBasic))$";
|
||||||
|
const string coreFxIdExclusionPattern = @"System.CommandLine";
|
||||||
|
|
||||||
|
List<DependencyInfo> dependencyInfos = c.GetDependencyInfo();
|
||||||
|
dependencyInfos.Add(new DependencyInfo()
|
||||||
|
{
|
||||||
|
Name = "CoreFx",
|
||||||
|
IdPattern = coreFxIdPattern,
|
||||||
|
IdExclusionPattern = coreFxIdExclusionPattern,
|
||||||
|
NewReleaseVersion = coreFxLkgVersion
|
||||||
|
});
|
||||||
|
|
||||||
|
return c.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<DependencyInfo> GetDependencyInfo(this BuildTargetContext c)
|
||||||
|
{
|
||||||
|
const string propertyName = "DependencyInfo";
|
||||||
|
|
||||||
|
List<DependencyInfo> dependencyInfos;
|
||||||
|
object dependencyInfosObj;
|
||||||
|
if (c.BuildContext.Properties.TryGetValue(propertyName, out dependencyInfosObj))
|
||||||
|
{
|
||||||
|
dependencyInfos = (List<DependencyInfo>)dependencyInfosObj;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dependencyInfos = new List<DependencyInfo>();
|
||||||
|
c.BuildContext[propertyName] = dependencyInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dependencyInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Target(nameof(ReplaceProjectJson), nameof(ReplaceCrossGen))]
|
||||||
|
public static BuildTargetResult ReplaceVersions(BuildTargetContext c) => c.Success();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replaces all the dependency versions in the project.json files.
|
||||||
|
/// </summary>
|
||||||
|
[Target]
|
||||||
|
public static BuildTargetResult ReplaceProjectJson(BuildTargetContext c)
|
||||||
|
{
|
||||||
|
List<DependencyInfo> dependencyInfos = c.GetDependencyInfo();
|
||||||
|
|
||||||
|
IEnumerable<string> projectJsonFiles = Enumerable.Union(
|
||||||
|
Directory.GetFiles(Dirs.RepoRoot, "project.json", SearchOption.AllDirectories),
|
||||||
|
Directory.GetFiles(Path.Combine(Dirs.RepoRoot, @"src\dotnet\commands\dotnet-new"), "project.json.template", SearchOption.AllDirectories));
|
||||||
|
|
||||||
|
JObject projectRoot;
|
||||||
|
foreach (string projectJsonFile in projectJsonFiles)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
projectRoot = ReadProject(projectJsonFile);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
c.Warn($"Non-fatal exception occurred reading '{projectJsonFile}'. Skipping file. Exception: {e}. ");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool changedAnyPackage = FindAllDependencyProperties(projectRoot)
|
||||||
|
.Select(dependencyProperty => ReplaceDependencyVersion(dependencyProperty, dependencyInfos))
|
||||||
|
.ToArray()
|
||||||
|
.Any(shouldWrite => shouldWrite);
|
||||||
|
|
||||||
|
if (changedAnyPackage)
|
||||||
|
{
|
||||||
|
c.Info($"Writing changes to {projectJsonFile}");
|
||||||
|
WriteProject(projectRoot, projectJsonFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Success();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replaces the single dependency with the updated version, if it matches any of the dependencies that need to be updated.
|
||||||
|
/// </summary>
|
||||||
|
private static bool ReplaceDependencyVersion(JProperty dependencyProperty, List<DependencyInfo> dependencyInfos)
|
||||||
|
{
|
||||||
|
string id = dependencyProperty.Name;
|
||||||
|
foreach (DependencyInfo dependencyInfo in dependencyInfos)
|
||||||
|
{
|
||||||
|
if (Regex.IsMatch(id, dependencyInfo.IdPattern))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(dependencyInfo.IdExclusionPattern) || !Regex.IsMatch(id, dependencyInfo.IdExclusionPattern))
|
||||||
|
{
|
||||||
|
string version;
|
||||||
|
if (dependencyProperty.Value is JObject)
|
||||||
|
{
|
||||||
|
version = dependencyProperty.Value["version"].Value<string>();
|
||||||
|
}
|
||||||
|
else if (dependencyProperty.Value is JValue)
|
||||||
|
{
|
||||||
|
version = dependencyProperty.Value.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"Invalid package project.json version {dependencyProperty}");
|
||||||
|
}
|
||||||
|
|
||||||
|
VersionRange dependencyVersionRange = VersionRange.Parse(version);
|
||||||
|
NuGetVersion dependencyVersion = dependencyVersionRange.MinVersion;
|
||||||
|
|
||||||
|
string newReleaseVersion = dependencyInfo.NewReleaseVersion;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(dependencyVersion.Release) && dependencyVersion.Release != newReleaseVersion)
|
||||||
|
{
|
||||||
|
string newVersion = new NuGetVersion(
|
||||||
|
dependencyVersion.Major,
|
||||||
|
dependencyVersion.Minor,
|
||||||
|
dependencyVersion.Patch,
|
||||||
|
newReleaseVersion,
|
||||||
|
dependencyVersion.Metadata).ToNormalizedString();
|
||||||
|
|
||||||
|
if (dependencyProperty.Value is JObject)
|
||||||
|
{
|
||||||
|
dependencyProperty.Value["version"] = newVersion;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dependencyProperty.Value = newVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JObject ReadProject(string projectJsonPath)
|
||||||
|
{
|
||||||
|
using (TextReader projectFileReader = File.OpenText(projectJsonPath))
|
||||||
|
{
|
||||||
|
var projectJsonReader = new JsonTextReader(projectFileReader);
|
||||||
|
|
||||||
|
var serializer = new JsonSerializer();
|
||||||
|
return serializer.Deserialize<JObject>(projectJsonReader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteProject(JObject projectRoot, string projectJsonPath)
|
||||||
|
{
|
||||||
|
string projectJson = JsonConvert.SerializeObject(projectRoot, Formatting.Indented);
|
||||||
|
|
||||||
|
File.WriteAllText(projectJsonPath, projectJson + Environment.NewLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable<JProperty> FindAllDependencyProperties(JObject projectJsonRoot)
|
||||||
|
{
|
||||||
|
return projectJsonRoot
|
||||||
|
.Descendants()
|
||||||
|
.OfType<JProperty>()
|
||||||
|
.Where(property => property.Name == "dependencies")
|
||||||
|
.Select(property => property.Value)
|
||||||
|
.SelectMany(o => o.Children<JProperty>());
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DependencyInfo
|
||||||
|
{
|
||||||
|
public string Name { get; set; }
|
||||||
|
public string IdPattern { get; set; }
|
||||||
|
public string IdExclusionPattern { get; set; }
|
||||||
|
public string NewReleaseVersion { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Replaces version number that is hard-coded in the CrossGen script.
|
||||||
|
/// </summary>
|
||||||
|
[Target]
|
||||||
|
public static BuildTargetResult ReplaceCrossGen(BuildTargetContext c)
|
||||||
|
{
|
||||||
|
DependencyInfo coreFXInfo = c.GetDependencyInfo().Single(d => d.Name == "CoreFx");
|
||||||
|
|
||||||
|
string compileTargetsPath = Path.Combine(Dirs.RepoRoot, @"scripts\dotnet-cli-build\CompileTargets.cs");
|
||||||
|
string compileTargetsContent = File.ReadAllText(compileTargetsPath);
|
||||||
|
|
||||||
|
Regex regex = new Regex(@"CoreCLRVersion = ""(?<version>\d.\d.\d)-(?<release>.*)"";");
|
||||||
|
compileTargetsContent = regex.Replace(compileTargetsContent, m =>
|
||||||
|
{
|
||||||
|
string replacedValue = m.Value;
|
||||||
|
Group releaseGroup = m.Groups["release"];
|
||||||
|
|
||||||
|
replacedValue = replacedValue.Remove(releaseGroup.Index - m.Index, releaseGroup.Length);
|
||||||
|
replacedValue = replacedValue.Insert(releaseGroup.Index - m.Index, coreFXInfo.NewReleaseVersion);
|
||||||
|
|
||||||
|
return replacedValue;
|
||||||
|
});
|
||||||
|
|
||||||
|
File.WriteAllText(compileTargetsPath, compileTargetsContent, Encoding.UTF8);
|
||||||
|
|
||||||
|
return c.Success();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
25
scripts/update-dependencies/project.json
Normal file
25
scripts/update-dependencies/project.json
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"version": "1.0.0-*",
|
||||||
|
"description": "Updates the repos dependencies",
|
||||||
|
"compilationOptions": {
|
||||||
|
"emitEntryPoint": true
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"NETStandard.Library": "1.5.0-rc2-23911",
|
||||||
|
"Microsoft.CSharp": "4.0.1-rc2-23911",
|
||||||
|
"System.Runtime.Serialization.Primitives": "4.1.1-rc2-23911",
|
||||||
|
"Microsoft.DotNet.Cli.Build.Framework": "1.0.0-*",
|
||||||
|
"NuGet.Versioning": "3.4.0-rtm-0764",
|
||||||
|
"Newtonsoft.Json": "7.0.1",
|
||||||
|
"Octokit": "0.18.0",
|
||||||
|
"Microsoft.Net.Http": "2.2.29"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"netstandardapp1.5": {
|
||||||
|
"imports": [
|
||||||
|
"dnxcore50",
|
||||||
|
"portable-net45+win"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
scripts/update-dependencies/update-dependencies.xproj
Normal file
18
scripts/update-dependencies/update-dependencies.xproj
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
<?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>a28bd8ac-df15-4f58-8299-98a9ae2b8726</ProjectGuid>
|
||||||
|
<RootNamespace>Microsoft.DotNet.Scripts</RootNamespace>
|
||||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
|
||||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin</OutputPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
|
||||||
|
</Project>
|
Loading…
Reference in a new issue