diff --git a/scripts/UpdateDependencies.ps1 b/scripts/UpdateDependencies.ps1 index 02f799614a..4430f93f00 100755 --- a/scripts/UpdateDependencies.ps1 +++ b/scripts/UpdateDependencies.ps1 @@ -6,7 +6,8 @@ [CmdletBinding()] param( [Parameter(Mandatory = $true)] - $BuildXml + $BuildXml, + [string[]]$ConfigVars = @() ) $ErrorActionPreference = 'Stop' @@ -19,12 +20,12 @@ $depsPath = Resolve-Path "$PSScriptRoot/../build/dependencies.props" if ($BuildXml -like 'http*') { $url = $BuildXml New-Item -Type Directory "$PSScriptRoot/../obj/" -ErrorAction Ignore - $BuildXml = "$PSScriptRoot/../obj/build.xml" + $localXml = "$PSScriptRoot/../obj/build.xml" Write-Verbose "Downloading from $url to $BuildXml" - Invoke-WebRequest -OutFile $BuildXml $url + Invoke-WebRequest -OutFile $localXml $url } -[xml] $remoteDeps = LoadXml $BuildXml +[xml] $remoteDeps = LoadXml $localXml $count = 0 $variables = @{} @@ -36,15 +37,20 @@ foreach ($package in $remoteDeps.SelectNodes('//Package')) { Write-Verbose "Found {id: $packageId, version: $packageVersion, varName: $varName }" if ($variables[$varName]) { - $variables[$varName] += $packageVersion - } else { + if ($variables[$varName].Where( {$_ -eq $packageVersion}, 'First').Count -eq 0) { + $variables[$varName] += $packageVersion + } + } + else { $variables[$varName] = @($packageVersion) } } +$updatedVars = @{} + foreach ($varName in ($variables.Keys | sort)) { $packageVersions = $variables[$varName] - if ($packageVersions.Length -gt 1){ + if ($packageVersions.Length -gt 1) { Write-Warning "Skipped $varName. Multiple version found. { $($packageVersions -join ', ') }." continue } @@ -56,12 +62,33 @@ foreach ($varName in ($variables.Keys | sort)) { $depVarNode.InnerText = $packageVersion $count++ Write-Host -f DarkGray " Updating $varName to $packageVersion" + $updatedVars[$varName] = $packageVersion } } if ($count -gt 0) { Write-Host -f Cyan "Updating $count version variables in $depsPath" SaveXml $dependencies $depsPath + + # Ensure dotnet is installed + & "$PSScriptRoot\..\run.ps1" install-tools + + $ProjectPath = "$PSScriptRoot\update-dependencies\update-dependencies.csproj" + + $ConfigVars += "--BuildXml" + $ConfigVars += $BuildXml + + $ConfigVars += "--UpdatedVersions" + $varString = "" + foreach ($updatedVar in $updatedVars.GetEnumerator()) { + $varString += "$($updatedVar.Name)=$($updatedVar.Value);" + } + $ConfigVars += $varString + + # Restore and run the app + Write-Host "Invoking App $ProjectPath..." + Invoke-Expression "dotnet run -p `"$ProjectPath`" @ConfigVars" + if ($LASTEXITCODE -ne 0) { throw "Build failed" } } else { Write-Host -f Green "No changes found" diff --git a/scripts/update-dependencies/Config.cs b/scripts/update-dependencies/Config.cs new file mode 100644 index 0000000000..ddb590c944 --- /dev/null +++ b/scripts/update-dependencies/Config.cs @@ -0,0 +1,26 @@ +// 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. + +namespace Microsoft.Dotnet.Scripts +{ + public class Config + { + public string UpdatedVersions { get; set; } + public string BuildXml { get; set; } + public string GithubUsername {get; set;} + public string GithubEmail {get; set;} + public string GithubToken {get; set;} + public string GithubUpstreamOwner {get; set;} = "aspnet"; + public string GithubProject {get; set;} = "Universe"; + public string GithubUpstreamBranch {get; set;} = "dev"; + public string[] GitHubPullRequestNotifications { get; set; } = new string[] { }; + + public string[] UpdatedVersionsList + { + get + { + return UpdatedVersions.Split(';',System.StringSplitOptions.RemoveEmptyEntries); + } + } + } +} diff --git a/scripts/update-dependencies/Program.cs b/scripts/update-dependencies/Program.cs new file mode 100644 index 0000000000..06ec564689 --- /dev/null +++ b/scripts/update-dependencies/Program.cs @@ -0,0 +1,84 @@ +// 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.Diagnostics; +using System.Linq; +using System.Net.Http; +using System.Threading.Tasks; +using System.Xml; +using Microsoft.DotNet.VersionTools.Automation; +using Microsoft.Extensions.Configuration; + +namespace Microsoft.Dotnet.Scripts +{ + public static class Program + { + private static readonly Config _config = new Config(); + + public static async Task Main(string[] args) + { + Trace.Listeners.Add(new TextWriterTraceListener(Console.Out)); + + ParseArgs(args); + + await CreatePullRequest(); + } + + private static void ParseArgs(string[] args) + { + var builder = new ConfigurationBuilder().AddCommandLine(args); + var configRoot = builder.Build(); + configRoot.Bind(_config); + } + + private static async Task CreatePullRequest() + { + var gitHubAuth = new GitHubAuth(_config.GithubToken, _config.GithubUsername, _config.GithubEmail); + var origin = new GitHubProject(_config.GithubProject, _config.GithubUsername); + var upstreamBranch = new GitHubBranch(_config.GithubUpstreamBranch, new GitHubProject(_config.GithubProject, _config.GithubUpstreamOwner)); + + var commitMessage = $"Updating external dependencies to '{ await GetOrchestratedBuildId() }'"; + var body = string.Empty; + if (_config.GitHubPullRequestNotifications.Any()) + { + body += PullRequestCreator.NotificationString(_config.GitHubPullRequestNotifications); + } + + body += $"New versions:{Environment.NewLine}"; + + foreach (var updatedVersion in _config.UpdatedVersionsList) + { + body += $" {updatedVersion}{Environment.NewLine}"; + } + + await new PullRequestCreator(gitHubAuth, origin, upstreamBranch) + .CreateOrUpdateAsync(commitMessage, commitMessage + $" ({upstreamBranch.Name})", body); + } + + private static async Task GetOrchestratedBuildId() + { + var xmlUrl = _config.BuildXml; + + using (var client = new HttpClient()) + { + var response = await client.GetAsync(xmlUrl); + using (var bodyStream = await response.Content.ReadAsStreamAsync()) + { + var xmlDoc = new XmlDocument(); + xmlDoc.Load(bodyStream); + var orcBuilds = xmlDoc.GetElementsByTagName("OrchestratedBuild"); + + if (orcBuilds.Count < 1) + { + throw new ArgumentException($"{xmlUrl} didn't have an 'OrchestratedBuild' element."); + } + + var orcBuild = orcBuilds[0]; + + return orcBuild.Attributes["BuildId"].Value; + } + } + } + } +} diff --git a/scripts/update-dependencies/update-dependencies.csproj b/scripts/update-dependencies/update-dependencies.csproj new file mode 100644 index 0000000000..2887812fbb --- /dev/null +++ b/scripts/update-dependencies/update-dependencies.csproj @@ -0,0 +1,21 @@ + + + + Exe + netcoreapp2.0 + 7.1 + + https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; + https://api.nuget.org/v3/index.json; + + + + + + + + + + + +