-2.0.0-prerelease-01616-04
+2.0.0-prerelease-01705-02
DependsOnTargets="$(TraversalBuildDependencies)" />
<Target Name="BuildCustomTasks">
- <MSBuild Projects="tools-local/Microsoft.DotNet.Build.Tasks.Local/Microsoft.DotNet.Build.Tasks.Local.builds" />
<MSBuild Projects="tools-local/tasks/core-setup.tasks.builds" />
<PropertyGroup>
<DependencyModelTFM Condition="'$(MSBuildRuntimeType)' != 'Core'">net451</DependencyModelTFM>
</PropertyGroup>
- <ItemGroup>
- <CustomTaskDependencies Include="$(BuildToolsTaskDir)Newtonsoft.Json.dll" />
- <CustomTaskDependencies Include="$(BuildToolsTaskDir)Microsoft.DotNet.PlatformAbstractions.dll" />
- <CustomTaskDependencies Include="$(PackagesDir)microsoft.extensions.dependencymodel\1.1.1\lib\$(DependencyModelTFM)\Microsoft.Extensions.DependencyModel.dll" />
- </ItemGroup>
- <Copy SourceFiles="@(CustomTaskDependencies)"
- DestinationFolder="$(LocalBuildToolsTaskDir)"
- OverwriteReadOnlyFiles="true"
- SkipUnchangedFiles="true" />
+ <ItemGroup>
+ <CustomTaskDependencies Include="$(BuildToolsTaskDir)Newtonsoft.Json.dll" />
+ <CustomTaskDependencies Include="$(BuildToolsTaskDir)Microsoft.DotNet.PlatformAbstractions.dll" />
+ <CustomTaskDependencies Include="$(PackagesDir)microsoft.extensions.dependencymodel\1.1.1\lib\$(DependencyModelTFM)\Microsoft.Extensions.DependencyModel.dll" />
+ </ItemGroup>
+ <Copy SourceFiles="@(CustomTaskDependencies)"
+ DestinationFolder="$(LocalBuildToolsTaskDir)"
+ OverwriteReadOnlyFiles="true"
+ SkipUnchangedFiles="true" />
</Target>
<Target Name="BatchRestorePackages" Condition="'$(RestoreDuringBuild)'=='true'">
</PropertyGroup>
<ItemGroup>
- <File Include="$(ToolsDir)\_.pdb"
+ <File Include="$(MSBuildThisFileDirectory)../_.pdb"
Condition="'$(NeedsPlaceholderPdb)' == 'true' AND '$(PackageTargetRuntime)' != ''">
<TargetPath>runtimes/$(PackageTargetRuntime)/native</TargetPath>
<IsSymbolFile>true</IsSymbolFile>
</MSBuild>
</Target>
-</Project>
\ No newline at end of file
+</Project>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <UsingTask TaskName="DownloadBlobsFromAzure" AssemblyFile="$(LocalBuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.Local.dll" />
+ <UsingTask TaskName="DownloadFromAzure" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.CloudTestTasks.dll" />
<UsingTask TaskName="FinalizeBuild" AssemblyFile="$(LocalBuildToolsTaskDir)core-setup.tasks.dll" />
- <UsingTask TaskName="GetAzureBlobList" AssemblyFile="$(LocalBuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.Local.dll" />
- <UsingTask TaskName="UploadToAzure" AssemblyFile="$(LocalBuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.Local.dll" />
+ <UsingTask TaskName="ListAzureBlobs" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.CloudTestTasks.dll" />
+ <UsingTask TaskName="UploadToAzure" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.CloudTestTasks.dll" />
<Target Name="Build"
DependsOnTargets="PublishToAzure;PublishDebFilesToDebianRepo;PublishDebToolPackageToFeed;PublishFinalOutput" />
<Error Condition="'$(AzureAccountName)' == ''" Text="Missing required property 'AzureAccountName'" />
<Error Condition="'$(ContainerName)' == ''" Text="Missing required property 'ContainerName'" />
- <GetAzureBlobList AccountName="$(AzureAccountName)"
+ <ListAzureBlobs AccountName="$(AzureAccountName)"
AccountKey="$(AzureAccessToken)"
ContainerName="$(ContainerName)"
- FilterblobNames="Runtime/$(SharedFrameworkNugetVersion)">
+ FilterBlobNames="Runtime/$(SharedFrameworkNugetVersion)">
<Output TaskParameter="BlobNames" ItemName="_BlobList" />
- </GetAzureBlobList>
+ </ListAzureBlobs>
<ItemGroup>
<_CoreHostPackages Include="%(_BlobList.Identity)" Condition="'%(_BlobList.Extension)' == '.nupkg'" />
</ItemGroup>
</PropertyGroup>
<MakeDir Directories="$(DownloadDirectory)"
Condition="!Exists('$(DownloadDirectory)')" />
- <DownloadBlobsFromAzure AccountName="$(AzureAccountName)"
+ <DownloadFromAzure AccountName="$(AzureAccountName)"
AccountKey="$(AzureAccessToken)"
ContainerName="$(ContainerName)"
BlobNames="@(_CoreHostPackages)"
+ BlobNamePrefix="Runtime/$(SharedFrameworkNugetVersion)"
DownloadDirectory="$(DownloadDirectory)" />
<ItemGroup>
<_DownloadedPackages Include="@(_CoreHostPackages->'$(DownloadDirectory)%(Filename)%(Extension)')" />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="dir.props" />
- <UsingTask TaskName="GetHostInformation" AssemblyFile="$(LocalBuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.Local.dll" />
+ <UsingTask TaskName="GetTargetMachineInfo" AssemblyFile="$(BuildToolsTaskDir)Microsoft.DotNet.Build.Tasks.dll" />
<PropertyGroup>
<BuildTestTargets>
<Target Name="Build" DependsOnTargets="$(BuildTestTargets)" />
<Target Name="DetermineTestOutputDirectory">
- <GetHostInformation>
- <Output TaskParameter="Rid" PropertyName="_HostRid" />
- </GetHostInformation>
+ <GetTargetMachineInfo>
+ <Output TaskParameter="RuntimeIdentifier" PropertyName="_HostRid" />
+ </GetTargetMachineInfo>
<PropertyGroup>
<TestTargetRid Condition="'$(TestTargetRid)' == ''">$(_HostRid)</TestTargetRid>
<TestOSPlatformConfig>$(TestTargetRid).$(ConfigurationGroup)</TestOSPlatformConfig>
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Build.Framework;
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public partial class AzureBlobLease
- {
- private string _containerName;
- private string _blobName;
- private TimeSpan _maxWait;
- private TimeSpan _delay;
- private const int s_MaxWaitDefault = 60; // seconds
- private const int s_DelayDefault = 500; // milliseconds
- private CancellationTokenSource _cancellationTokenSource;
- private Task _leaseRenewalTask;
- private string _connectionString;
- private string _accountName;
- private string _accountKey;
- private Microsoft.Build.Utilities.TaskLoggingHelper _log;
- private string _leaseId;
- private string _leaseUrl;
-
- public AzureBlobLease(string accountName, string accountKey, string connectionString, string containerName, string blobName, Microsoft.Build.Utilities.TaskLoggingHelper log, string maxWait = null, string delay=null)
- {
- _accountName = accountName;
- _accountKey = accountKey;
- _connectionString = connectionString;
- _containerName = containerName;
- _blobName = blobName;
- _maxWait = !string.IsNullOrWhiteSpace(maxWait) ? TimeSpan.Parse(maxWait) : TimeSpan.FromSeconds(s_MaxWaitDefault);
- _delay = !string.IsNullOrWhiteSpace(delay) ? TimeSpan.Parse(delay) : TimeSpan.FromMilliseconds(s_DelayDefault);
- _log = log;
- _leaseUrl = $"{Utility.AzureHelper.GetBlobRestUrl(_accountName, _containerName, _blobName)}?comp=lease";
- }
-
- public void Acquire()
- {
- Stopwatch stopWatch = new Stopwatch();
- stopWatch.Start();
-
- while (stopWatch.ElapsedMilliseconds < _maxWait.TotalMilliseconds)
- {
- try
- {
- string leaseId = AcquireLeaseOnBlobAsync().GetAwaiter().GetResult();
- _cancellationTokenSource = new CancellationTokenSource();
- _leaseRenewalTask = Task.Run(() =>
- { AutoRenewLeaseOnBlob(this, _accountName, _accountKey, _containerName, _blobName, leaseId, _leaseUrl, _log); },
- _cancellationTokenSource.Token);
- _leaseId = leaseId;
- return;
- }
- catch (Exception e)
- {
- _log.LogMessage($"Retrying lease acquisition on {_blobName}, {e.Message}");
- Thread.Sleep(_delay);
- }
- }
- ResetLeaseRenewalTaskState();
- throw new Exception($"Unable to acquire lease on {_blobName}");
-
- }
-
- public void Release()
- {
- // Cancel the lease renewal task since we are about to release the lease.
- ResetLeaseRenewalTaskState();
-
- using (HttpClient client = new HttpClient())
- {
- Tuple<string, string> leaseAction = new Tuple<string, string>("x-ms-lease-action", "release");
- Tuple<string, string> headerLeaseId = new Tuple<string, string>("x-ms-lease-id", _leaseId);
- List<Tuple<string, string>> additionalHeaders = new List<Tuple<string, string>>() { leaseAction, headerLeaseId };
- var request = Utility.AzureHelper.RequestMessage("PUT", _leaseUrl, _accountName, _accountKey, additionalHeaders);
- using (HttpResponseMessage response = Utility.AzureHelper.RequestWithRetry(_log, client, request).GetAwaiter().GetResult())
- {
- if (!response.IsSuccessStatusCode)
- {
- _log.LogMessage($"Unable to release lease on container/blob {_containerName}/{_blobName}.");
- }
- }
- }
- }
-
- private async Task<string> AcquireLeaseOnBlobAsync()
- {
- _log.LogMessage(MessageImportance.Low, $"Requesting lease for container/blob '{_containerName}/{_blobName}'.");
- string leaseId = string.Empty;
- using (HttpClient client = new HttpClient())
- {
- try
- {
- Tuple<string, string> leaseAction = new Tuple<string, string>("x-ms-lease-action", "acquire");
- Tuple<string, string> leaseDuration = new Tuple<string, string>("x-ms-lease-duration", "60" /* seconds */);
- List<Tuple<string, string>> additionalHeaders = new List<Tuple<string, string>>() { leaseAction, leaseDuration };
- var request = Utility.AzureHelper.RequestMessage("PUT", _leaseUrl, _accountName, _accountKey, additionalHeaders);
- using (HttpResponseMessage response = await Utility.AzureHelper.RequestWithRetry(_log, client, request))
- {
- leaseId = response.Headers.GetValues("x-ms-lease-id").FirstOrDefault();
- }
- }
- catch (Exception e)
- {
- _log.LogErrorFromException(e, true);
- }
- }
-
- return leaseId;
- }
- private static void AutoRenewLeaseOnBlob(AzureBlobLease instance, string accountName, string accountKey, string containerName, string blob, string leaseId, string leaseUrl, Microsoft.Build.Utilities.TaskLoggingHelper log)
- {
- TimeSpan maxWait = TimeSpan.FromSeconds(s_MaxWaitDefault);
- TimeSpan delay = TimeSpan.FromMilliseconds(s_DelayDefault);
- TimeSpan waitFor = maxWait;
- CancellationToken token = instance._cancellationTokenSource.Token;
-
- while (true)
- {
- token.ThrowIfCancellationRequested();
-
- try
- {
- log.LogMessage(MessageImportance.Low, $"Requesting lease for container/blob '{containerName}/{blob}'.");
- using (HttpClient client = new HttpClient())
- {
- Tuple<string, string> leaseAction = new Tuple<string, string>("x-ms-lease-action", "renew");
- Tuple<string, string> headerLeaseId = new Tuple<string, string>("x-ms-lease-id", leaseId);
- List<Tuple<string, string>> additionalHeaders = new List<Tuple<string, string>>() { leaseAction, headerLeaseId };
- var request = Utility.AzureHelper.RequestMessage("PUT", leaseUrl, accountName, accountKey, additionalHeaders);
- using (HttpResponseMessage response = Utility.AzureHelper.RequestWithRetry(log, client, request).GetAwaiter().GetResult())
- {
- if (!response.IsSuccessStatusCode)
- {
- throw new Exception("Unable to acquire lease.");
- }
- }
- }
- waitFor = maxWait;
- }
- catch (Exception e)
- {
- Console.WriteLine($"Rerying lease renewal on {containerName}, {e.Message}");
- waitFor = delay;
- }
- token.ThrowIfCancellationRequested();
-
- Thread.Sleep(waitFor);
- }
- }
-
- private void ResetLeaseRenewalTaskState()
- {
- // Cancel the lease renewal task if it was created
- if (_leaseRenewalTask != null)
- {
- _cancellationTokenSource.Cancel();
-
- // Block until the task ends. It can throw if we cancelled it before it completed.
- try
- {
- _leaseRenewalTask.Wait();
- }
- catch (Exception)
- {
- // Ignore the caught exception as it will be expected.
- }
-
- _leaseRenewalTask = null;
- }
- }
-
- }
-}
+++ /dev/null
-using Microsoft.Build.Utilities;
-using System.Text.RegularExpressions;
-
-namespace Microsoft.DotNet.Build.Tasks.Utility
-{
- public abstract class AzureConnectionStringBuildTask : Task
- {
- /// <summary>
- /// Azure Storage account connection string. Supersedes Account Key / Name.
- /// Will cause errors if both are set.
- /// </summary>
- public string ConnectionString { get; set; }
-
- /// <summary>
- /// The Azure account key used when creating the connection string.
- /// When we fully deprecate these, can just make them get; only.
- /// </summary>
- public string AccountKey { get; set; }
-
- /// <summary>
- /// The Azure account name used when creating the connection string.
- /// When we fully deprecate these, can just make them get; only.
- /// </summary>
- public string AccountName { get; set; }
-
- public void ParseConnectionString()
- {
- if (!string.IsNullOrEmpty(ConnectionString))
- {
- if (!(string.IsNullOrEmpty(AccountKey) && string.IsNullOrEmpty(AccountName)))
- {
- Log.LogError("If the ConnectionString property is set, you must not provide AccountKey / AccountName. These values will be deprecated in the future.");
- }
- else
- {
- Regex storageConnectionStringRegex = new Regex("AccountName=(?<name>.+?);AccountKey=(?<key>.+?);");
-
- MatchCollection matches = storageConnectionStringRegex.Matches(ConnectionString);
- if (matches.Count > 0)
- {
- // When we deprecate this format, we'll want to demote these to private
- AccountName = matches[0].Groups["name"].Value;
- AccountKey = matches[0].Groups["key"].Value;
- }
- else
- {
- Log.LogError("Error parsing connection string. Please review its value.");
- }
- }
- }
- else if (string.IsNullOrEmpty(AccountKey) || string.IsNullOrEmpty(AccountName))
- {
- Log.LogError("Error, must provide either ConnectionString or AccountName with AccountKey");
- }
- }
- }
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Security.Cryptography;
-using System.Text;
-using System.Text.RegularExpressions;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace Microsoft.DotNet.Build.Tasks.Utility
-{
- // This is grabbed directly from buildtools and we should not duplicate this when we move ListAzureBlobs back to buildtools
- public static class AzureHelper
- {
- /// <summary>
- /// The storage api version.
- /// </summary>
- public static readonly string StorageApiVersion = "2015-04-05";
- public const string DateHeaderString = "x-ms-date";
- public const string VersionHeaderString = "x-ms-version";
- public const string AuthorizationHeaderString = "Authorization";
- public const string CacheControlString = "x-ms-blob-cache-control";
- public const string ContentTypeString = "x-ms-blob-content-type";
-
- public enum SasAccessType
- {
- Read,
- Write,
- };
-
- public static string AuthorizationHeader(
- string storageAccount,
- string storageKey,
- string method,
- DateTime now,
- HttpRequestMessage request,
- string ifMatch = "",
- string contentMD5 = "",
- string size = "",
- string contentType = "")
- {
- string stringToSign = string.Empty;
- stringToSign = string.Format(
- "{0}\n\n\n{1}\n{5}\n{6}\n\n\n{2}\n\n\n\n{3}{4}",
- method,
- (size == string.Empty) ? string.Empty : size,
- ifMatch,
- GetCanonicalizedHeaders(request),
- GetCanonicalizedResource(request.RequestUri, storageAccount),
- contentMD5,
- contentType);
- byte[] signatureBytes = Encoding.UTF8.GetBytes(stringToSign);
- string authorizationHeader;
- using (HMACSHA256 hmacsha256 = new HMACSHA256(Convert.FromBase64String(storageKey)))
- {
- authorizationHeader = "SharedKey " + storageAccount + ":"
- + Convert.ToBase64String(hmacsha256.ComputeHash(signatureBytes));
- }
-
- return authorizationHeader;
- }
-
- public static string CreateContainerSasToken(
- string accountName,
- string containerName,
- string key,
- SasAccessType accessType,
- int validityTimeInDays)
- {
- string signedPermissions = string.Empty;
- switch (accessType)
- {
- case SasAccessType.Read:
- signedPermissions = "r";
- break;
- case SasAccessType.Write:
- signedPermissions = "wdl";
- break;
- default:
- throw new ArgumentOutOfRangeException(nameof(accessType), accessType, "Unrecognized value");
- }
-
- string signedStart = DateTime.UtcNow.ToString("O");
- string signedExpiry = DateTime.UtcNow.AddDays(validityTimeInDays).ToString("O");
- string canonicalizedResource = "/blob/" + accountName + "/" + containerName;
- string signedIdentifier = string.Empty;
- string signedVersion = StorageApiVersion;
-
- string stringToSign = ConstructServiceStringToSign(
- signedPermissions,
- signedVersion,
- signedExpiry,
- canonicalizedResource,
- signedIdentifier,
- signedStart);
-
- byte[] signatureBytes = Encoding.UTF8.GetBytes(stringToSign);
- string signature;
- using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(key)))
- {
- signature = Convert.ToBase64String(hmacSha256.ComputeHash(signatureBytes));
- }
-
- string sasToken = string.Format(
- "?sv={0}&sr={1}&sig={2}&st={3}&se={4}&sp={5}",
- WebUtility.UrlEncode(signedVersion),
- WebUtility.UrlEncode("c"),
- WebUtility.UrlEncode(signature),
- WebUtility.UrlEncode(signedStart),
- WebUtility.UrlEncode(signedExpiry),
- WebUtility.UrlEncode(signedPermissions));
-
- return sasToken;
- }
-
- public static string GetCanonicalizedHeaders(HttpRequestMessage request)
- {
- StringBuilder sb = new StringBuilder();
- List<string> headerNameList = (from headerName in request.Headers
- where
- headerName.Key.ToLowerInvariant()
- .StartsWith("x-ms-", StringComparison.Ordinal)
- select headerName.Key.ToLowerInvariant()).ToList();
- headerNameList.Sort();
- foreach (string headerName in headerNameList)
- {
- StringBuilder builder = new StringBuilder(headerName);
- string separator = ":";
- foreach (string headerValue in GetHeaderValues(request.Headers, headerName))
- {
- string trimmedValue = headerValue.Replace("\r\n", string.Empty);
- builder.Append(separator);
- builder.Append(trimmedValue);
- separator = ",";
- }
-
- sb.Append(builder);
- sb.Append("\n");
- }
-
- return sb.ToString();
- }
-
- public static string GetCanonicalizedResource(Uri address, string accountName)
- {
- StringBuilder str = new StringBuilder();
- StringBuilder builder = new StringBuilder("/");
- builder.Append(accountName);
- builder.Append(address.AbsolutePath);
- str.Append(builder);
- Dictionary<string, HashSet<string>> queryKeyValues = ExtractQueryKeyValues(address);
- Dictionary<string, HashSet<string>> dictionary = GetCommaSeparatedList(queryKeyValues);
-
- foreach (KeyValuePair<string, HashSet<string>> pair in dictionary.OrderBy(p => p.Key))
- {
- StringBuilder stringBuilder = new StringBuilder(string.Empty);
- stringBuilder.Append(pair.Key + ":");
- string commaList = string.Join(",", pair.Value);
- stringBuilder.Append(commaList);
- str.Append("\n");
- str.Append(stringBuilder);
- }
-
- return str.ToString();
- }
-
- public static List<string> GetHeaderValues(HttpRequestHeaders headers, string headerName)
- {
- List<string> list = new List<string>();
- headers.TryGetValues(headerName, out IEnumerable<string> values);
- if (values != null)
- {
- list.Add((values.FirstOrDefault() ?? string.Empty).TrimStart(null));
- }
-
- return list;
- }
-
- private static bool IsWithinRetryRange(HttpStatusCode statusCode)
- {
- // Retry on http client and server error codes (4xx - 5xx) as well as redirect
-
- var rawStatus = (int)statusCode;
- if (rawStatus == 302)
- return true;
- else if (rawStatus >= 400 && rawStatus <= 599)
- return true;
- else
- return false;
- }
-
- public static async Task<HttpResponseMessage> RequestWithRetry(TaskLoggingHelper loggingHelper, HttpClient client,
- Func<HttpRequestMessage> createRequest, Func<HttpResponseMessage, bool> validationCallback = null, int retryCount = 5,
- int retryDelaySeconds = 5)
- {
- if (loggingHelper == null)
- throw new ArgumentNullException(nameof(loggingHelper));
- if (client == null)
- throw new ArgumentNullException(nameof(client));
- if (createRequest == null)
- throw new ArgumentNullException(nameof(createRequest));
- if (retryCount < 1)
- throw new ArgumentException(nameof(retryCount));
- if (retryDelaySeconds < 1)
- throw new ArgumentException(nameof(retryDelaySeconds));
-
- int retries = 0;
- HttpResponseMessage response = null;
-
- // add a bit of randomness to the retry delay
- var rng = new Random();
-
- while (retries < retryCount)
- {
- if (retries > 0)
- {
- if (response != null)
- {
- response.Dispose();
- response = null;
- }
-
- int delay = retryDelaySeconds * retries * rng.Next(1, 5);
- loggingHelper.LogMessage(MessageImportance.Low, "Waiting {0} seconds before retry", delay);
- await System.Threading.Tasks.Task.Delay(delay * 1000);
- }
-
- try
- {
- using (var request = createRequest())
- response = await client.SendAsync(request);
- }
- catch (Exception e)
- {
- loggingHelper.LogWarningFromException(e, true);
-
- // if this is the final iteration let the exception bubble up
- if (retries + 1 == retryCount)
- throw;
- }
-
- // response can be null if we fail to send the request
- if (response != null)
- {
- if (validationCallback == null)
- {
- // check if the response code is within the range of failures
- if (!IsWithinRetryRange(response.StatusCode))
- {
- return response;
- }
- }
- else
- {
- bool isSuccess = validationCallback(response);
- if (!isSuccess)
- {
- loggingHelper.LogMessage("Validation callback returned retry for status code {0}", response.StatusCode);
- }
- else
- {
- loggingHelper.LogMessage("Validation callback returned success for status code {0}", response.StatusCode);
- return response;
- }
- }
- }
-
- ++retries;
- }
-
- // retry count exceeded
- loggingHelper.LogWarning("Retry count {0} exceeded", retryCount);
-
- // set some default values in case response is null
- var statusCode = "None";
- var contentStr = "Null";
- if (response != null)
- {
- statusCode = response.StatusCode.ToString();
- contentStr = await response.Content.ReadAsStringAsync();
- response.Dispose();
- }
-
- throw new HttpRequestException(string.Format("Request failed with status {0} response {1}", statusCode, contentStr));
- }
-
- private static string ConstructServiceStringToSign(
- string signedPermissions,
- string signedVersion,
- string signedExpiry,
- string canonicalizedResource,
- string signedIdentifier,
- string signedStart,
- string signedIP = "",
- string signedProtocol = "",
- string rscc = "",
- string rscd = "",
- string rsce = "",
- string rscl = "",
- string rsct = "")
- {
- // constructing string to sign based on spec in https://msdn.microsoft.com/en-us/library/azure/dn140255.aspx
- var stringToSign = string.Join(
- "\n",
- signedPermissions,
- signedStart,
- signedExpiry,
- canonicalizedResource,
- signedIdentifier,
- signedIP,
- signedProtocol,
- signedVersion,
- rscc,
- rscd,
- rsce,
- rscl,
- rsct);
- return stringToSign;
- }
-
- private static Dictionary<string, HashSet<string>> ExtractQueryKeyValues(Uri address)
- {
- Dictionary<string, HashSet<string>> values = new Dictionary<string, HashSet<string>>();
- //Decode this to allow the regex to pull out the correct groups for signing
- address = new Uri(WebUtility.UrlDecode(address.ToString()));
- Regex newreg = new Regex(@"(?:\?|&)([^=]+)=([^&]+)");
- MatchCollection matches = newreg.Matches(address.Query);
- foreach (Match match in matches)
- {
- string key, value;
- if (!string.IsNullOrEmpty(match.Groups[1].Value))
- {
- key = match.Groups[1].Value;
- value = match.Groups[2].Value;
- }
- else
- {
- key = match.Groups[3].Value;
- value = match.Groups[4].Value;
- }
-
- if (values.TryGetValue(key, out HashSet<string> setOfValues))
- {
- setOfValues.Add(value);
- }
- else
- {
- HashSet<string> newSet = new HashSet<string> { value };
- values.Add(key, newSet);
- }
- }
-
- return values;
- }
-
- private static Dictionary<string, HashSet<string>> GetCommaSeparatedList(
- Dictionary<string, HashSet<string>> queryKeyValues)
- {
- Dictionary<string, HashSet<string>> dictionary = new Dictionary<string, HashSet<string>>();
-
- foreach (string queryKeys in queryKeyValues.Keys)
- {
- queryKeyValues.TryGetValue(queryKeys, out HashSet<string> setOfValues);
- List<string> list = new List<string>();
- list.AddRange(setOfValues);
- list.Sort();
- string commaSeparatedValues = string.Join(",", list);
- string key = queryKeys.ToLowerInvariant();
- if (dictionary.TryGetValue(key, out HashSet<string> setOfValues2))
- {
- setOfValues2.Add(commaSeparatedValues);
- }
- else
- {
- HashSet<string> newSet = new HashSet<string> { commaSeparatedValues };
- dictionary.Add(key, newSet);
- }
- }
-
- return dictionary;
- }
- // This is duplicated code from https://github.com/dotnet/buildtools/blob/master/src/Microsoft.DotNet.Build.CloudTestTasks/AzureConnectionStringBuildTask.cs
- // when we move "ListAzureBlobs.cs" into buildtools, we should eliminate this duplication.
- public static Tuple<string, string> ParseConnectionString(string connectionString)
- {
- Regex storageConnectionStringRegex = new Regex("AccountName=(?<name>.+?);AccountKey=(?<key>.+?);");
-
- MatchCollection matches = storageConnectionStringRegex.Matches(connectionString);
- if (matches.Count > 0)
- {
- return new Tuple<string, string>(matches[0].Groups["name"].Value, matches[0].Groups["key"].Value);
- }
- else
- {
- return null;
- }
- }
-
- public static Func<HttpRequestMessage> RequestMessage(string method, string url, string accountName, string accountKey, List<Tuple<string, string>> additionalHeaders = null, string body = null)
- {
- Func<HttpRequestMessage> requestFunc = () =>
- {
- HttpMethod httpMethod = HttpMethod.Get;
- if(method == "PUT")
- {
- httpMethod = HttpMethod.Put;
- }
- else if (method == "DELETE")
- {
- httpMethod = HttpMethod.Delete;
- }
- DateTime dateTime = DateTime.UtcNow;
- var request = new HttpRequestMessage(httpMethod, url);
- request.Headers.Add(AzureHelper.DateHeaderString, dateTime.ToString("R", CultureInfo.InvariantCulture));
- request.Headers.Add(AzureHelper.VersionHeaderString, AzureHelper.StorageApiVersion);
- if (additionalHeaders != null)
- {
- foreach (Tuple<string, string> additionalHeader in additionalHeaders)
- {
- request.Headers.Add(additionalHeader.Item1, additionalHeader.Item2);
- }
- }
- if (body != null)
- {
- request.Content = new StringContent(body);
- request.Headers.Add(AzureHelper.AuthorizationHeaderString, AzureHelper.AuthorizationHeader(
- accountName,
- accountKey,
- method,
- dateTime,
- request,
- "",
- "",
- request.Content.Headers.ContentLength.ToString(),
- request.Content.Headers.ContentType.ToString()));
- }
- else
- {
- request.Headers.Add(AzureHelper.AuthorizationHeaderString, AzureHelper.AuthorizationHeader(
- accountName,
- accountKey,
- method,
- dateTime,
- request));
- }
- return request;
- };
- return requestFunc;
- }
-
- public static string GetBlobRestUrl(string accountName, string containerName, string blob)
- {
- return $"https://{accountName}.blob.core.windows.net/{containerName}/{blob}";
- }
- }
-}
+++ /dev/null
-using Microsoft.Build.Framework;
-using System;
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Threading.Tasks;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public partial class CopyAzureBlobToBlob : Utility.AzureConnectionStringBuildTask
- {
- [Required]
- public string ContainerName { get; set; }
- [Required]
- public string SourceBlobName { get; set; }
- [Required]
- public string DestinationBlobName { get; set; }
-
- public override bool Execute()
- {
- return ExecuteAsync().GetAwaiter().GetResult();
- }
-
- public async Task<bool> ExecuteAsync()
- {
- ParseConnectionString();
- if (Log.HasLoggedErrors)
- {
- return false;
- }
-
- string sourceUrl = Utility.AzureHelper.GetBlobRestUrl(AccountName, ContainerName, SourceBlobName);
- string destinationUrl = Utility.AzureHelper.GetBlobRestUrl(AccountName, ContainerName, DestinationBlobName);
- using (HttpClient client = new HttpClient())
- {
- try
- {
- Tuple<string, string> leaseAction = new Tuple<string, string>("x-ms-lease-action", "acquire");
- Tuple<string, string> leaseDuration = new Tuple<string, string>("x-ms-lease-duration", "60" /* seconds */);
- Tuple<string, string> headerSource = new Tuple<string, string>("x-ms-copy-source", sourceUrl);
- List<Tuple<string, string>> additionalHeaders = new List<Tuple<string, string>>() { leaseAction, leaseDuration, headerSource };
- var request = Utility.AzureHelper.RequestMessage("PUT", destinationUrl, AccountName, AccountKey, additionalHeaders);
- using (HttpResponseMessage response = await Utility.AzureHelper.RequestWithRetry(Log, client, request))
- {
- if (response.IsSuccessStatusCode)
- {
- return true;
- }
- }
- }
- catch (Exception e)
- {
- Log.LogErrorFromException(e, true);
- }
- }
- return false;
- }
- public static bool Execute(string accountName,
- string accountKey,
- string connectionString,
- string containerName,
- string sourceBlobName,
- string destinationBlobName,
- IBuildEngine buildengine,
- ITaskHost taskHost)
- {
- CopyAzureBlobToBlob copyAzureBlobToBlob = new CopyAzureBlobToBlob()
- {
- AccountName = accountName,
- AccountKey = accountKey,
- ContainerName = containerName,
- SourceBlobName = sourceBlobName,
- DestinationBlobName = destinationBlobName,
- BuildEngine = buildengine,
- HostObject = taskHost
- };
- return copyAzureBlobToBlob.Execute();
- }
- public static Task<bool> ExecuteAsync(string accountName,
- string accountKey,
- string connectionString,
- string containerName,
- string sourceBlobName,
- string destinationBlobName,
- IBuildEngine buildengine,
- ITaskHost taskHost)
- {
- CopyAzureBlobToBlob copyAzureBlobToBlob = new CopyAzureBlobToBlob()
- {
- AccountName = accountName,
- AccountKey = accountKey,
- ContainerName = containerName,
- SourceBlobName = sourceBlobName,
- DestinationBlobName = destinationBlobName,
- BuildEngine = buildengine,
- HostObject = taskHost
- };
- return copyAzureBlobToBlob.ExecuteAsync();
- }
- }
-}
+++ /dev/null
-using Microsoft.Build.Framework;
-using System;
-using System.Collections.Generic;
-using System.Net.Http;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public partial class DeleteAzureBlob: Utility.AzureConnectionStringBuildTask
- {
- [Required]
- public string ContainerName { get; set; }
- [Required]
- public string BlobName { get; set; }
-
- public override bool Execute()
- {
- ParseConnectionString();
- if (Log.HasLoggedErrors)
- {
- return false;
- }
-
- string deleteUrl = $"https://{AccountName}.blob.core.windows.net/{ContainerName}/{BlobName}";
-
- using (HttpClient client = new HttpClient())
- {
- try
- {
- Tuple<string, string> snapshots = new Tuple<string, string>("x-ms-lease-delete-snapshots", "include");
- List<Tuple<string, string>> additionalHeaders = new List<Tuple<string, string>>() { snapshots };
- var request = Utility.AzureHelper.RequestMessage("DELETE", deleteUrl, AccountName, AccountKey, additionalHeaders);
- using (HttpResponseMessage response = Utility.AzureHelper.RequestWithRetry(Log, client, request).GetAwaiter().GetResult())
- {
- return response.IsSuccessStatusCode;
- }
- }
- catch (Exception e)
- {
- Log.LogErrorFromException(e, true);
- }
- }
-
- return !Log.HasLoggedErrors;
- }
-
- public static bool Execute(string accountName,
- string accountKey,
- string connectionString,
- string containerName,
- string blobName,
- IBuildEngine buildengine,
- ITaskHost taskHost)
- {
- DeleteAzureBlob deleteAzureoBlob = new DeleteAzureBlob()
- {
- AccountName = accountName,
- AccountKey = accountKey,
- ContainerName = containerName,
- BlobName = blobName,
- BuildEngine = buildengine,
- HostObject = taskHost
- };
- return deleteAzureoBlob.Execute();
- }
- }
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Build.Framework;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Net.Http;
-using System.Threading.Tasks;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public partial class DownloadBlobFromAzure : Utility.AzureConnectionStringBuildTask
- {
- /// <summary>
- /// The name of the container to access. The specified name must be in the correct format, see the
- /// following page for more info. https://msdn.microsoft.com/en-us/library/azure/dd135715.aspx
- /// </summary>
- [Required]
- public string ContainerName { get; set; }
-
- [Required]
- public string BlobName { get; set; }
-
- /// <summary>
- /// Directory to download blob files to.
- /// </summary>
- [Required]
- public string DownloadDirectory { get; set; }
-
- public override bool Execute()
- {
- return ExecuteAsync().GetAwaiter().GetResult();
- }
-
- public async Task<bool> ExecuteAsync()
- {
- ParseConnectionString();
- if (Log.HasLoggedErrors)
- {
- return false;
- }
-
- Log.LogMessage(MessageImportance.Normal, "Downloading blob {0} from container {1} at storage account '{2}' to directory {3}.",
- BlobName, ContainerName, AccountName, DownloadDirectory);
-
- List<string> blobsNames = new List<string>();
- string urlListBlobs = $"https://{AccountName}.blob.core.windows.net/{ContainerName}/{BlobName}";
-
- Log.LogMessage(MessageImportance.Low, "Sending request to list blobsNames for container '{0}'.", ContainerName);
-
- using (HttpClient client = new HttpClient())
- {
- try
- {
- Func<HttpRequestMessage> createRequest = () =>
- {
- DateTime dateTime = DateTime.UtcNow;
- var request = new HttpRequestMessage(HttpMethod.Get, urlListBlobs);
- request.Headers.Add(Utility.AzureHelper.DateHeaderString, dateTime.ToString("R", CultureInfo.InvariantCulture));
- request.Headers.Add(Utility.AzureHelper.VersionHeaderString, Utility.AzureHelper.StorageApiVersion);
- request.Headers.Add(Utility.AzureHelper.AuthorizationHeaderString, Utility.AzureHelper.AuthorizationHeader(
- AccountName,
- AccountKey,
- "GET",
- dateTime,
- request));
- return request;
- };
-
- // track the number of blobs that fail to download
- string blob = Path.GetFileName(BlobName);
- string filename = Path.Combine(DownloadDirectory, blob);
- using (HttpResponseMessage response = await Utility.AzureHelper.RequestWithRetry(Log, client, createRequest))
- {
- if (response.IsSuccessStatusCode)
- {
- // Blobs can be files but have the name of a directory. We'll skip those and log something weird happened.
- if (!string.IsNullOrEmpty(Path.GetFileName(filename)))
- {
- Stream responseStream = await response.Content.ReadAsStreamAsync();
-
- using (FileStream sourceStream = File.Open(filename, FileMode.Create))
- {
- responseStream.CopyTo(sourceStream);
- }
- }
- else
- {
- Log.LogWarning($"Unable to download blob '{blob}' as it has a directory-like name. This may cause problems if it was needed.");
- }
- }
- else
- {
- Log.LogError("Failed to retrieve blob {0}, the status code was {1}", blob, response.StatusCode);
- }
- }
- }
- catch (Exception e)
- {
- Log.LogErrorFromException(e, true);
- }
- return !Log.HasLoggedErrors;
- }
- }
-
- public static bool Execute(string accountName,
- string accountKey,
- string connectionString,
- string containerName,
- string blobName,
- string downloadDirectory,
- IBuildEngine buildengine,
- ITaskHost taskHost)
- {
- DownloadBlobFromAzure downloadBlobFromAzure = new DownloadBlobFromAzure()
- {
- AccountName = accountName,
- AccountKey = accountKey,
- ContainerName = containerName,
- BlobName = blobName,
- DownloadDirectory = downloadDirectory,
- BuildEngine = buildengine,
- HostObject = taskHost
- };
- return downloadBlobFromAzure.Execute();
- }
-
- public static Task<bool> ExecuteAsync(string accountName,
- string accountKey,
- string connectionString,
- string containerName,
- string blobName,
- string downloadDirectory,
- IBuildEngine buildengine,
- ITaskHost taskHost)
- {
- DownloadBlobFromAzure downloadBlobFromAzure = new DownloadBlobFromAzure()
- {
- AccountName = accountName,
- AccountKey = accountKey,
- ContainerName = containerName,
- BlobName = blobName,
- DownloadDirectory = downloadDirectory,
- BuildEngine = buildengine,
- HostObject = taskHost
- };
- return downloadBlobFromAzure.ExecuteAsync();
- }
- }
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Build.Framework;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Threading.Tasks;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public partial class DownloadBlobsFromAzure : Utility.AzureConnectionStringBuildTask
- {
- /// <summary>
- /// The name of the container to access. The specified name must be in the correct format, see the
- /// following page for more info. https://msdn.microsoft.com/en-us/library/azure/dd135715.aspx
- /// </summary>
- [Required]
- public string ContainerName { get; set; }
-
- [Required]
- public ITaskItem[] BlobNames { get; set; }
-
- /// <summary>
- /// Directory to download blob files to.
- /// </summary>
- [Required]
- public string DownloadDirectory { get; set; }
-
- public override bool Execute()
- {
- var tasks = ExecuteAsync();
- if(tasks == null)
- {
- return false;
- }
- Task.WaitAll(tasks.ToArray());
- return !tasks.Any(t => t.Result == false);
- }
-
- public List<Task<bool>> ExecuteAsync()
- {
- ParseConnectionString();
- if (Log.HasLoggedErrors)
- {
- return null;
- }
- List<Task<bool>> downloadTasks = new List<Task<bool>>();
- foreach (var blobFile in BlobNames)
- {
- string localBlobFile = Path.Combine(DownloadDirectory, Path.GetFileName(blobFile.ItemSpec));
- Log.LogMessage($"Downloading {blobFile} to {localBlobFile}");
-
- downloadTasks.Add(DownloadBlobFromAzure.ExecuteAsync(AccountName, AccountKey, ConnectionString, ContainerName, blobFile.ItemSpec, DownloadDirectory, BuildEngine, HostObject));
- }
- return downloadTasks;
- }
- }
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-using System;
-using System.IO;
-using System.Security.Cryptography;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public class GenerateChecksums : Task
- {
- /// <summary>
- /// An item collection of files for which to generate checksums. Each item must have metadata
- /// 'DestinationPath' that specifies the path of the checksum file to create.
- /// </summary>
- [Required]
- public ITaskItem[] Items { get; set; }
-
- public override bool Execute()
- {
- foreach (ITaskItem item in Items)
- {
- try
- {
- string destinationPath = item.GetMetadata("DestinationPath");
- if (string.IsNullOrEmpty(destinationPath))
- {
- throw new Exception($"Metadata 'DestinationPath' is missing for item '{item.ItemSpec}'.");
- }
-
- if (!File.Exists(item.ItemSpec))
- {
- throw new Exception($"The file '{item.ItemSpec}' does not exist.");
- }
-
- Log.LogMessage(
- MessageImportance.High,
- "Generating checksum for '{0}' into '{1}'...",
- item.ItemSpec,
- destinationPath);
-
- using (FileStream stream = File.OpenRead(item.ItemSpec))
- {
- using(HashAlgorithm hashAlgorithm = SHA512.Create())
- {
- byte[] hash = hashAlgorithm.ComputeHash(stream);
- string checksum = BitConverter.ToString(hash).Replace("-", string.Empty);
- File.WriteAllText(destinationPath, checksum);
- }
- }
- }
- catch (Exception e)
- {
- // We have 2 log calls because we want a nice error message but we also want to capture the
- // callstack in the log.
- Log.LogError("An exception occurred while trying to generate a checksum for '{0}'.", item.ItemSpec);
- Log.LogMessage(MessageImportance.Low, e.ToString());
- return false;
- }
- }
-
- return true;
- }
- }
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using Microsoft.Build.Framework;
-using System.Collections.Generic;
-using System.Net.Http;
-using System.Xml;
-using System.Threading.Tasks;
-using System.Linq;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public partial class GetAzureBlobList : Utility.AzureConnectionStringBuildTask
- {
-
- /// <summary>
- /// The name of the container to access. The specified name must be in the correct format, see the
- /// following page for more info. https://msdn.microsoft.com/en-us/library/azure/dd135715.aspx
- /// </summary>
- [Required]
- public string ContainerName { get; set; }
-
- [Output]
- public string[] BlobNames { get; set; }
-
- public string FilterBlobNames { get; set; }
-
- public override bool Execute()
- {
- return ExecuteAsync().GetAwaiter().GetResult();
- }
-
- public static string [] Execute(string accountName,
- string accountKey,
- string connectionString,
- string containerName,
- string filterBlobNames,
- IBuildEngine buildengine,
- ITaskHost taskHost)
- {
- GetAzureBlobList getAzureBlobList = new GetAzureBlobList()
- {
- AccountName = accountName,
- AccountKey = accountKey,
- ContainerName = containerName,
- FilterBlobNames = filterBlobNames,
- BuildEngine = buildengine,
- HostObject = taskHost
- };
- getAzureBlobList.Execute();
- return getAzureBlobList.BlobNames;
- }
-
- // This code is duplicated in BuildTools task DownloadFromAzure, and that code should be refactored to permit blob listing.
- public async Task<bool> ExecuteAsync()
- {
- ParseConnectionString();
-
- if (Log.HasLoggedErrors)
- {
- return false;
- }
-
- List<string> blobsNames = new List<string>();
- string urlListBlobs = string.Format("https://{0}.blob.core.windows.net/{1}?restype=container&comp=list", AccountName, ContainerName);
- if (!string.IsNullOrWhiteSpace(FilterBlobNames))
- {
- urlListBlobs += $"&prefix={FilterBlobNames}";
- }
- Log.LogMessage(MessageImportance.Low, "Sending request to list blobsNames for container '{0}'.", ContainerName);
-
- using (HttpClient client = new HttpClient())
- {
- try
- {
- var createRequest = Utility.AzureHelper.RequestMessage("GET", urlListBlobs, AccountName, AccountKey);
-
- XmlDocument responseFile;
- string nextMarker = string.Empty;
- using (HttpResponseMessage response = await Utility.AzureHelper.RequestWithRetry(Log, client, createRequest))
- {
- responseFile = new XmlDocument();
- responseFile.LoadXml(await response.Content.ReadAsStringAsync());
- XmlNodeList elemList = responseFile.GetElementsByTagName("Name");
-
- blobsNames.AddRange(elemList.Cast<XmlNode>()
- .Select(x => x.InnerText)
- .ToList());
-
- nextMarker = responseFile.GetElementsByTagName("NextMarker").Cast<XmlNode>().FirstOrDefault()?.InnerText;
- }
- while (!string.IsNullOrEmpty(nextMarker))
- {
- urlListBlobs = string.Format($"https://{AccountName}.blob.core.windows.net/{ContainerName}?restype=container&comp=list&marker={nextMarker}");
- var nextRequest = Utility.AzureHelper.RequestMessage("GET", urlListBlobs, AccountName, AccountKey);
- using (HttpResponseMessage nextResponse = Utility.AzureHelper.RequestWithRetry(Log, client, nextRequest).GetAwaiter().GetResult())
- {
- responseFile = new XmlDocument();
- responseFile.LoadXml(await nextResponse.Content.ReadAsStringAsync());
- XmlNodeList elemList = responseFile.GetElementsByTagName("Name");
-
- blobsNames.AddRange(elemList.Cast<XmlNode>()
- .Select(x => x.InnerText)
- .ToList());
-
- nextMarker = responseFile.GetElementsByTagName("NextMarker").Cast<XmlNode>().FirstOrDefault()?.InnerText;
- }
- }
- BlobNames = blobsNames.ToArray();
- }
- catch (Exception e)
- {
- Log.LogErrorFromException(e, true);
- }
- return !Log.HasLoggedErrors;
- }
- }
- }
-
-}
+++ /dev/null
-using System;
-using System.IO;
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-using Microsoft.DotNet.PlatformAbstractions;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- /*
- * Used vendored code from Microsoft.DotNet.PlatformAbstractions.
- * Long term we should use that library once it is clear how to
- * get MSBuild on core to be able to load the dependent assembly.
- */
- public class GetHostInformation : Task
- {
- [Output]
- public string Rid { get; set; }
-
- [Output]
- public string OSName { get; set; }
-
- public override bool Execute()
- {
- Rid = RuntimeEnvironment.GetRuntimeIdentifier();
-
- switch (RuntimeEnvironment.OperatingSystemPlatform)
- {
- case Platform.Windows:
- OSName = "Windows_NT";
- break;
- case Platform.Linux:
- OSName = "Linux";
- break;
- case Platform.Darwin:
- OSName = "OSX";
- break;
- default:
- Log.LogError("Could not determine display name for platform.");
- return false;
- }
-
- return true;
- }
- }
-}
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <ItemGroup>
- <Project Include="$(MSBuildThisFileDirectory)$(MSBuildProjectName).csproj">
- <AdditionalProperties>TargetGroup=netstandard1.5</AdditionalProperties>
- </Project>
- <Project Include="$(MSBuildThisFileDirectory)$(MSBuildProjectName).csproj">
- <AdditionalProperties>TargetGroup=net45</AdditionalProperties>
- </Project>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.traversal.targets))\dir.traversal.targets" />
-</Project>
\ No newline at end of file
+++ /dev/null
-<?xml version="1.0" encoding="utf-8"?>
-<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
- <PropertyGroup>
- <OutputType>Library</OutputType>
- <NuGetTargetMoniker>.NETStandard,Version=v1.5</NuGetTargetMoniker>
- <NuGetTargetMonikerShort>netstandard1.5</NuGetTargetMonikerShort>
- <NuGetTargetMoniker Condition="'$(TargetGroup)' == 'net45'">.NETFramework,Version=v4.5.1</NuGetTargetMoniker>
- <NuGetTargetMonikerShort Condition="'$(TargetGroup)' == 'net45'">net451</NuGetTargetMonikerShort>
- <CLSCompliant>false</CLSCompliant>
- <ProjectGuid>{B507BED2-0A28-456A-99C6-AD7AA148E35F}</ProjectGuid>
- <OutputPath Condition="'$(TargetGroup)' != 'net45'">$(LocalToolRuntimePath)</OutputPath>
- <OutputPath Condition="'$(TargetGroup)' == 'net45'">$(LocalToolRuntimePath)\net46</OutputPath>
- <IntermediateOutputPath>$(BaseIntermediateOutputPath)tools-local/$(MSBuildProjectName)/$(TargetGroup)</IntermediateOutputPath>
- <PackageTargetFallback>dnxcore50;portable-net45+win8+wpa81</PackageTargetFallback>
- <ContainsPackageReferences>true</ContainsPackageReferences>
- <TargetFrameworkIdentifier>.NETStandard</TargetFrameworkIdentifier>
- <RestoreOutputPath>$(IntermediateOutputPath)</RestoreOutputPath>
- <SkipSigning>true</SkipSigning>
- <RestorePackages>true</RestorePackages>
- </PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)' == 'netstandard1.5_Debug'" />
- <PropertyGroup Condition="'$(Configuration)' == 'net45_Debug'" />
- <ItemGroup>
- <Compile Include="*.cs" />
- </ItemGroup>
- <ItemGroup>
- <PackageReference Include="Microsoft.DotNet.PlatformAbstractions">
- <Version>1.2.0-beta-001090</Version>
- </PackageReference>
- <PackageReference Include="System.Reflection.Metadata">
- <Version>1.3.0</Version>
- </PackageReference>
- <PackageReference Include="Newtonsoft.Json">
- <Version>9.0.1</Version>
- </PackageReference>
- </ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'net45'">
- <PackageReference Include="Microsoft.TargetingPack.NETFramework.v4.5.1">
- <Version>1.0.1</Version>
- </PackageReference>
- <TargetingPackReference Include="System" />
- <TargetingPackReference Include="System.Core" />
- <TargetingPackReference Include="System.Net.Http" />
- <TargetingPackReference Include="System.Runtime" />
- <TargetingPackReference Include="System.Xml" />
- <TargetingPackReference Include="Microsoft.Build" />
- <TargetingPackReference Include="Microsoft.Build.Framework" />
- <TargetingPackReference Include="Microsoft.Build.Utilities.v4.0" />
- <TargetingPackReference Include="Microsoft.DotNet.PlatformAbstractions" />
- </ItemGroup>
- <ItemGroup Condition="'$(TargetGroup)' == 'netstandard1.5'">
- <PackageReference Include="Microsoft.Build">
- <Version>0.1.0-preview-00022</Version>
- </PackageReference>
- <PackageReference Include="Microsoft.Build.Framework">
- <Version>0.1.0-preview-00022</Version>
- </PackageReference>
- <PackageReference Include="Microsoft.Build.Tasks.Core">
- <Version>0.1.0-preview-00022</Version>
- </PackageReference>
- <PackageReference Include="Microsoft.Build.Utilities.Core">
- <Version>0.1.0-preview-00022</Version>
- </PackageReference>
- <PackageReference Include="Microsoft.Tpl.Dataflow">
- <Version>4.5.24</Version>
- <IncludeAssets>None</IncludeAssets>
- </PackageReference>
- <PackageReference Include="NETStandard.Library">
- <Version>1.6.0</Version>
- </PackageReference>
- <PackageReference Include="System.Diagnostics.FileVersionInfo">
- <Version>4.0.0</Version>
- </PackageReference>
- </ItemGroup>
- <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
-</Project>
+++ /dev/null
-using Microsoft.Build.Framework;
-using Microsoft.DotNet.Build.Tasks.Utility;
-using System;
-using System.Collections.Generic;
-using System.Net.Http;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
- public partial class PublishStringToAzureBlob : Utility.AzureConnectionStringBuildTask
- {
- [Required]
- public string BlobName { get; set; }
- [Required]
- public string ContainerName { get; set; }
- [Required]
- public string Content { get; set; }
- public string ContentType { get; set; }
-
- public override bool Execute()
- {
- ParseConnectionString();
-
- string blobUrl = $"https://{AccountName}.blob.core.windows.net/{ContainerName}/{BlobName}";
- using (HttpClient client = new HttpClient())
- {
- try
- {
- Tuple<string, string> headerBlobType = new Tuple<string, string>("x-ms-blob-type", "BlockBlob");
- List<Tuple<string, string>> additionalHeaders = new List<Tuple<string, string>>() { headerBlobType };
-
- if (!string.IsNullOrEmpty(ContentType))
- {
- additionalHeaders.Add(new Tuple<string, string>(AzureHelper.ContentTypeString, ContentType));
- }
-
- var request = Utility.AzureHelper.RequestMessage("PUT", blobUrl, AccountName, AccountKey, additionalHeaders, Content);
-
- Utility.AzureHelper.RequestWithRetry(Log, client, request).GetAwaiter().GetResult();
- }
- catch (Exception e)
- {
- Log.LogErrorFromException(e, true);
- }
- }
-
- return !Log.HasLoggedErrors;
- }
-
- public static bool Execute(string accountName,
- string accountKey,
- string connectionString,
- string containerName,
- string blobName,
- string content,
- string contentType,
- IBuildEngine buildengine,
- ITaskHost taskHost)
- {
- PublishStringToAzureBlob publishStringToBlob = new PublishStringToAzureBlob()
- {
- AccountName = accountName,
- AccountKey = accountKey,
- ContainerName = containerName,
- BlobName = blobName,
- Content = content,
- ContentType = contentType,
- BuildEngine = buildengine,
- HostObject = taskHost
- };
- return publishStringToBlob.Execute();
- }
- }
-}
+++ /dev/null
-These tasks are candidates to be moved to BuildTools or are branched directly from BuildTools and refactored.
\ No newline at end of file
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using Microsoft.Build.Framework;
-using Microsoft.Build.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Net;
-using System.Net.Http;
-using System.Text;
-using System.Threading;
-using Task = System.Threading.Tasks.Task;
-
-namespace Microsoft.DotNet.Build.Tasks.Utility
-{
- public class UploadClient
- {
- private TaskLoggingHelper log;
-
- public UploadClient(TaskLoggingHelper loggingHelper)
- {
- log = loggingHelper;
- }
-
- public string EncodeBlockIds(int numberOfBlocks, int lengthOfId)
- {
- string numberOfBlocksString = numberOfBlocks.ToString("D" + lengthOfId);
- if (Encoding.UTF8.GetByteCount(numberOfBlocksString) <= 64)
- {
- byte[] bytes = Encoding.UTF8.GetBytes(numberOfBlocksString);
- return Convert.ToBase64String(bytes);
- }
- else
- {
- throw new Exception("Task failed - Could not encode block id.");
- }
- }
-
- public async Task UploadBlockBlobAsync(
- CancellationToken ct,
- string AccountName,
- string AccountKey,
- string ContainerName,
- string filePath,
- string destinationBlob)
- {
- string resourceUrl = string.Format("https://{0}.blob.core.windows.net/{1}", AccountName, ContainerName);
-
- string fileName = destinationBlob;
- fileName = fileName.Replace("\\", "/");
- string blobUploadUrl = resourceUrl + "/" + fileName;
- int size = (int)new FileInfo(filePath).Length;
- int blockSize = 4 * 1024 * 1024; //4MB max size of a block blob
- int bytesLeft = size;
- List<string> blockIds = new List<string>();
- int numberOfBlocks = (size / blockSize) + 1;
- int countForId = 0;
- using (FileStream fileStreamTofilePath = new FileStream(filePath, FileMode.Open))
- {
- int offset = 0;
-
- while (bytesLeft > 0)
- {
- int nextBytesToRead = (bytesLeft < blockSize) ? bytesLeft : blockSize;
- byte[] fileBytes = new byte[blockSize];
- int read = fileStreamTofilePath.Read(fileBytes, 0, nextBytesToRead);
-
- if (nextBytesToRead != read)
- {
- throw new Exception(string.Format(
- "Number of bytes read ({0}) from file {1} isn't equal to the number of bytes expected ({2}) .",
- read, fileName, nextBytesToRead));
- }
-
- string blockId = EncodeBlockIds(countForId, numberOfBlocks.ToString().Length);
-
- blockIds.Add(blockId);
- string blockUploadUrl = blobUploadUrl + "?comp=block&blockid=" + WebUtility.UrlEncode(blockId);
-
- using (HttpClient client = new HttpClient())
- {
- client.DefaultRequestHeaders.Clear();
- Func<HttpRequestMessage> createRequest = () =>
- {
- DateTime dt = DateTime.UtcNow;
- var req = new HttpRequestMessage(HttpMethod.Put, blockUploadUrl);
- req.Headers.Add(AzureHelper.DateHeaderString, dt.ToString("R", CultureInfo.InvariantCulture));
- req.Headers.Add(AzureHelper.VersionHeaderString, AzureHelper.StorageApiVersion);
- req.Headers.Add(
- AzureHelper.AuthorizationHeaderString,
- AzureHelper.AuthorizationHeader(
- AccountName,
- AccountKey,
- "PUT",
- dt,
- req,
- string.Empty,
- string.Empty,
- nextBytesToRead.ToString(),
- string.Empty));
-
- Stream postStream = new MemoryStream();
- postStream.Write(fileBytes, 0, nextBytesToRead);
- postStream.Seek(0, SeekOrigin.Begin);
- req.Content = new StreamContent(postStream);
- return req;
- };
-
- log.LogMessage(MessageImportance.Low, "Sending request to upload part {0} of file {1}", countForId, fileName);
-
- using (HttpResponseMessage response = await AzureHelper.RequestWithRetry(log, client, createRequest))
- {
- log.LogMessage(
- MessageImportance.Low,
- "Received response to upload part {0} of file {1}: Status Code:{2} Status Desc: {3}",
- countForId,
- fileName,
- response.StatusCode,
- await response.Content.ReadAsStringAsync());
- }
- }
-
- offset += read;
- bytesLeft -= nextBytesToRead;
- countForId += 1;
- }
- }
-
- string blockListUploadUrl = blobUploadUrl + "?comp=blocklist";
-
- using (HttpClient client = new HttpClient())
- {
- Func<HttpRequestMessage> createRequest = () =>
- {
- DateTime dt1 = DateTime.UtcNow;
- var req = new HttpRequestMessage(HttpMethod.Put, blockListUploadUrl);
- req.Headers.Add(AzureHelper.DateHeaderString, dt1.ToString("R", CultureInfo.InvariantCulture));
- req.Headers.Add(AzureHelper.VersionHeaderString, AzureHelper.StorageApiVersion);
- string contentType = DetermineContentTypeBasedOnFileExtension(filePath);
- if (!string.IsNullOrEmpty(contentType))
- {
- req.Headers.Add(AzureHelper.ContentTypeString, contentType);
- }
- string cacheControl = DetermineCacheControlBasedOnFileExtension(filePath);
- if (!string.IsNullOrEmpty(cacheControl))
- {
- req.Headers.Add(AzureHelper.CacheControlString, cacheControl);
- }
-
- var body = new StringBuilder("<?xml version=\"1.0\" encoding=\"UTF-8\"?><BlockList>");
- foreach (object item in blockIds)
- body.AppendFormat("<Latest>{0}</Latest>", item);
-
- body.Append("</BlockList>");
- byte[] bodyData = Encoding.UTF8.GetBytes(body.ToString());
- req.Headers.Add(
- AzureHelper.AuthorizationHeaderString,
- AzureHelper.AuthorizationHeader(
- AccountName,
- AccountKey,
- "PUT",
- dt1,
- req,
- string.Empty,
- string.Empty,
- bodyData.Length.ToString(),
- string.Empty));
- Stream postStream = new MemoryStream();
- postStream.Write(bodyData, 0, bodyData.Length);
- postStream.Seek(0, SeekOrigin.Begin);
- req.Content = new StreamContent(postStream);
- return req;
- };
-
- using (HttpResponseMessage response = await AzureHelper.RequestWithRetry(log, client, createRequest))
- {
- log.LogMessage(
- MessageImportance.Low,
- "Received response to combine block list for file {0}: Status Code:{1} Status Desc: {2}",
- fileName,
- response.StatusCode,
- await response.Content.ReadAsStringAsync());
- }
- }
- }
- private string DetermineContentTypeBasedOnFileExtension(string filename)
- {
- if(Path.GetExtension(filename) == ".svg")
- {
- return "image/svg+xml";
- }
- else if(Path.GetExtension(filename) == ".version")
- {
- return "text/plain";
- }
- return string.Empty;
- }
- private string DetermineCacheControlBasedOnFileExtension(string filename)
- {
- if(Path.GetExtension(filename) == ".svg")
- {
- return "No-Cache";
- }
- return string.Empty;
- }
- }
-}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using System.Xml;
-using System.Linq;
-using System.Net.Http;
-
-using Microsoft.Build.Framework;
-using ThreadingTask = System.Threading.Tasks.Task;
-
-namespace Microsoft.DotNet.Build.Tasks
-{
-
- public partial class UploadToAzure : Utility.AzureConnectionStringBuildTask
- {
- private static readonly CancellationTokenSource TokenSource = new CancellationTokenSource();
- private static readonly CancellationToken CancellationToken = TokenSource.Token;
-
- /// <summary>
- /// The name of the container to access. The specified name must be in the correct format, see the
- /// following page for more info. https://msdn.microsoft.com/en-us/library/azure/dd135715.aspx
- /// </summary>
- [Required]
- public string ContainerName { get; set; }
-
- /// <summary>
- /// An item group of files to upload. Each item must have metadata RelativeBlobPath
- /// that specifies the path relative to ContainerName where the item will be uploaded.
- /// </summary>
- [Required]
- public ITaskItem[] Items { get; set; }
-
- /// <summary>
- /// Indicates if the destination blob should be overwritten if it already exists. The default if false.
- /// </summary>
- public bool Overwrite { get; set; } = false;
-
- /// <summary>
- /// Specifies the maximum number of clients to concurrently upload blobs to azure
- /// </summary>
- public int MaxClients { get; set; } = 8;
-
- public void Cancel()
- {
- TokenSource.Cancel();
- }
-
- public override bool Execute()
- {
- return ExecuteAsync(CancellationToken).GetAwaiter().GetResult();
- }
-
- public async Task<bool> ExecuteAsync(CancellationToken ct)
- {
- ParseConnectionString();
- if (Log.HasLoggedErrors)
- {
- return false;
- }
-
- Log.LogMessage(
- MessageImportance.Normal,
- "Begin uploading blobs to Azure account {0} in container {1}.",
- AccountName,
- ContainerName);
-
- if (Items.Length == 0)
- {
- Log.LogError("No items were provided for upload.");
- return false;
- }
-
- // first check what blobs are present
- string checkListUrl = string.Format(
- "https://{0}.blob.core.windows.net/{1}?restype=container&comp=list",
- AccountName,
- ContainerName);
-
- HashSet<string> blobsPresent = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
-
- try
- {
- using (HttpClient client = new HttpClient())
- {
- Func<HttpRequestMessage> createRequest = () =>
- {
- DateTime dt = DateTime.UtcNow;
- var req = new HttpRequestMessage(HttpMethod.Get, checkListUrl);
- req.Headers.Add(Utility.AzureHelper.DateHeaderString, dt.ToString("R", CultureInfo.InvariantCulture));
- req.Headers.Add(Utility.AzureHelper.VersionHeaderString, Utility.AzureHelper.StorageApiVersion);
- req.Headers.Add(Utility.AzureHelper.AuthorizationHeaderString, Utility.AzureHelper.AuthorizationHeader(
- AccountName,
- AccountKey,
- "GET",
- dt,
- req));
- return req;
- };
-
- Log.LogMessage(MessageImportance.Low, "Sending request to check whether Container blobs exist");
- using (HttpResponseMessage response = await Utility.AzureHelper.RequestWithRetry(Log, client, createRequest))
- {
- var doc = new XmlDocument();
- doc.LoadXml(await response.Content.ReadAsStringAsync());
-
- XmlNodeList nodes = doc.DocumentElement.GetElementsByTagName("Blob");
-
- foreach (XmlNode node in nodes)
- {
- blobsPresent.Add(node["Name"].InnerText);
- }
-
- Log.LogMessage(MessageImportance.Low, "Received response to check whether Container blobs exist");
- }
- }
-
- using (var clientThrottle = new SemaphoreSlim(this.MaxClients, this.MaxClients))
- {
- await ThreadingTask.WhenAll(Items.Select(item => UploadAsync(ct, item, blobsPresent, clientThrottle)));
- }
-
- Log.LogMessage(MessageImportance.Normal, "Upload to Azure is complete, a total of {0} items were uploaded.", Items.Length);
- }
- catch (Exception e)
- {
- Log.LogErrorFromException(e, true);
- }
- return !Log.HasLoggedErrors;
- }
-
- private async ThreadingTask UploadAsync(CancellationToken ct, ITaskItem item, HashSet<string> blobsPresent, SemaphoreSlim clientThrottle)
- {
- if (ct.IsCancellationRequested)
- {
- Log.LogError("Task UploadToAzure cancelled");
- ct.ThrowIfCancellationRequested();
- }
-
- string relativeBlobPath = item.GetMetadata("RelativeBlobPath");
- if (string.IsNullOrEmpty(relativeBlobPath))
- throw new Exception(string.Format("Metadata 'RelativeBlobPath' is missing for item '{0}'.", item.ItemSpec));
-
- if (!File.Exists(item.ItemSpec))
- throw new Exception(string.Format("The file '{0}' does not exist.", item.ItemSpec));
-
- if (!Overwrite && blobsPresent.Contains(relativeBlobPath))
- throw new Exception(string.Format("The blob '{0}' already exists.", relativeBlobPath));
-
- await clientThrottle.WaitAsync();
-
- try
- {
- Log.LogMessage("Uploading {0} to {1}.", item.ItemSpec, ContainerName);
- Utility.UploadClient uploadClient = new Utility.UploadClient(Log);
- await
- uploadClient.UploadBlockBlobAsync(
- ct,
- AccountName,
- AccountKey,
- ContainerName,
- item.ItemSpec,
- relativeBlobPath);
- }
- finally
- {
- clientThrottle.Release();
- }
- }
- }
-}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System;
using Microsoft.Build.Framework;
+using Microsoft.DotNet.Build.CloudTestTasks;
+using System;
using System.IO;
using System.Collections.Generic;
using System.Text.RegularExpressions;
namespace Microsoft.DotNet.Build.Tasks
{
- public partial class FinalizeBuild : Utility.AzureConnectionStringBuildTask
+ public class FinalizeBuild : AzureConnectionStringBuildTask
{
[Required]
public string SemaphoreBlob { get; set; }
public string[] GetBlobList(string path)
{
- return GetAzureBlobList.Execute(AccountName,
+ return ListAzureBlobs.Execute(AccountName,
AccountKey,
ConnectionString,
ContainerName,
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<ItemGroup>
<Project Include="$(MSBuildThisFileDirectory)$(MSBuildProjectName).csproj">
- <AdditionalProperties>TargetGroup=netstandard1.5</AdditionalProperties>
+ <AdditionalProperties>TargetGroup=netstandard1.3</AdditionalProperties>
</Project>
<Project Include="$(MSBuildThisFileDirectory)$(MSBuildProjectName).csproj">
<AdditionalProperties>TargetGroup=net45</AdditionalProperties>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
<PropertyGroup>
<OutputType>Library</OutputType>
- <NuGetTargetMoniker>.NETStandard,Version=v1.5</NuGetTargetMoniker>
- <NuGetTargetMonikerShort>netstandard1.5</NuGetTargetMonikerShort>
+ <NuGetTargetMoniker>.NETStandard,Version=v1.3</NuGetTargetMoniker>
+ <NuGetTargetMonikerShort>netstandard1.3</NuGetTargetMonikerShort>
<NuGetTargetMoniker Condition="'$(TargetGroup)' == 'net45'">.NETFramework,Version=v4.5.1</NuGetTargetMoniker>
<NuGetTargetMonikerShort Condition="'$(TargetGroup)' == 'net45'">net451</NuGetTargetMonikerShort>
<CLSCompliant>false</CLSCompliant>
<SkipSigning>true</SkipSigning>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
- <PropertyGroup Condition="'$(Configuration)' == 'netstandard1.5_Debug'" />
+ <PropertyGroup Condition="'$(Configuration)' == 'netstandard1.3_Debug'" />
<PropertyGroup Condition="'$(Configuration)' == 'net45_Debug'" />
<ItemGroup>
<Compile Include="*.cs" />
</ItemGroup>
<ItemGroup Condition="'$(TargetGroup)' != 'net45'">
<Compile Include="netstandard/FileUtilities.netstandard.cs" />
+
+ <Reference Include="$(BuildToolsTaskCoreDir)Microsoft.DotNet.Build.CloudTestTasks.dll" />
+
<PackageReference Include="Microsoft.Build">
<Version>0.1.0-preview-00022</Version>
</PackageReference>
<ItemGroup Condition="'$(TargetGroup)' == 'net45'">
<Compile Include="net45/FileUtilities.net45.cs" />
<Compile Include="net45/ProcessSharedFrameworkDeps.net45.cs" />
+
+ <Reference Include="$(BuildToolsTaskDesktopDir)Microsoft.DotNet.Build.CloudTestTasks.dll" />
+
<PackageReference Include="Microsoft.TargetingPack.NETFramework.v4.5.1">
<Version>1.0.1</Version>
</PackageReference>
<TargetingPackReference Include="Microsoft.Build.Framework" />
<TargetingPackReference Include="Microsoft.Build.Utilities.v4.0" />
</ItemGroup>
- <ItemGroup>
- <ProjectReference Include="..\Microsoft.DotNet.Build.Tasks.Local\Microsoft.DotNet.Build.Tasks.Local.csproj">
- <Project>{b507bed2-0a28-456a-99c6-ad7aa148e35f}</Project>
- <Name>Microsoft.DotNet.Build.Tasks.Local</Name>
- </ProjectReference>
- </ItemGroup>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
</Project>