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-02-02 10:04:50 -08:00
using System.Collections.Generic ;
using System.Globalization ;
using System.IO ;
2016-06-27 21:09:30 -05:00
using System.IO.Compression ;
using Microsoft.Build.Utilities ;
2016-04-06 19:45:38 -05:00
using Microsoft.DotNet.Cli.Build.Framework ;
2016-04-28 16:30:32 -07:00
using Microsoft.DotNet.InternalAbstractions ;
2016-04-06 19:45:38 -05:00
using static Microsoft . DotNet . Cli . Build . Framework . BuildHelpers ;
2016-02-02 10:04:50 -08:00
using static Microsoft . DotNet . Cli . Build . FS ;
using static Microsoft . DotNet . Cli . Build . Utils ;
namespace Microsoft.DotNet.Cli.Build
{
2016-07-15 08:31:50 -07:00
public class PrepareTargets
2016-02-02 10:04:50 -08:00
{
2016-06-24 13:06:13 -05:00
2016-02-02 10:04:50 -08:00
// All major targets will depend on this in order to ensure variables are set up right if they are run independently
public static BuildTargetResult Init ( BuildTargetContext c )
{
2016-06-24 13:06:13 -05:00
GenerateVersions ( c ) ;
2016-06-27 21:09:30 -05:00
CheckPrereqs . Run ( s = > c . Info ( s ) ) ;
2016-06-24 13:06:13 -05:00
ExpectedBuildArtifacts ( c ) ;
SetTelemetryProfile ( c ) ;
2016-02-02 10:04:50 -08:00
var configEnv = Environment . GetEnvironmentVariable ( "CONFIGURATION" ) ;
2016-02-15 09:42:17 -08:00
if ( string . IsNullOrEmpty ( configEnv ) )
2016-02-02 10:04:50 -08:00
{
configEnv = "Debug" ;
}
2016-02-15 09:42:17 -08:00
2016-02-02 10:04:50 -08:00
c . BuildContext [ "Configuration" ] = configEnv ;
2016-03-07 14:52:41 -08:00
c . BuildContext [ "Channel" ] = Environment . GetEnvironmentVariable ( "CHANNEL" ) ;
2016-02-02 10:04:50 -08:00
c . Info ( $"Building {c.BuildContext[" Configuration "]} to: {Dirs.Output}" ) ;
c . Info ( "Build Environment:" ) ;
2016-04-28 16:30:32 -07:00
c . Info ( $" Operating System: {RuntimeEnvironment.OperatingSystem} {RuntimeEnvironment.OperatingSystemVersion}" ) ;
c . Info ( $" Platform: {RuntimeEnvironment.OperatingSystemPlatform}" ) ;
2016-02-02 10:04:50 -08:00
return c . Success ( ) ;
}
public static BuildTargetResult GenerateVersions ( BuildTargetContext c )
{
2016-05-19 19:07:33 -05:00
var commitCount = GitUtils . GetCommitCount ( ) ;
var commitHash = GitUtils . GetCommitHash ( ) ;
2016-02-02 10:04:50 -08:00
var branchInfo = ReadBranchInfo ( c , Path . Combine ( c . BuildContext . BuildDirectory , "branchinfo.txt" ) ) ;
var buildVersion = new BuildVersion ( )
{
Major = int . Parse ( branchInfo [ "MAJOR_VERSION" ] ) ,
Minor = int . Parse ( branchInfo [ "MINOR_VERSION" ] ) ,
Patch = int . Parse ( branchInfo [ "PATCH_VERSION" ] ) ,
ReleaseSuffix = branchInfo [ "RELEASE_SUFFIX" ] ,
CommitCount = commitCount
} ;
c . BuildContext [ "BuildVersion" ] = buildVersion ;
2016-06-08 17:59:58 -05:00
c . BuildContext [ "BranchName" ] = branchInfo [ "BRANCH_NAME" ] ;
2016-02-02 10:04:50 -08:00
c . BuildContext [ "CommitHash" ] = commitHash ;
c . Info ( $"Building Version: {buildVersion.SimpleVersion} (NuGet Packages: {buildVersion.NuGetVersion})" ) ;
c . Info ( $"From Commit: {commitHash}" ) ;
return c . Success ( ) ;
}
2016-05-27 12:37:17 -07:00
public static BuildTargetResult ZipTemplates ( BuildTargetContext c )
{
var templateDirectories = Directory . GetDirectories (
Path . Combine ( Dirs . RepoRoot , "src" , "dotnet" , "commands" , "dotnet-new" ) ) ;
foreach ( var directory in templateDirectories )
{
var zipFile = Path . Combine ( Path . GetDirectoryName ( directory ) , Path . GetFileName ( directory ) + ".zip" ) ;
if ( File . Exists ( zipFile ) )
{
File . Delete ( zipFile ) ;
}
ZipFile . CreateFromDirectory ( directory , zipFile ) ;
}
return c . Success ( ) ;
}
2016-06-27 21:09:30 -05:00
2016-02-02 10:04:50 -08:00
2016-03-07 12:20:50 -08:00
public static BuildTargetResult ExpectedBuildArtifacts ( BuildTargetContext c )
{
var config = Environment . GetEnvironmentVariable ( "CONFIGURATION" ) ;
2016-05-29 22:38:14 -07:00
var versionBadgeName = $"{Monikers.GetBadgeMoniker()}_{config}_version_badge.svg" ;
2016-03-07 12:20:50 -08:00
c . BuildContext [ "VersionBadge" ] = Path . Combine ( Dirs . Output , versionBadgeName ) ;
2016-03-23 17:13:58 -07:00
var cliVersion = c . BuildContext . Get < BuildVersion > ( "BuildVersion" ) . NuGetVersion ;
2016-05-27 13:24:39 -07:00
var sharedFrameworkVersion = CliDependencyVersions . SharedFrameworkVersion ;
var hostVersion = CliDependencyVersions . SharedHostVersion ;
2016-06-12 15:33:02 -07:00
var hostFxrVersion = CliDependencyVersions . HostFxrVersion ;
2016-03-23 17:13:58 -07:00
2016-05-16 15:30:53 -07:00
// Generated Installers + Archives
2016-03-23 17:13:58 -07:00
AddInstallerArtifactToContext ( c , "dotnet-sdk" , "Sdk" , cliVersion ) ;
AddInstallerArtifactToContext ( c , "dotnet-dev" , "CombinedFrameworkSDKHost" , cliVersion ) ;
2016-04-24 13:01:52 -07:00
AddInstallerArtifactToContext ( c , "dotnet-sharedframework-sdk" , "CombinedFrameworkSDK" , cliVersion ) ;
2016-04-04 20:13:13 -07:00
AddInstallerArtifactToContext ( c , "dotnet-sdk-debug" , "SdkSymbols" , cliVersion ) ;
2016-03-07 12:20:50 -08:00
2016-05-16 15:30:53 -07:00
//Downloaded Installers + Archives
AddInstallerArtifactToContext ( c , "dotnet-host" , "SharedHost" , hostVersion ) ;
2016-06-12 15:33:02 -07:00
AddInstallerArtifactToContext ( c , "dotnet-hostfxr" , "HostFxr" , hostFxrVersion ) ;
2016-05-16 15:30:53 -07:00
AddInstallerArtifactToContext ( c , "dotnet-sharedframework" , "SharedFramework" , sharedFrameworkVersion ) ;
AddInstallerArtifactToContext ( c , "dotnet" , "CombinedFrameworkHost" , sharedFrameworkVersion ) ;
return c . Success ( ) ;
}
2016-06-24 13:06:13 -05:00
public static BuildTargetResult DownloadHostAndSharedFxArtifacts ( BuildTargetContext c )
{
ExpectedBuildArtifacts ( c ) ;
DownloadHostAndSharedFxArchives ( c ) ;
DownloadHostAndSharedFxInstallers ( c ) ;
return c . Success ( ) ;
}
2016-05-16 15:30:53 -07:00
public static BuildTargetResult DownloadHostAndSharedFxArchives ( BuildTargetContext c )
{
2016-05-27 13:24:39 -07:00
var sharedFrameworkVersion = CliDependencyVersions . SharedFrameworkVersion ;
var sharedFrameworkChannel = CliDependencyVersions . SharedFrameworkChannel ;
2016-05-16 15:30:53 -07:00
2016-05-26 12:58:19 -07:00
var combinedSharedHostAndFrameworkArchiveDownloadFile =
2016-05-27 13:24:39 -07:00
Path . Combine ( CliDirs . CoreSetupDownload , "combinedSharedHostAndFrameworkArchive" ) ;
2016-05-16 15:30:53 -07:00
2016-05-26 12:58:19 -07:00
Mkdirp ( Path . GetDirectoryName ( combinedSharedHostAndFrameworkArchiveDownloadFile ) ) ;
2016-05-16 15:30:53 -07:00
2016-06-21 16:06:32 -05:00
if ( ! File . Exists ( combinedSharedHostAndFrameworkArchiveDownloadFile ) )
2016-05-16 15:30:53 -07:00
{
2016-05-26 12:58:19 -07:00
// Needed for computing the blob path
2016-06-21 16:06:32 -05:00
var combinedSharedHostAndFrameworkArchiveBuildContextFile =
2016-05-26 12:58:19 -07:00
c . BuildContext . Get < string > ( "CombinedFrameworkHostCompressedFile" ) ;
AzurePublisher . DownloadFile (
2016-06-21 16:06:32 -05:00
CalculateArchiveBlob (
2016-05-26 12:58:19 -07:00
combinedSharedHostAndFrameworkArchiveBuildContextFile ,
sharedFrameworkChannel ,
sharedFrameworkVersion ) ,
combinedSharedHostAndFrameworkArchiveDownloadFile ) . Wait ( ) ;
// Unpack the combined archive to shared framework publish directory
Rmdir ( Dirs . SharedFrameworkPublish ) ;
Mkdirp ( Dirs . SharedFrameworkPublish ) ;
if ( CurrentPlatform . IsWindows )
{
ZipFile . ExtractToDirectory ( combinedSharedHostAndFrameworkArchiveDownloadFile , Dirs . SharedFrameworkPublish ) ;
}
else
{
Exec ( "tar" , "xf" , combinedSharedHostAndFrameworkArchiveDownloadFile , "-C" , Dirs . SharedFrameworkPublish ) ;
}
2016-05-16 15:30:53 -07:00
}
return c . Success ( ) ;
}
public static BuildTargetResult DownloadHostAndSharedFxInstallers ( BuildTargetContext c )
{
2016-06-24 13:06:13 -05:00
if ( CurrentPlatform . IsAnyPlatform ( BuildPlatform . Windows , BuildPlatform . OSX , BuildPlatform . Ubuntu ) )
{
var sharedFrameworkVersion = CliDependencyVersions . SharedFrameworkVersion ;
var hostVersion = CliDependencyVersions . SharedHostVersion ;
var hostFxrVersion = CliDependencyVersions . HostFxrVersion ;
2016-05-16 15:30:53 -07:00
2016-06-24 13:06:13 -05:00
var sharedFrameworkChannel = CliDependencyVersions . SharedFrameworkChannel ;
var sharedHostChannel = CliDependencyVersions . SharedHostChannel ;
var hostFxrChannel = CliDependencyVersions . HostFxrChannel ;
2016-05-16 15:30:53 -07:00
2016-06-24 13:06:13 -05:00
var sharedFrameworkInstallerDownloadFile = Path . Combine ( CliDirs . CoreSetupDownload , "sharedFrameworkInstaller" ) ;
var sharedHostInstallerDownloadFile = Path . Combine ( CliDirs . CoreSetupDownload , "sharedHostInstaller" ) ;
var hostFxrInstallerDownloadFile = Path . Combine ( CliDirs . CoreSetupDownload , "hostFxrInstaller" ) ;
2016-05-26 12:58:19 -07:00
2016-06-24 13:06:13 -05:00
Mkdirp ( Path . GetDirectoryName ( sharedFrameworkInstallerDownloadFile ) ) ;
Mkdirp ( Path . GetDirectoryName ( sharedHostInstallerDownloadFile ) ) ;
Mkdirp ( Path . GetDirectoryName ( hostFxrInstallerDownloadFile ) ) ;
2016-06-01 17:12:31 -07:00
2016-06-24 13:06:13 -05:00
if ( ! File . Exists ( sharedFrameworkInstallerDownloadFile ) )
{
var sharedFrameworkInstallerDestinationFile = c . BuildContext . Get < string > ( "SharedFrameworkInstallerFile" ) ;
Mkdirp ( Path . GetDirectoryName ( sharedFrameworkInstallerDestinationFile ) ) ;
2016-06-21 16:06:32 -05:00
2016-06-24 13:06:13 -05:00
AzurePublisher . DownloadFile (
CalculateInstallerBlob (
sharedFrameworkInstallerDestinationFile ,
sharedFrameworkChannel ,
sharedFrameworkVersion ) ,
sharedFrameworkInstallerDownloadFile ) . Wait ( ) ;
2016-05-26 12:58:19 -07:00
2016-06-24 13:06:13 -05:00
File . Copy ( sharedFrameworkInstallerDownloadFile , sharedFrameworkInstallerDestinationFile , true ) ;
}
2016-06-21 16:06:32 -05:00
2016-06-24 13:06:13 -05:00
if ( ! File . Exists ( sharedHostInstallerDownloadFile ) )
{
var sharedHostInstallerDestinationFile = c . BuildContext . Get < string > ( "SharedHostInstallerFile" ) ;
Mkdirp ( Path . GetDirectoryName ( sharedHostInstallerDestinationFile ) ) ;
2016-05-26 12:58:19 -07:00
2016-06-24 13:06:13 -05:00
AzurePublisher . DownloadFile (
CalculateInstallerBlob (
sharedHostInstallerDestinationFile ,
sharedHostChannel ,
hostVersion ) ,
sharedHostInstallerDownloadFile ) . Wait ( ) ;
2016-05-26 12:58:19 -07:00
2016-06-24 13:06:13 -05:00
File . Copy ( sharedHostInstallerDownloadFile , sharedHostInstallerDestinationFile , true ) ;
}
2016-05-16 15:30:53 -07:00
2016-06-24 13:06:13 -05:00
if ( ! File . Exists ( hostFxrInstallerDownloadFile ) )
{
var hostFxrInstallerDestinationFile = c . BuildContext . Get < string > ( "HostFxrInstallerFile" ) ;
Mkdirp ( Path . GetDirectoryName ( hostFxrInstallerDestinationFile ) ) ;
2016-06-12 15:33:02 -07:00
2016-06-24 13:06:13 -05:00
AzurePublisher . DownloadFile (
CalculateInstallerBlob (
hostFxrInstallerDestinationFile ,
hostFxrChannel ,
hostFxrVersion ) ,
hostFxrInstallerDownloadFile ) . Wait ( ) ;
2016-06-12 15:33:02 -07:00
2016-06-24 13:06:13 -05:00
File . Copy ( hostFxrInstallerDownloadFile , hostFxrInstallerDestinationFile , true ) ;
}
2016-06-12 15:33:02 -07:00
}
2016-03-07 12:20:50 -08:00
return c . Success ( ) ;
}
2016-02-02 10:04:50 -08:00
public static BuildTargetResult CheckPackageCache ( BuildTargetContext c )
{
var ciBuild = string . Equals ( Environment . GetEnvironmentVariable ( "CI_BUILD" ) , "1" , StringComparison . Ordinal ) ;
2016-06-21 16:06:32 -05:00
2016-06-09 15:05:27 -07:00
// Always set the package cache location local to the build
Environment . SetEnvironmentVariable ( "NUGET_PACKAGES" , Dirs . NuGetPackages ) ;
2016-02-02 10:04:50 -08:00
CleanNuGetTempCache ( ) ;
// Determine cache expiration time
var cacheExpiration = 7 * 24 ; // cache expiration in hours
var cacheExpirationStr = Environment . GetEnvironmentVariable ( "NUGET_PACKAGES_CACHE_TIME_LIMIT" ) ;
if ( ! string . IsNullOrEmpty ( cacheExpirationStr ) )
{
cacheExpiration = int . Parse ( cacheExpirationStr ) ;
}
if ( ciBuild )
{
var cacheTimeFile = Path . Combine ( Dirs . NuGetPackages , "packageCacheTime.txt" ) ;
DateTime ? cacheTime = null ;
try
{
// Read the cache file
2016-02-15 09:42:17 -08:00
if ( File . Exists ( cacheTimeFile ) )
2016-02-02 10:04:50 -08:00
{
var content = File . ReadAllText ( cacheTimeFile ) ;
2016-02-15 09:42:17 -08:00
if ( ! string . IsNullOrEmpty ( content ) )
2016-02-02 10:04:50 -08:00
{
cacheTime = DateTime . ParseExact ( "O" , content , CultureInfo . InvariantCulture , DateTimeStyles . AssumeUniversal ) ;
}
}
}
2016-02-15 09:42:17 -08:00
catch ( Exception ex )
2016-02-02 10:04:50 -08:00
{
c . Warn ( $"Error reading NuGet cache time file, leaving the cache alone" ) ;
c . Warn ( $"Error Detail: {ex.ToString()}" ) ;
}
2016-02-15 09:42:17 -08:00
if ( cacheTime = = null | | ( cacheTime . Value . AddHours ( cacheExpiration ) < DateTime . UtcNow ) )
2016-02-02 10:04:50 -08:00
{
// Cache has expired or the status is unknown, clear it and write the file
c . Info ( "Clearing NuGet cache" ) ;
Rmdir ( Dirs . NuGetPackages ) ;
Mkdirp ( Dirs . NuGetPackages ) ;
File . WriteAllText ( cacheTimeFile , DateTime . UtcNow . ToString ( "O" ) ) ;
}
}
return c . Success ( ) ;
}
public static BuildTargetResult RestorePackages ( BuildTargetContext c )
{
2016-06-24 13:06:13 -05:00
CheckPackageCache ( c ) ;
2016-02-02 10:04:50 -08:00
var dotnet = DotNetCli . Stage0 ;
2016-05-16 15:30:53 -07:00
dotnet . Restore ( "--verbosity" , "verbose" , "--disable-parallel" )
2016-04-06 19:45:38 -05:00
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "src" ) )
. Execute ( )
. EnsureSuccessful ( ) ;
dotnet . Restore ( "--verbosity" , "verbose" , "--disable-parallel" , "--infer-runtimes" )
. WorkingDirectory ( Path . Combine ( c . BuildContext . BuildDirectory , "tools" ) )
. Execute ( )
. EnsureSuccessful ( ) ;
2016-02-02 10:04:50 -08:00
return c . Success ( ) ;
}
2016-05-25 09:21:08 -07:00
public static BuildTargetResult SetTelemetryProfile ( BuildTargetContext c )
{
var gitResult = Cmd ( "git" , "rev-parse" , "HEAD" )
. CaptureStdOut ( )
. Execute ( ) ;
gitResult . EnsureSuccessful ( ) ;
var commitHash = gitResult . StdOut . Trim ( ) ;
Environment . SetEnvironmentVariable ( "DOTNET_CLI_TELEMETRY_PROFILE" , $"https://github.com/dotnet/cli;{commitHash}" ) ;
return c . Success ( ) ;
}
2016-02-02 10:04:50 -08:00
private static IDictionary < string , string > ReadBranchInfo ( BuildTargetContext c , string path )
{
var lines = File . ReadAllLines ( path ) ;
var dict = new Dictionary < string , string > ( ) ;
c . Verbose ( "Branch Info:" ) ;
2016-02-15 09:42:17 -08:00
foreach ( var line in lines )
2016-02-02 10:04:50 -08:00
{
2016-02-15 09:42:17 -08:00
if ( ! line . Trim ( ) . StartsWith ( "#" ) & & ! string . IsNullOrWhiteSpace ( line ) )
2016-02-02 10:04:50 -08:00
{
var splat = line . Split ( new [ ] { '=' } , 2 ) ;
dict [ splat [ 0 ] ] = splat [ 1 ] ;
c . Verbose ( $" {splat[0]} = {splat[1]}" ) ;
}
}
return dict ;
}
2016-03-08 13:39:41 -08:00
2016-03-23 17:13:58 -07:00
private static void AddInstallerArtifactToContext (
2016-05-27 12:37:17 -07:00
BuildTargetContext c ,
string artifactPrefix ,
2016-03-23 17:13:58 -07:00
string contextPrefix ,
string version )
2016-03-08 13:39:41 -08:00
{
2016-03-23 17:13:58 -07:00
var productName = Monikers . GetProductMoniker ( c , artifactPrefix , version ) ;
2016-03-08 13:39:41 -08:00
var extension = CurrentPlatform . IsWindows ? ".zip" : ".tar.gz" ;
c . BuildContext [ contextPrefix + "CompressedFile" ] = Path . Combine ( Dirs . Packages , productName + extension ) ;
string installer = "" ;
switch ( CurrentPlatform . Current )
{
case BuildPlatform . Windows :
2016-05-16 15:30:53 -07:00
if ( contextPrefix . Contains ( "Combined" ) )
{
installer = productName + ".exe" ;
}
else
{
installer = productName + ".msi" ;
}
2016-03-08 13:39:41 -08:00
break ;
case BuildPlatform . OSX :
installer = productName + ".pkg" ;
break ;
case BuildPlatform . Ubuntu :
installer = productName + ".deb" ;
break ;
default :
break ;
}
if ( ! string . IsNullOrEmpty ( installer ) )
{
c . BuildContext [ contextPrefix + "InstallerFile" ] = Path . Combine ( Dirs . Packages , installer ) ;
}
2016-06-21 16:06:32 -05:00
}
2016-03-08 13:39:41 -08:00
2016-06-21 16:06:32 -05:00
// The following CalculateBlob methods are temporary until the core-setup repo up-takes the new Azure Publish layout and
// CLI consumes newer Shared FX versions.
private static string CalculateArchiveBlob ( string archiveFile , string channel , string version )
{
return $"{channel}/Binaries/{version}/{Path.GetFileName(archiveFile)}" ;
}
private static string CalculateInstallerBlob ( string installerFile , string channel , string version )
{
return $"{channel}/Installers/{version}/{Path.GetFileName(installerFile)}" ;
2016-03-08 13:39:41 -08:00
}
2016-02-02 10:04:50 -08:00
}
}