private async Task PublishBlobsToAzureStorageNugetFeedAsync( List <BlobArtifactModel> blobsToPublish, IMaestroApi client, Maestro.Client.Models.Build buildInformation, FeedConfig feedConfig) { BlobAssetsBasePath = BlobAssetsBasePath.TrimEnd( Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; var blobs = blobsToPublish .Select(blob => { var fileName = Path.GetFileName(blob.Id); return(new MSBuild.TaskItem($"{BlobAssetsBasePath}{fileName}", new Dictionary <string, string> { { "RelativeBlobPath", blob.Id } })); }) .ToArray(); var blobFeedAction = new BlobFeedAction(feedConfig.TargetFeedURL, feedConfig.FeedKey, Log); var pushOptions = new PushOptions { AllowOverwrite = false, PassIfExistingItemIdentical = true }; foreach (var blob in blobsToPublish) { var assetRecord = buildInformation.Assets .Where(a => a.Name.Equals(blob.Id)) .SingleOrDefault(); if (assetRecord == null) { Log.LogError($"Asset with Id {blob.Id} isn't registered on the BAR Build with ID {BARBuildId}"); continue; } var assetWithLocations = await client.Assets.GetAssetAsync(assetRecord.Id); if (assetWithLocations?.Locations.Any(al => al.Location.Equals(feedConfig.TargetFeedURL, StringComparison.OrdinalIgnoreCase)) ?? false) { Log.LogMessage($"Asset with Id {blob.Id} already has location {feedConfig.TargetFeedURL}"); continue; } await client.Assets.AddAssetLocationToAssetAsync(assetRecord.Id, AddAssetLocationToAssetAssetLocationType.Container, feedConfig.TargetFeedURL); } await blobFeedAction.PublishToFlatContainerAsync(blobs, maxClients : 8, pushOptions); }
private async Task PublishPackagesToAzureStorageNugetFeedAsync( List <PackageArtifactModel> packagesToPublish, IMaestroApi client, Maestro.Client.Models.Build buildInformation, FeedConfig feedConfig) { PackageAssetsBasePath = PackageAssetsBasePath.TrimEnd( Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; var packages = packagesToPublish.Select(p => $"{PackageAssetsBasePath}{p.Id}.{p.Version}.nupkg"); var blobFeedAction = new BlobFeedAction(feedConfig.TargetFeedURL, feedConfig.FeedKey, Log); var pushOptions = new PushOptions { AllowOverwrite = false, PassIfExistingItemIdentical = true }; foreach (var package in packagesToPublish) { var assetRecord = buildInformation.Assets .Where(a => a.Name.Equals(package.Id) && a.Version.Equals(package.Version)) .FirstOrDefault(); if (assetRecord == null) { Log.LogError($"Asset with Id {package.Id}, Version {package.Version} isn't registered on the BAR Build with ID {BARBuildId}"); continue; } var assetWithLocations = await client.Assets.GetAssetAsync(assetRecord.Id); if (assetWithLocations?.Locations.Any(al => al.Location.Equals(feedConfig.TargetFeedURL, StringComparison.OrdinalIgnoreCase)) ?? false) { Log.LogMessage($"Asset with Id {package.Id}, Version {package.Version} already has location {feedConfig.TargetFeedURL}"); continue; } await client.Assets.AddAssetLocationToAssetAsync(assetRecord.Id, AddAssetLocationToAssetAssetLocationType.NugetFeed, feedConfig.TargetFeedURL); } await blobFeedAction.PushToFeedAsync(packages, pushOptions); }
public virtual IAssetPublisher CreateAssetPublisher(TargetFeedConfig feedConfig, PublishArtifactsInManifestBase task) { switch (feedConfig.Type) { case FeedType.AzDoNugetFeed: return(new AzureDevOpsNugetFeedAssetPublisher(_log, feedConfig.TargetURL, feedConfig.Token, task)); case FeedType.AzureStorageFeed: var action = new BlobFeedAction(feedConfig.TargetURL, feedConfig.Token, _log); return(new AzureStorageFeedAssetPublisher(action.AccountName, action.AccountKey, action.ContainerName, _log)); case FeedType.AzureStorageContainer: return(new AzureStorageContainerAssetPublisher(new Uri(feedConfig.TargetURL), _log)); default: throw new NotImplementedException(); } }
private async Task <bool> ExecuteAsync() { try { Log.LogMessage(MessageImportance.High, "Listing blob feed packages..."); BlobFeedAction action = new BlobFeedAction(ExpectedFeedUrl, AccountKey, Log); ISet <PackageIdentity> packages = await action.GetPackageIdentitiesAsync(); PackageInfos = packages.Select(ConvertToPackageInfoItem).ToArray(); } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
public async Task <bool> ExecuteAsync() { Debugger.Launch(); try { Log.LogMessage(MessageImportance.High, "Performing feed push..."); if (ItemsToPush == null) { Log.LogError($"No items to push. Please check ItemGroup ItemsToPush."); } if (string.IsNullOrEmpty(RelativePath)) { Log.LogWarning($"No relative path. Items are pushed to root of container."); } BlobFeedAction blobFeedAction = new BlobFeedAction(AccountName, AccountKey, ContainerName, IndexDirectory, Log); bool containerExists = await blobFeedAction.feed.CheckIfFeedExists(); if (!containerExists) { await blobFeedAction.feed.CreateFeedContainer(RelativePath); } if (!PublishFlatContainer) { if (!containerExists) { await blobFeedAction.PushToFeed(ConvertToStringLists(ItemsToPush), RelativePath); } else { await blobFeedAction.PushToFeed(ConvertToStringLists(ItemsToPush), RelativePath, Overwrite); } } else { await blobFeedAction.PushToFeedFlat(ConvertToStringLists(ItemsToPush), RelativePath, Overwrite); } } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
public async Task <bool> ExecuteAsync() { try { Log.LogMessage(MessageImportance.High, "Performing feed push..."); if (ItemsToPush == null) { Log.LogError($"No items to push. Please check ItemGroup ItemsToPush."); } else { BlobFeedAction blobFeedAction = new BlobFeedAction(ExpectedFeedUrl, AccountKey, Log); if (!SkipCreateContainer) { await blobFeedAction.CreateContainerAsync(this.BuildEngine); } List <string> items = ConvertToStringLists(ItemsToPush); if (!PublishFlatContainer) { await blobFeedAction.PushToFeed(items, Overwrite); } else { using (var clientThrottle = new SemaphoreSlim(this.MaxClients, this.MaxClients)) { Log.LogMessage($"Uploading {ItemsToPush.Length} items..."); await Task.WhenAll(ItemsToPush.Select(item => blobFeedAction.UploadAssets(item, clientThrottle, Overwrite))); } } } } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
public async Task <bool> ExecuteAsync() { try { Log.LogMessage(MessageImportance.High, "Performing feed push..."); if (ItemsToPush == null) { Log.LogError($"No items to push. Please check ItemGroup ItemsToPush."); } BlobFeedAction blobFeedAction = new BlobFeedAction(ExpectedFeedUrl, AccountKey, IndexDirectory, Log); bool containerExists = await blobFeedAction.feed.CheckIfFeedExists(); if (!containerExists) { await blobFeedAction.feed.CreateFeedContainer(); } if (!PublishFlatContainer) { if (!containerExists) { await blobFeedAction.PushToFeed(ConvertToStringLists(ItemsToPush)); } else { await blobFeedAction.PushToFeed(ConvertToStringLists(ItemsToPush), Overwrite); } } else { await blobFeedAction.PushToFeedFlat(ConvertToStringLists(ItemsToPush), Overwrite); } } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
public async Task <bool> ExecuteAsync() { try { Log.LogMessage(MessageImportance.High, "Performing push feeds."); if (string.IsNullOrWhiteSpace(ExpectedFeedUrl) || string.IsNullOrWhiteSpace(AccountKey)) { Log.LogError($"{nameof(ExpectedFeedUrl)} / {nameof(AccountKey)} is not set properly."); } else if (string.IsNullOrWhiteSpace(AssetManifestPath) || !File.Exists(AssetManifestPath)) { Log.LogError($"Problem reading asset manifest path from {AssetManifestPath}"); } else if (MaxClients <= 0) { Log.LogError($"{nameof(MaxClients)} should be greater than zero."); } else if (UploadTimeoutInMinutes <= 0) { Log.LogError($"{nameof(UploadTimeoutInMinutes)} should be greater than zero."); } var buildModel = BuildManifestUtil.ManifestFileToModel(AssetManifestPath, Log); // Parsing the manifest may fail for several reasons if (Log.HasLoggedErrors) { return(false); } // Fetch Maestro record of the build. We're going to use it to get the BAR ID // of the assets being published so we can add a new location for them. IMaestroApi client = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken); Maestro.Client.Models.Build buildInformation = await client.Builds.GetBuildAsync(BARBuildId); var blobFeedAction = new BlobFeedAction(ExpectedFeedUrl, AccountKey, Log); var pushOptions = new PushOptions { AllowOverwrite = Overwrite, PassIfExistingItemIdentical = PassIfExistingItemIdentical }; if (buildModel.Artifacts.Packages.Any()) { if (!Directory.Exists(PackageAssetsBasePath)) { Log.LogError($"Invalid {nameof(PackageAssetsBasePath)} was supplied: {PackageAssetsBasePath}"); return(false); } PackageAssetsBasePath = PackageAssetsBasePath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; var packages = buildModel.Artifacts.Packages.Select(p => $"{PackageAssetsBasePath}{p.Id}.{p.Version}.nupkg"); await blobFeedAction.PushToFeedAsync(packages, pushOptions); foreach (var package in buildModel.Artifacts.Packages) { var assetRecord = buildInformation.Assets .Where(a => a.Name.Equals(package.Id) && a.Version.Equals(package.Version)) .Single(); if (assetRecord == null) { Log.LogError($"Asset with Id {package.Id}, Version {package.Version} isn't registered on the BAR Build with ID {BARBuildId}"); continue; } await client.Assets.AddAssetLocationToAssetAsync(assetRecord.Id.Value, ExpectedFeedUrl, "NugetFeed"); } } if (buildModel.Artifacts.Blobs.Any()) { if (!Directory.Exists(BlobAssetsBasePath)) { Log.LogError($"Invalid {nameof(BlobAssetsBasePath)} was supplied: {BlobAssetsBasePath}"); return(false); } BlobAssetsBasePath = BlobAssetsBasePath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; var blobs = buildModel.Artifacts.Blobs .Select(blob => { var fileName = Path.GetFileName(blob.Id); return(new MSBuild.TaskItem($"{BlobAssetsBasePath}{fileName}", new Dictionary <string, string> { { "RelativeBlobPath", $"{BuildManifestUtil.AssetsVirtualDir}{blob.Id}" } })); }) .ToArray(); await blobFeedAction.PublishToFlatContainerAsync(blobs, MaxClients, UploadTimeoutInMinutes, pushOptions); foreach (var package in buildModel.Artifacts.Blobs) { var assetRecord = buildInformation.Assets .Where(a => a.Name.Equals(package.Id)) .SingleOrDefault(); if (assetRecord == null) { Log.LogError($"Asset with Id {package.Id} isn't registered on the BAR Build with ID {BARBuildId}"); continue; } await client.Assets.AddAssetLocationToAssetAsync(assetRecord.Id.Value, ExpectedFeedUrl, "NugetFeed"); } } } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
private async Task <bool> ExecuteAsync() { try { string accessId = IsInternal ? "int" : "pub"; string baseFeedName = $"darc-{accessId}-{RepositoryName}-{CommitSha}"; string versionedFeedName = baseFeedName; bool needsUniqueName = false; int subVersion = 0; var containerName = string.Empty; Log.LogMessage(MessageImportance.High, $"Creating a new Azure Storage internal feed ..."); Match m = Regex.Match(AzureStorageFeedsBaseUrl, baseUrlRegex); if (m.Success) { containerName = m.Groups["containername"].Value; } else { Log.LogError($"Could not parse {nameof(AzureStorageFeedsBaseUrl)} to extract the container name: '{AzureStorageFeedsBaseUrl}'"); return(false); } AzureStorageUtils azUtils = new AzureStorageUtils(AzureStorageAccountName, AzureStorageAccountKey, containerName); // Create container if it doesn't already exist if (!await azUtils.CheckIfContainerExistsAsync()) { BlobContainerPermissions permissions = new BlobContainerPermissions { PublicAccess = IsInternal ? BlobContainerPublicAccessType.Off : BlobContainerPublicAccessType.Container }; await azUtils.CreateContainerAsync(permissions); } // Create folder inside the container. Note that AzureStorage requires a folder // to have at least one file. do { if (await azUtils.CheckIfBlobExistsAsync($"{versionedFeedName}/index.json")) { versionedFeedName = $"{baseFeedName}-{++subVersion}"; needsUniqueName = true; } else { baseFeedName = versionedFeedName; needsUniqueName = false; } } while (needsUniqueName); // Initialize the feed using sleet SleetSource sleetSource = new SleetSource() { Name = baseFeedName, Type = "azure", BaseUri = $"{AzureStorageFeedsBaseUrl}{baseFeedName}", AccountName = AzureStorageAccountName, Container = containerName, FeedSubPath = $"{baseFeedName}", ConnectionString = $"DefaultEndpointsProtocol=https;AccountName={AzureStorageAccountName};AccountKey={AzureStorageAccountKey};EndpointSuffix=core.windows.net" }; BlobFeedAction bfAction = new BlobFeedAction(sleetSource, AzureStorageAccountKey, Log); await bfAction.InitAsync(); TargetFeedURL = $"{AzureStorageFeedsBaseUrl}{baseFeedName}"; Log.LogMessage(MessageImportance.High, $"Feed '{TargetFeedURL}' created successfully!"); } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
private async Task <bool> ExecuteAsync() { try { Log.LogMessage(MessageImportance.High, "Performing feed push..."); if (ItemsToPush == null) { Log.LogError($"No items to push. Please check ItemGroup ItemsToPush."); } else if (string.IsNullOrWhiteSpace(ExpectedFeedUrl) || string.IsNullOrWhiteSpace(AccountKey)) { Log.LogError($"{nameof(ExpectedFeedUrl)} / {nameof(AccountKey)} is not set properly."); } else if (string.IsNullOrWhiteSpace(AssetManifestPath)) { Log.LogError($"{nameof(AssetManifestPath)} is not set properly."); } else if (MaxClients <= 0) { Log.LogError($"{nameof(MaxClients)} should be greater than zero."); } else if (UploadTimeoutInMinutes <= 0) { Log.LogError($"{nameof(UploadTimeoutInMinutes)} should be greater than zero."); } if (Log.HasLoggedErrors) { return(false); } BlobFeedAction blobFeedAction = new BlobFeedAction(ExpectedFeedUrl, AccountKey, Log); var pushOptions = new PushOptions { AllowOverwrite = Overwrite, PassIfExistingItemIdentical = PassIfExistingItemIdentical }; IEnumerable <BlobArtifactModel> blobArtifacts = Enumerable.Empty <BlobArtifactModel>(); IEnumerable <PackageArtifactModel> packageArtifacts = Enumerable.Empty <PackageArtifactModel>(); if (!SkipCreateContainer) { await blobFeedAction.CreateContainerAsync(BuildEngine, PublishFlatContainer); } if (PublishFlatContainer) { await blobFeedAction.PublishToFlatContainerAsync(ItemsToPush, MaxClients, pushOptions); blobArtifacts = ConcatBlobArtifacts(blobArtifacts, ItemsToPush); } else { ITaskItem[] symbolItems = ItemsToPush .Where(i => i.ItemSpec.Contains("symbols.nupkg")) .Select(i => { string fileName = Path.GetFileName(i.ItemSpec); i.SetMetadata("RelativeBlobPath", $"{BuildManifestUtil.AssetsVirtualDir}symbols/{fileName}"); return(i); }) .ToArray(); ITaskItem[] packageItems = ItemsToPush .Where(i => !symbolItems.Contains(i)) .ToArray(); var packagePaths = packageItems.Select(i => i.ItemSpec); if (!blobFeedAction.PushToFeedAsync(packagePaths, pushOptions).Result) { return(!Log.HasLoggedErrors); } await blobFeedAction.PublishToFlatContainerAsync(symbolItems, MaxClients, pushOptions); if (Log.HasLoggedErrors) { return(!Log.HasLoggedErrors); } packageArtifacts = ConcatPackageArtifacts(packageArtifacts, packageItems); blobArtifacts = ConcatBlobArtifacts(blobArtifacts, symbolItems); } if (!BuildManifestUtil.ManifestBuildDataHasLocationInformation(ManifestBuildData)) { string[] locationAttribute = new string[] { $"Location={ExpectedFeedUrl}" }; ManifestBuildData = ManifestBuildData == null ? locationAttribute : ManifestBuildData.Concat(locationAttribute).ToArray(); } BuildManifestUtil.CreateBuildManifest(Log, blobArtifacts, packageArtifacts, AssetManifestPath, ManifestRepoUri, ManifestBuildId, ManifestBranch, ManifestCommit, ManifestBuildData, IsStableBuild, PublishingInfraVersion.Legacy, IsReleaseOnlyPackageVersion); } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
public async Task <bool> ExecuteAsync() { try { Log.LogMessage(MessageImportance.High, "Performing feed push..."); if (ItemsToPush == null) { Log.LogError($"No items to push. Please check ItemGroup ItemsToPush."); } else { BlobFeedAction blobFeedAction = new BlobFeedAction(ExpectedFeedUrl, AccountKey, Log); IEnumerable <BlobArtifactModel> blobArtifacts = Enumerable.Empty <BlobArtifactModel>(); IEnumerable <PackageArtifactModel> packageArtifacts = Enumerable.Empty <PackageArtifactModel>(); if (!SkipCreateContainer) { await blobFeedAction.CreateContainerAsync(BuildEngine, PublishFlatContainer); } if (PublishFlatContainer) { await PublishToFlatContainerAsync(ItemsToPush, blobFeedAction); blobArtifacts = ConcatBlobArtifacts(blobArtifacts, ItemsToPush); } else { var symbolItems = ItemsToPush.Where(i => i.ItemSpec.Contains("symbols.nupkg")).Select(i => { string fileName = Path.GetFileName(i.ItemSpec); i.SetMetadata("RelativeBlobPath", $"symbols/{fileName}"); return(i); }).ToArray(); ITaskItem[] packageItems = ItemsToPush .Where(i => !symbolItems.Contains(i)) .ToArray(); var packagePaths = packageItems.Select(i => i.ItemSpec); await blobFeedAction.PushToFeed(packagePaths, Overwrite); await PublishToFlatContainerAsync(symbolItems, blobFeedAction); packageArtifacts = ConcatPackageArtifacts(packageArtifacts, packageItems); blobArtifacts = ConcatBlobArtifacts(blobArtifacts, symbolItems); } if (!SkipCreateManifest) { await PushBuildManifestAsync(blobFeedAction, blobArtifacts, packageArtifacts); } } } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }
private async Task PublishToFlatContainerAsync(IEnumerable <ITaskItem> taskItems, BlobFeedAction blobFeedAction) { if (taskItems.Any()) { using (var clientThrottle = new SemaphoreSlim(this.MaxClients, this.MaxClients)) { Log.LogMessage($"Uploading {taskItems.Count()} items..."); await Task.WhenAll(taskItems.Select(item => blobFeedAction.UploadAssets(item, clientThrottle, UploadTimeoutInMinutes, Overwrite))); } } }
private async Task PushBuildManifestAsync( BlobFeedAction blobFeedAction, IEnumerable <BlobArtifactModel> blobArtifacts, IEnumerable <PackageArtifactModel> packageArtifacts) { bool disabledByBlob = await blobFeedAction.feed.CheckIfBlobExists( $"{blobFeedAction.feed.RelativePath}{DisableManifestPushConfigurationBlob}"); if (disabledByBlob) { Log.LogMessage( MessageImportance.Normal, $"Skipping manifest push: feed has '{DisableManifestPushConfigurationBlob}'."); return; } string blobPath = $"{AssetsVirtualDir}{ManifestAssetOutputDir}{ManifestName}.xml"; string existingStr = await blobFeedAction.feed.DownloadBlobAsString( $"{blobFeedAction.feed.RelativePath}{blobPath}"); BuildModel buildModel; if (existingStr != null) { buildModel = BuildModel.Parse(XElement.Parse(existingStr)); } else { buildModel = new BuildModel( new BuildIdentity( ManifestName, ManifestBuildId, ManifestBranch, ManifestCommit)); } buildModel.Artifacts.Blobs.AddRange(blobArtifacts); buildModel.Artifacts.Packages.AddRange(packageArtifacts); string tempFile = null; try { tempFile = Path.GetTempFileName(); File.WriteAllText(tempFile, buildModel.ToXml().ToString()); var item = new MSBuild.TaskItem(tempFile, new Dictionary <string, string> { ["RelativeBlobPath"] = blobPath }); using (var clientThrottle = new SemaphoreSlim(MaxClients, MaxClients)) { await blobFeedAction.UploadAssets( item, clientThrottle, UploadTimeoutInMinutes, allowOverwrite : true); } } finally { if (tempFile != null) { File.Delete(tempFile); } } }
private async Task PublishToFlatContainerAsync(IEnumerable <ITaskItem> taskItems, BlobFeedAction blobFeedAction) { if (taskItems.Any()) { using (var clientThrottle = new SemaphoreSlim(this.MaxClients, this.MaxClients)) { Log.LogMessage(MessageImportance.High, $"Uploading {taskItems.Count()} items:"); await Task.WhenAll(taskItems.Select( item => { Log.LogMessage(MessageImportance.High, $"Async uploading {item.ItemSpec}"); return(blobFeedAction.UploadAssetAsync( item, clientThrottle, UploadTimeoutInMinutes, CreatePushOptions())); } )); } } }
public async Task <bool> ExecuteAsync() { try { Log.LogMessage(MessageImportance.High, "Performing push feeds."); if (string.IsNullOrWhiteSpace(ExpectedFeedUrl) || string.IsNullOrWhiteSpace(AccountKey)) { Log.LogError($"{nameof(ExpectedFeedUrl)} / {nameof(AccountKey)} is not set properly."); } else if (string.IsNullOrWhiteSpace(AssetManifestPath) || !File.Exists(AssetManifestPath)) { Log.LogError($"Problem reading asset manifest path from {AssetManifestPath}"); } else if (MaxClients <= 0) { Log.LogError($"{nameof(MaxClients)} should be greater than zero."); } else if (UploadTimeoutInMinutes <= 0) { Log.LogError($"{nameof(UploadTimeoutInMinutes)} should be greater than zero."); } var buildModel = BuildManifestUtil.ManifestFileToModel(AssetManifestPath, Log); // Parsing the manifest may fail for several reasons if (Log.HasLoggedErrors) { return(false); } var blobFeedAction = new BlobFeedAction(ExpectedFeedUrl, AccountKey, Log); var pushOptions = new PushOptions { AllowOverwrite = Overwrite, PassIfExistingItemIdentical = PassIfExistingItemIdentical }; if (buildModel.Artifacts.Packages.Any()) { if (!Directory.Exists(PackageAssetsBasePath)) { Log.LogError($"Invalid {nameof(PackageAssetsBasePath)} was supplied: {PackageAssetsBasePath}"); return(false); } PackageAssetsBasePath = PackageAssetsBasePath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; var packages = buildModel.Artifacts.Packages.Select(p => $"{PackageAssetsBasePath}{p.Id}.{p.Version}.nupkg"); await blobFeedAction.PushToFeedAsync(packages, pushOptions); } if (buildModel.Artifacts.Blobs.Any()) { if (!Directory.Exists(BlobAssetsBasePath)) { Log.LogError($"Invalid {nameof(BlobAssetsBasePath)} was supplied: {BlobAssetsBasePath}"); return(false); } BlobAssetsBasePath = BlobAssetsBasePath.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + Path.DirectorySeparatorChar; var blobs = buildModel.Artifacts.Blobs .Select(blob => { var fileName = Path.GetFileName(blob.Id); return(new MSBuild.TaskItem($"{BlobAssetsBasePath}{fileName}", new Dictionary <string, string> { { "RelativeBlobPath", $"{BuildManifestUtil.AssetsVirtualDir}{blob.Id}" } })); }) .ToArray(); await blobFeedAction.PublishToFlatContainerAsync(blobs, MaxClients, UploadTimeoutInMinutes, pushOptions); } } catch (Exception e) { Log.LogErrorFromException(e, true); } return(!Log.HasLoggedErrors); }