2016-07-15 08:31:50 -07:00
// 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 ;
2016-04-25 13:17:46 -07:00
using System.Collections.Generic ;
2016-02-12 10:11:30 -08:00
using System.IO ;
2016-04-25 13:17:46 -07:00
using System.Linq ;
2016-04-08 08:57:24 -07:00
using System.Text.RegularExpressions ;
2016-02-15 10:07:39 -08:00
using Microsoft.DotNet.Cli.Build.Framework ;
2016-06-24 13:06:13 -05:00
using Microsoft.Build.Utilities ;
2016-02-12 10:11:30 -08:00
namespace Microsoft.DotNet.Cli.Build
{
2016-06-24 13:06:13 -05:00
public class PublishTargets : Task
2016-02-12 10:11:30 -08:00
{
2016-03-23 16:37:59 -07:00
private static AzurePublisher AzurePublisherTool { get ; set ; }
private static DebRepoPublisher DebRepoPublisherTool { get ; set ; }
2016-03-07 12:20:50 -08:00
2016-03-07 14:52:41 -08:00
private static string Channel { get ; set ; }
2016-03-07 12:20:50 -08:00
2016-06-21 19:18:48 -05:00
private static string CommitHash { get ; set ; }
2016-03-23 16:37:59 -07:00
private static string CliNuGetVersion { get ; set ; }
2016-03-17 22:22:22 -07:00
2016-03-23 16:37:59 -07:00
private static string SharedFrameworkNugetVersion { get ; set ; }
2016-03-07 12:20:50 -08:00
2016-06-24 13:06:13 -05:00
public override bool Execute ( )
{
BuildContext context = new BuildSetup ( "MSBuild" ) . UseAllTargetsFromAssembly < PublishTargets > ( ) . CreateBuildContext ( ) ;
BuildTargetContext c = new BuildTargetContext ( context , null , null ) ;
return Publish ( c ) . Success ;
}
2016-03-07 12:20:50 -08:00
public static BuildTargetResult InitPublish ( BuildTargetContext c )
{
2016-03-23 16:37:59 -07:00
AzurePublisherTool = new AzurePublisher ( ) ;
DebRepoPublisherTool = new DebRepoPublisher ( Dirs . Packages ) ;
2016-03-07 12:20:50 -08:00
2016-03-23 17:13:58 -07:00
CliNuGetVersion = c . BuildContext . Get < BuildVersion > ( "BuildVersion" ) . NuGetVersion ;
2016-05-27 13:24:39 -07:00
SharedFrameworkNugetVersion = CliDependencyVersions . SharedFrameworkVersion ;
2016-03-07 14:52:41 -08:00
Channel = c . BuildContext . Get < string > ( "Channel" ) ;
2016-06-21 19:18:48 -05:00
CommitHash = c . BuildContext . Get < string > ( "CommitHash" ) ;
2016-03-23 16:37:59 -07:00
2016-03-07 12:20:50 -08:00
return c . Success ( ) ;
}
2016-06-24 13:06:13 -05:00
[Target]
2016-02-12 10:11:30 -08:00
public static BuildTargetResult Publish ( BuildTargetContext c )
{
2016-06-24 13:06:13 -05:00
if ( EnvVars . GetBool ( "PUBLISH_TO_AZURE_BLOB" ) ) // This is set by CI systems
{
PrepareTargets . Init ( c ) ;
InitPublish ( c ) ;
PublishArtifacts ( c ) ;
FinalizeBuild ( c ) ;
}
2016-03-07 12:20:50 -08:00
return c . Success ( ) ;
}
2016-02-16 11:39:17 -08:00
2016-04-25 13:17:46 -07:00
public static BuildTargetResult FinalizeBuild ( BuildTargetContext c )
{
if ( CheckIfAllBuildsHavePublished ( ) )
{
2016-06-22 21:47:42 -05:00
string targetContainer = $"{AzurePublisher.Product.Sdk}/{Channel}" ;
string targetVersionFile = $"{targetContainer}/{CommitHash}" ;
2016-06-21 16:06:32 -05:00
string semaphoreBlob = $"{targetContainer}/publishSemaphore" ;
2016-04-29 14:05:41 -07:00
AzurePublisherTool . CreateBlobIfNotExists ( semaphoreBlob ) ;
string leaseId = AzurePublisherTool . AcquireLeaseOnBlob ( semaphoreBlob ) ;
2016-04-25 13:17:46 -07:00
// Prevent race conditions by dropping a version hint of what version this is. If we see this file
// and it is the same as our version then we know that a race happened where two+ builds finished
// at the same time and someone already took care of publishing and we have no work to do.
if ( AzurePublisherTool . IsLatestSpecifiedVersion ( targetVersionFile ) )
{
2016-05-02 01:03:31 -07:00
AzurePublisherTool . ReleaseLeaseOnBlob ( semaphoreBlob , leaseId ) ;
2016-04-25 13:17:46 -07:00
return c . Success ( ) ;
}
else
{
2016-06-21 19:18:48 -05:00
Regex versionFileRegex = new Regex ( @"(?<CommitHash>[\w\d]{40})" ) ;
2016-05-26 10:20:14 -07:00
// Delete old version files
2016-06-21 16:06:32 -05:00
AzurePublisherTool . ListBlobs ( targetContainer )
2016-05-26 10:20:14 -07:00
. Where ( s = > versionFileRegex . IsMatch ( s ) )
2016-05-02 01:03:31 -07:00
. ToList ( )
. ForEach ( f = > AzurePublisherTool . TryDeleteBlob ( f ) ) ;
2016-04-25 13:17:46 -07:00
// Drop the version file signaling such for any race-condition builds (see above comment).
AzurePublisherTool . DropLatestSpecifiedVersion ( targetVersionFile ) ;
}
try
{
2016-06-21 16:06:32 -05:00
CopyBlobsToLatest ( targetContainer ) ;
2016-05-26 12:48:16 -07:00
2016-04-25 13:17:46 -07:00
string cliVersion = Utils . GetCliVersionFileContent ( c ) ;
2016-06-21 16:06:32 -05:00
AzurePublisherTool . PublishStringToBlob ( $"{targetContainer}/latest.version" , cliVersion ) ;
2016-06-08 17:59:58 -05:00
UpdateVersionsRepo ( c ) ;
2016-04-25 13:17:46 -07:00
}
finally
{
2016-05-02 09:54:10 -07:00
AzurePublisherTool . ReleaseLeaseOnBlob ( semaphoreBlob , leaseId ) ;
2016-04-25 13:17:46 -07:00
}
}
return c . Success ( ) ;
}
2016-06-21 16:06:32 -05:00
private static void CopyBlobsToLatest ( string destinationFolder )
2016-05-02 10:32:28 -07:00
{
2016-06-21 16:06:32 -05:00
foreach ( string blob in AzurePublisherTool . ListBlobs ( AzurePublisher . Product . Sdk , CliNuGetVersion ) )
2016-05-02 10:32:28 -07:00
{
string targetName = Path . GetFileName ( blob )
2016-05-16 15:30:53 -07:00
. Replace ( CliNuGetVersion , "latest" ) ;
2016-06-22 21:47:42 -05:00
string target = $"{destinationFolder}/{targetName}" ;
2016-06-21 16:06:32 -05:00
AzurePublisherTool . CopyBlob ( blob , target ) ;
2016-05-02 10:32:28 -07:00
}
}
2016-04-25 13:17:46 -07:00
private static bool CheckIfAllBuildsHavePublished ( )
{
2016-05-04 12:25:26 -07:00
Dictionary < string , bool > badges = new Dictionary < string , bool > ( )
2016-06-21 16:06:32 -05:00
{
{ "Windows_x86" , false } ,
{ "Windows_x64" , false } ,
{ "Ubuntu_x64" , false } ,
{ "Ubuntu_16_04_x64" , false } ,
{ "RHEL_x64" , false } ,
{ "OSX_x64" , false } ,
{ "Debian_x64" , false } ,
{ "CentOS_x64" , false } ,
{ "Fedora_23_x64" , false } ,
{ "openSUSE_13_2_x64" , false }
} ;
2016-04-25 13:17:46 -07:00
2016-05-31 13:54:35 -07:00
var versionBadgeName = $"{Monikers.GetBadgeMoniker()}" ;
2016-06-21 16:06:32 -05:00
if ( ! badges . ContainsKey ( versionBadgeName ) )
2016-04-25 13:17:46 -07:00
{
2016-06-21 16:06:32 -05:00
throw new ArgumentException ( $"A new OS build '{versionBadgeName}' was added without adding the moniker to the {nameof(badges)} lookup" ) ;
2016-04-25 13:17:46 -07:00
}
2016-06-21 16:06:32 -05:00
IEnumerable < string > blobs = AzurePublisherTool . ListBlobs ( AzurePublisher . Product . Sdk , CliNuGetVersion ) ;
2016-05-02 10:32:28 -07:00
foreach ( string file in blobs )
2016-04-25 13:17:46 -07:00
{
string name = Path . GetFileName ( file ) ;
foreach ( string img in badges . Keys )
{
if ( ( name . StartsWith ( $"{img}" ) ) & & ( name . EndsWith ( ".svg" ) ) )
{
2016-06-21 16:06:32 -05:00
badges [ img ] = true ;
2016-04-25 13:17:46 -07:00
break ;
}
}
}
2016-06-21 16:06:32 -05:00
return badges . Values . All ( v = > v ) ;
2016-04-25 13:17:46 -07:00
}
2016-06-24 13:06:13 -05:00
public static BuildTargetResult PublishArtifacts ( BuildTargetContext c )
{
PublishInstallerFilesToAzure ( c ) ;
PublishArchivesToAzure ( c ) ;
PublishDebFilesToDebianRepo ( c ) ;
PublishCliVersionBadge ( c ) ;
return c . Success ( ) ;
}
public static BuildTargetResult PublishInstallerFilesToAzure ( BuildTargetContext c )
{
PublishSdkInstallerFileToAzure ( c ) ;
PublishCombinedFrameworkSDKHostInstallerFileToAzure ( c ) ;
return c . Success ( ) ;
}
public static BuildTargetResult PublishArchivesToAzure ( BuildTargetContext c )
{
PublishCombinedHostFrameworkSdkArchiveToAzure ( c ) ;
PublishCombinedFrameworkSDKArchiveToAzure ( c ) ;
PublishSDKSymbolsArchiveToAzure ( c ) ;
return c . Success ( ) ;
}
2016-03-23 16:37:59 -07:00
public static BuildTargetResult PublishDebFilesToDebianRepo ( BuildTargetContext c )
2016-03-07 12:20:50 -08:00
{
2016-06-24 13:06:13 -05:00
if ( CurrentPlatform . IsPlatform ( BuildPlatform . Ubuntu ) )
{
PublishSdkDebToDebianRepo ( c ) ;
}
2016-03-07 12:20:50 -08:00
return c . Success ( ) ;
}
2016-02-12 10:11:30 -08:00
2016-03-23 16:37:59 -07:00
public static BuildTargetResult PublishCliVersionBadge ( BuildTargetContext c )
2016-03-07 12:20:50 -08:00
{
2016-03-23 17:13:58 -07:00
var versionBadge = c . BuildContext . Get < string > ( "VersionBadge" ) ;
2016-06-21 16:06:32 -05:00
UploadFile ( versionBadge ) ;
2016-03-23 16:37:59 -07:00
return c . Success ( ) ;
}
2016-06-02 19:07:16 -07:00
2016-03-23 16:37:59 -07:00
public static BuildTargetResult PublishSdkInstallerFileToAzure ( BuildTargetContext c )
{
2016-06-24 13:06:13 -05:00
if ( CurrentPlatform . IsPlatform ( BuildPlatform . Ubuntu ) )
{
var installerFile = c . BuildContext . Get < string > ( "SdkInstallerFile" ) ;
UploadFile ( installerFile ) ;
}
2016-03-23 16:37:59 -07:00
return c . Success ( ) ;
}
public static BuildTargetResult PublishCombinedFrameworkSDKHostInstallerFileToAzure ( BuildTargetContext c )
2016-03-07 12:20:50 -08:00
{
2016-06-24 13:06:13 -05:00
if ( CurrentPlatform . IsAnyPlatform ( BuildPlatform . Windows , BuildPlatform . OSX ) )
{
var installerFile = c . BuildContext . Get < string > ( "CombinedFrameworkSDKHostInstallerFile" ) ;
UploadFile ( installerFile ) ;
}
2016-03-23 16:37:59 -07:00
return c . Success ( ) ;
}
2016-04-24 13:01:52 -07:00
public static BuildTargetResult PublishCombinedFrameworkSDKArchiveToAzure ( BuildTargetContext c )
{
2016-06-24 13:06:13 -05:00
if ( CurrentPlatform . IsPlatform ( BuildPlatform . Windows ) )
{
var archiveFile = c . BuildContext . Get < string > ( "CombinedFrameworkSDKCompressedFile" ) ;
UploadFile ( archiveFile ) ;
}
2016-04-24 13:01:52 -07:00
return c . Success ( ) ;
}
2016-03-23 16:37:59 -07:00
public static BuildTargetResult PublishCombinedHostFrameworkSdkArchiveToAzure ( BuildTargetContext c )
{
var archiveFile = c . BuildContext . Get < string > ( "CombinedFrameworkSDKHostCompressedFile" ) ;
2016-06-21 16:06:32 -05:00
UploadFile ( archiveFile ) ;
2016-03-23 16:37:59 -07:00
2016-03-07 12:20:50 -08:00
return c . Success ( ) ;
}
2016-04-04 20:13:13 -07:00
public static BuildTargetResult PublishSDKSymbolsArchiveToAzure ( BuildTargetContext c )
{
var archiveFile = c . BuildContext . Get < string > ( "SdkSymbolsCompressedFile" ) ;
2016-06-21 16:06:32 -05:00
UploadFile ( archiveFile ) ;
2016-04-04 20:13:13 -07:00
return c . Success ( ) ;
}
2016-03-22 14:14:54 -07:00
public static BuildTargetResult PublishSdkDebToDebianRepo ( BuildTargetContext c )
{
2016-06-24 13:06:13 -05:00
if ( CurrentPlatform . IsPlatform ( BuildPlatform . Ubuntu ) )
{
var version = CliNuGetVersion ;
2016-03-23 16:37:59 -07:00
2016-06-24 13:06:13 -05:00
var packageName = CliMonikers . GetSdkDebianPackageName ( c ) ;
var installerFile = c . BuildContext . Get < string > ( "SdkInstallerFile" ) ;
var uploadUrl = AzurePublisher . CalculateFullUrlForFile ( installerFile , AzurePublisher . Product . Sdk , version ) ;
2016-03-08 23:33:18 +00:00
2016-06-24 13:06:13 -05:00
DebRepoPublisherTool . PublishDebFileToDebianRepo (
packageName ,
version ,
uploadUrl ) ;
}
2016-03-08 23:33:18 +00:00
return c . Success ( ) ;
}
2016-06-08 17:59:58 -05:00
private static void UpdateVersionsRepo ( BuildTargetContext c )
2016-05-17 18:16:48 -05:00
{
2016-05-18 14:14:50 -05:00
string githubAuthToken = EnvVars . EnsureVariable ( "GITHUB_PASSWORD" ) ;
2016-06-08 17:59:58 -05:00
string nupkgFilePath = Dirs . Packages ;
string branchName = c . BuildContext . Get < string > ( "BranchName" ) ;
string versionsRepoPath = $"build-info/dotnet/cli/{branchName}/Latest" ;
2016-05-17 18:16:48 -05:00
2016-05-18 14:14:50 -05:00
VersionRepoUpdater repoUpdater = new VersionRepoUpdater ( githubAuthToken ) ;
2016-05-17 18:16:48 -05:00
repoUpdater . UpdatePublishedVersions ( nupkgFilePath , versionsRepoPath ) . Wait ( ) ;
}
2016-06-21 16:06:32 -05:00
private static string UploadFile ( string file )
{
return AzurePublisherTool . UploadFile ( file , AzurePublisher . Product . Sdk , CliNuGetVersion ) ;
}
2016-02-12 10:11:30 -08:00
}
}
2016-05-11 17:20:40 -07:00