/// <summary> /// Given a downloaded build, determine what the product name should be /// for the release json /// </summary> /// <param name="build">Downloaded build</param> /// <returns>Product name</returns> private string GetProductNameForReleaseJson(DownloadedBuild build) { // Preference the github repo name over the azure devops repo name. if (!string.IsNullOrEmpty(build.Build.GitHubRepository)) { // Split off the github.com+org name and just use the repo name, all lower case. (string owner, string repo) = GitHubClient.ParseRepoUri(build.Build.GitHubRepository); return(repo.ToLowerInvariant()); } else if (!string.IsNullOrEmpty(build.Build.AzureDevOpsRepository)) { // Use the full repo name without project/account (string accountName, string projectName, string repoName) = AzureDevOpsClient.ParseRepoUri(build.Build.AzureDevOpsRepository); return(repoName.ToLowerInvariant()); } else { throw new NotImplementedException("Unknown repository name."); } }
public override async Task <int> ExecuteAsync() { try { // Formalize the directory path. string rootOutputPath = Path.GetFullPath(_options.OutputDirectory); bool success = true; // Gather the list of builds that need to be downloaded. InputBuilds buildsToDownload = await GatherBuildsToDownloadAsync(); if (!buildsToDownload.Successful) { success = false; if (!_options.ContinueOnError) { return(Constants.ErrorCode); } } Console.WriteLine(); List <DownloadedBuild> downloadedBuilds = new List <DownloadedBuild>(); foreach (var build in buildsToDownload.Builds) { DownloadedBuild downloadedBuild = await GatherDropForBuildAsync(build, rootOutputPath); if (!downloadedBuild.Successful) { success = false; Console.WriteLine($"Failed to download build with id {build.Id}"); if (!_options.ContinueOnError) { return(Constants.ErrorCode); } } downloadedBuilds.Add(downloadedBuild); } // Write the unified drop manifest await WriteDropManifest(downloadedBuilds, _options.OutputDirectory); // Write the release json await WriteReleaseJson(downloadedBuilds, _options.OutputDirectory); Console.WriteLine(); if (!success) { Console.WriteLine("One or more failures attempting to download the drop, please see output."); return(Constants.ErrorCode); } else { Console.WriteLine("Download successful."); return(Constants.SuccessCode); } } catch (Exception e) { Logger.LogError(e, "Error: Failed to gather drop."); return(Constants.ErrorCode); } }
/// <summary> /// Gather the drop for a specific build. /// </summary> /// <param name="build">Build to gather drop for</param> /// <param name="rootOutputDirectory">Output directory. Must exist.</param> private async Task <DownloadedBuild> GatherDropForBuildAsync(Build build, string rootOutputDirectory) { IRemote remote = RemoteFactory.GetBarOnlyRemote(_options, Logger); bool success = true; // If the drop is separated, calculate the directory name based on the last element of the build // repo uri plus the build number (to disambiguate overlapping builds) string outputDirectory = rootOutputDirectory; string repoUri = build.GitHubRepository ?? build.AzureDevOpsRepository; if (_options.ReleaseLayout) { int lastSlash = repoUri.LastIndexOf("/"); if (lastSlash != -1 && lastSlash != repoUri.Length - 1) { outputDirectory = Path.Combine(rootOutputDirectory, repoUri.Substring(lastSlash + 1), build.AzureDevOpsBuildNumber); } else { // Might contain invalid path chars, this is currently unhandled. outputDirectory = Path.Combine(rootOutputDirectory, repoUri, build.AzureDevOpsBuildNumber); } Directory.CreateDirectory(outputDirectory); } List <DownloadedAsset> downloadedAssets = new List <DownloadedAsset>(); bool anyShipping = false; Console.WriteLine($"Gathering drop for build {build.AzureDevOpsBuildNumber} of {repoUri}"); using (HttpClient client = new HttpClient(new HttpClientHandler { CheckCertificateRevocationList = true })) { var assets = await remote.GetAssetsAsync(buildId : build.Id, nonShipping : (!_options.IncludeNonShipping ? (bool?)false : null)); foreach (var asset in assets) { DownloadedAsset downloadedAsset = await DownloadAssetAsync(client, build, asset, outputDirectory); if (downloadedAsset == null) { continue; } else if (!downloadedAsset.Successful) { success = false; if (!_options.ContinueOnError) { Console.WriteLine($"Aborting download."); break; } } else { anyShipping |= !asset.NonShipping; downloadedAssets.Add(downloadedAsset); } } } DownloadedBuild newBuild = new DownloadedBuild { Successful = success, Build = build, DownloadedAssets = downloadedAssets, OutputDirectory = outputDirectory, AnyShippingAssets = anyShipping }; // If separated drop, generate a manifest per build if (_options.ReleaseLayout) { await WriteDropManifest(new List <DownloadedBuild>() { newBuild }, outputDirectory); } return(newBuild); }
/// <summary> /// Given a downloaded build, determine what the fileshare location should be. /// </summary> /// <param name="build">Downloaded build</param> /// <returns>File share location</returns> public string GetFileShareLocationForReleaseJson(DownloadedBuild build) { // We only want to have shipping assets in the release json, so append that path return(Path.Combine(build.OutputDirectory, shippingSubPath)); }