2016-05-17 18:16:48 -05:00
using System ;
using System.Collections.Generic ;
using System.IO ;
using System.Linq ;
using System.Net.Http ;
using System.Text ;
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
using Newtonsoft.Json.Linq ;
namespace Microsoft.DotNet.Cli.Build
{
public class VersionRepoUpdater
{
2016-06-10 03:16:25 -05:00
private static Regex s_nugetFileRegex = new Regex ( "^(?<id>.*?)\\.(?<version>([0-9]+\\.)?[0-9]+\\.[0-9]+(-(?<prerelease>[A-z0-9-]+))?)(?<symbols>\\.symbols)?\\.nupkg$" ) ;
2016-05-17 18:16:48 -05:00
2016-05-18 14:14:50 -05:00
private string _gitHubAuthToken ;
2016-05-17 18:16:48 -05:00
private string _gitHubUser ;
private string _gitHubEmail ;
private string _versionsRepoOwner ;
private string _versionsRepo ;
public VersionRepoUpdater (
2016-05-18 14:14:50 -05:00
string gitHubAuthToken ,
2016-05-18 11:15:28 -05:00
string gitHubUser = null ,
string gitHubEmail = null ,
string versionRepoOwner = null ,
string versionsRepo = null )
2016-05-17 18:16:48 -05:00
{
2016-05-18 14:14:50 -05:00
if ( string . IsNullOrEmpty ( gitHubAuthToken ) )
{
throw new ArgumentNullException ( nameof ( gitHubAuthToken ) ) ;
}
_gitHubAuthToken = gitHubAuthToken ;
2016-05-17 18:16:48 -05:00
_gitHubUser = gitHubUser ? ? "dotnet-bot" ;
_gitHubEmail = gitHubEmail ? ? "dotnet-bot@microsoft.com" ;
_versionsRepoOwner = versionRepoOwner ? ? "dotnet" ;
_versionsRepo = versionsRepo ? ? "versions" ;
}
public async Task UpdatePublishedVersions ( string nupkgFilePath , string versionsRepoPath )
{
2016-05-18 11:15:28 -05:00
List < NuGetPackageInfo > publishedPackages = GetPackageInfo ( nupkgFilePath ) ;
2016-05-17 18:16:48 -05:00
string packageInfoFileContent = string . Join (
Environment . NewLine ,
publishedPackages
2016-05-18 11:15:28 -05:00
. OrderBy ( t = > t . Id )
. Select ( t = > $"{t.Id} {t.Version}" ) ) ;
2016-05-17 18:16:48 -05:00
2016-05-18 11:15:28 -05:00
string prereleaseVersion = publishedPackages
. Where ( t = > ! string . IsNullOrEmpty ( t . Prerelease ) )
. Select ( t = > t . Prerelease )
. FirstOrDefault ( ) ;
2016-05-17 18:16:48 -05:00
string packageInfoFilePath = $"{versionsRepoPath}_Packages.txt" ;
string message = $"Adding package info to {packageInfoFilePath} for {prereleaseVersion}" ;
await UpdateGitHubFile ( packageInfoFilePath , packageInfoFileContent , message ) ;
}
2016-05-18 11:15:28 -05:00
private static List < NuGetPackageInfo > GetPackageInfo ( string nupkgFilePath )
2016-05-17 18:16:48 -05:00
{
2016-05-18 11:15:28 -05:00
List < NuGetPackageInfo > packages = new List < NuGetPackageInfo > ( ) ;
2016-05-17 18:16:48 -05:00
foreach ( string filePath in Directory . GetFiles ( nupkgFilePath , "*.nupkg" ) )
{
Match match = s_nugetFileRegex . Match ( Path . GetFileName ( filePath ) ) ;
2016-06-10 03:16:25 -05:00
// only look for non-symbols packages
if ( string . IsNullOrEmpty ( match . Groups [ "symbols" ] . Value ) )
2016-05-18 11:15:28 -05:00
{
2016-06-10 03:16:25 -05:00
packages . Add ( new NuGetPackageInfo ( )
{
Id = match . Groups [ "id" ] . Value ,
Version = match . Groups [ "version" ] . Value ,
Prerelease = match . Groups [ "prerelease" ] . Value ,
} ) ;
}
2016-05-17 18:16:48 -05:00
}
return packages ;
}
private async Task UpdateGitHubFile ( string path , string newFileContent , string commitMessage )
{
2016-05-18 11:15:28 -05:00
using ( HttpClient client = new HttpClient ( ) )
{
client . DefaultRequestHeaders . Add ( "Accept" , "application/vnd.github.v3+json" ) ;
client . DefaultRequestHeaders . Add ( "Authorization" , $"token {_gitHubAuthToken}" ) ;
client . DefaultRequestHeaders . Add ( "User-Agent" , _gitHubUser ) ;
2016-05-17 18:16:48 -05:00
2016-05-18 11:15:28 -05:00
string fileUrl = $"https://api.github.com/repos/{_versionsRepoOwner}/{_versionsRepo}/contents/{path}" ;
2016-05-17 18:16:48 -05:00
2016-05-18 11:15:28 -05:00
Console . WriteLine ( $"Getting the 'sha' of the current contents of file '{_versionsRepoOwner}/{_versionsRepo}/{path}'" ) ;
2016-05-17 18:16:48 -05:00
2016-05-18 11:15:28 -05:00
string currentFile = await client . GetStringAsync ( fileUrl ) ;
string currentSha = JObject . Parse ( currentFile ) [ "sha" ] . ToString ( ) ;
2016-05-17 18:16:48 -05:00
2016-05-18 11:15:28 -05:00
Console . WriteLine ( $"Got 'sha' value of '{currentSha}'" ) ;
2016-05-17 18:16:48 -05:00
2016-05-18 11:15:28 -05:00
Console . WriteLine ( $"Request to update file '{_versionsRepoOwner}/{_versionsRepo}/{path}' contents to:" ) ;
Console . WriteLine ( newFileContent ) ;
string updateFileBody = $ @ "{{
2016-05-17 18:16:48 -05:00
"" message "" : "" { commitMessage } "" ,
"" committer "" : { {
"" name "" : "" { _gitHubUser } "" ,
"" email "" : "" { _gitHubEmail } ""
} } ,
"" content "" : "" { ToBase64 ( newFileContent ) } "" ,
"" sha "" : "" { currentSha } ""
} } ";
2016-05-18 11:15:28 -05:00
Console . WriteLine ( "Sending request..." ) ;
StringContent content = new StringContent ( updateFileBody ) ;
2016-05-17 18:16:48 -05:00
2016-05-18 11:15:28 -05:00
using ( HttpResponseMessage response = await client . PutAsync ( fileUrl , content ) )
{
response . EnsureSuccessStatusCode ( ) ;
Console . WriteLine ( "Updated the file successfully..." ) ;
}
2016-05-17 18:16:48 -05:00
}
}
private static string ToBase64 ( string value )
{
return Convert . ToBase64String ( Encoding . UTF8 . GetBytes ( value ) ) ;
}
2016-05-18 11:15:28 -05:00
private class NuGetPackageInfo
{
public string Id { get ; set ; }
public string Version { get ; set ; }
public string Prerelease { get ; set ; }
}
2016-05-17 18:16:48 -05:00
}
}