public async Task <bool> PushMetadataAsync()
        {
            try
            {
                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    List <BuildData> buildsManifestMetadata = GetBuildManifestsMetadata(ManifestsPath);

                    BuildData finalBuild = MergeBuildManifests(buildsManifestMetadata);

                    IMaestroApi         client        = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);
                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(finalBuild, s_cancellationToken);

                    Log.LogMessage(MessageImportance.High, $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true);
            }

            return(!Log.HasLoggedErrors);
        }
        public async Task <bool> PushMetadataAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    List <BuildData> buildsManifestMetadata = GetBuildManifestsMetadata(ManifestsPath, cancellationToken);

                    BuildData finalBuild = MergeBuildManifests(buildsManifestMetadata);

                    IMaestroApi client = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                    var deps = await GetBuildDependenciesAsync(client, cancellationToken);

                    Log.LogMessage(MessageImportance.High, "Calculated Dependencies:");
                    foreach (var dep in deps)
                    {
                        Log.LogMessage(MessageImportance.High, $"    {dep.BuildId}, IsProduct: {dep.IsProduct}");
                    }
                    finalBuild.Dependencies = deps;

                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(finalBuild, cancellationToken);

                    Log.LogMessage(MessageImportance.High, $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");

                    // Only 'create' the AzDO (VSO) variables if running in an AzDO build
                    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_BUILDID")))
                    {
                        var defaultChannels = await client.DefaultChannels.ListAsync(
                            recordedBuild.GitHubBranch ?? recordedBuild.AzureDevOpsBranch,
                            channelId : null,
                            enabled : true,
                            recordedBuild.GitHubRepository ?? recordedBuild.AzureDevOpsRepository);

                        var defaultChannelsStr = "[" + string.Join("][", defaultChannels.Select(x => x.Channel.Id)) + "]";

                        Console.WriteLine($"##vso[task.setvariable variable=BARBuildId]{recordedBuild.Id}");
                        Console.WriteLine($"##vso[task.setvariable variable=DefaultChannels]{defaultChannelsStr}");
                        Console.WriteLine($"##vso[task.setvariable variable=IsStableBuild]{IsStableBuild}");
                    }
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
        public async Task <bool> PushMetadataAsync()
        {
            try
            {
                Log.LogMessage("Starting build metadata push to the Build Asset Registry...");

                if (!File.Exists(ManifestZipFilePath))
                {
                    Log.LogError($"Required file '{ManifestZipFilePath}' does not exist.");
                }
                else
                {
                    string tmpManifestsPath = null;

                    try
                    {
                        tmpManifestsPath = $"{Path.GetTempPath()}\asset-manifests";

                        if (!Directory.Exists(tmpManifestsPath))
                        {
                            Directory.Delete(tmpManifestsPath, true);
                        }

                        Directory.CreateDirectory(tmpManifestsPath);

                        ZipFile.ExtractToDirectory(ManifestZipFilePath, tmpManifestsPath);

                        List <BuildData> buildsManifestMetadata = GetBuildManifestsMetadata(tmpManifestsPath);

                        BuildData finalBuild = MergeBuildManifests(buildsManifestMetadata);

                        MaestroApi client = (MaestroApi)ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                        Builds buildAssetRegistryBuilds = new Builds(client);

                        Client.Models.Build recordedBuild = await buildAssetRegistryBuilds.CreateAsync(finalBuild, s_cancellationToken);

                        Log.LogMessage($"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                    }
                    finally
                    {
                        if (tmpManifestsPath != null)
                        {
                            Directory.Delete(tmpManifestsPath, true);
                        }
                    }
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true);
            }

            return(!Log.HasLoggedErrors);
        }
        public async Task <bool> PushMetadataAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    List <BuildData> buildsManifestMetadata = GetBuildManifestsMetadata(ManifestsPath, cancellationToken);

                    BuildData finalBuild = MergeBuildManifests(buildsManifestMetadata);

                    IMaestroApi client = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                    var deps = await GetBuildDependenciesAsync(client, cancellationToken);

                    Log.LogMessage(MessageImportance.High, "Calculated Dependencies:");
                    foreach (var dep in deps)
                    {
                        Log.LogMessage(MessageImportance.High, $"    {dep.BuildId}, IsProduct: {dep.IsProduct}");
                    }
                    finalBuild.Dependencies = deps;

                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(finalBuild, cancellationToken);

                    Log.LogMessage(MessageImportance.High, $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
        public async Task <bool> PushMetadataAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    List <BuildData> buildsManifestMetadata = GetBuildManifestsMetadata(ManifestsPath, cancellationToken);

                    if (buildsManifestMetadata.Count == 0)
                    {
                        Log.LogError($"No build manifests found matching the search pattern {SearchPattern} in {ManifestsPath}");
                        return(!Log.HasLoggedErrors);
                    }

                    BuildData finalBuild = MergeBuildManifests(buildsManifestMetadata);

                    IMaestroApi client = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                    var deps = await GetBuildDependenciesAsync(client, cancellationToken);

                    Log.LogMessage(MessageImportance.High, "Calculated Dependencies:");
                    foreach (var dep in deps)
                    {
                        Log.LogMessage(MessageImportance.High, $"    {dep.BuildId}, IsProduct: {dep.IsProduct}");
                    }
                    finalBuild.Dependencies = deps;

                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(finalBuild, cancellationToken);

                    BuildId = recordedBuild.Id;

                    Log.LogMessage(MessageImportance.High, $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                    Console.WriteLine($"##vso[build.addbuildtag]BAR ID - {recordedBuild.Id}");

                    // Only 'create' the AzDO (VSO) variables if running in an AzDO build
                    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_BUILDID")))
                    {
                        IEnumerable <DefaultChannel> defaultChannels = await GetBuildDefaultChannelsAsync(client, recordedBuild);

                        HashSet <int> targetChannelIds = new HashSet <int>(defaultChannels.Select(dc => dc.Channel.Id));

                        var defaultChannelsStr = "[" + string.Join("][", targetChannelIds) + "]";
                        Log.LogMessage(MessageImportance.High, $"Determined build will be added to the following channels: { defaultChannelsStr}");

                        Console.WriteLine($"##vso[task.setvariable variable=BARBuildId]{recordedBuild.Id}");
                        Console.WriteLine($"##vso[task.setvariable variable=DefaultChannels]{defaultChannelsStr}");
                        Console.WriteLine($"##vso[task.setvariable variable=IsStableBuild]{IsStableBuild}");
                    }
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
        private async Task <IEnumerable <DefaultChannel> > GetBuildDefaultChannelsAsync(IMaestroApi client, Client.Models.Build recordedBuild)
        {
            var defaultChannels = new List <DefaultChannel>();

            if (recordedBuild.GitHubBranch != null && recordedBuild.GitHubRepository != null)
            {
                defaultChannels.AddRange(
                    await client.DefaultChannels.ListAsync(
                        branch: recordedBuild.GitHubBranch,
                        channelId: null,
                        enabled: true,
                        repository: recordedBuild.GitHubRepository
                        ));
            }

            if (recordedBuild.AzureDevOpsBranch != null && recordedBuild.AzureDevOpsRepository != null)
            {
                defaultChannels.AddRange(
                    await client.DefaultChannels.ListAsync(
                        branch: recordedBuild.AzureDevOpsBranch,
                        channelId: null,
                        enabled: true,
                        repository: recordedBuild.AzureDevOpsRepository
                        ));
            }

            Log.LogMessage(MessageImportance.High, "Found the following default channels:");
            foreach (var defaultChannel in defaultChannels)
            {
                Log.LogMessage(
                    MessageImportance.High,
                    $"    {defaultChannel.Repository}@{defaultChannel.Branch} " +
                    $"=> ({defaultChannel.Channel.Id}) {defaultChannel.Channel.Name}");
            }
            return(defaultChannels);
        }
        public async Task <bool> PushMetadataAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    //get the list of manifests
                    List <Manifest> parsedManifests = GetParsedManifests(ManifestsPath, cancellationToken);

                    if (parsedManifests.Count == 0)
                    {
                        Log.LogError(
                            $"No manifests found matching the search pattern {SearchPattern} in {ManifestsPath}");
                        return(!Log.HasLoggedErrors);
                    }

                    Manifest manifest;
                    //check if the manifest have any duplicate packages and blobs
                    if (parsedManifests.Count > 1)
                    {
                        manifest = MergeManifests(parsedManifests);
                    }
                    else
                    {
                        manifest = parsedManifests[0];
                    }

                    List <SigningInformation> signingInformation = new List <SigningInformation>();
                    foreach (var m in parsedManifests)
                    {
                        if (m.SigningInformation != null)
                        {
                            signingInformation.Add(m.SigningInformation);
                        }
                    }

                    //get packages blobs and signing info
                    (List <PackageArtifactModel> packages,
                     List <BlobArtifactModel> blobs) = GetPackagesAndBlobsInfo(manifest);

                    //create merged buildModel to create the merged manifest
                    BuildModel modelForManifest =
                        CreateMergedManifestBuildModel(packages, blobs, manifest);


                    //add manifest as an asset to the buildModel
                    var mergedManifestAsset = GetManifestAsAsset(blobs, MergedManifestFileName);
                    modelForManifest.Artifacts.Blobs.Add(mergedManifestAsset);

                    SigningInformation finalSigningInfo = MergeSigningInfo(signingInformation);

                    // push the merged manifest, this is required for only publishingVersion 3 and above
                    if (manifest.PublishingVersion >= 3)
                    {
                        PushMergedManifest(modelForManifest, finalSigningInfo);
                    }

                    // populate buildData and assetData using merged manifest data
                    BuildData buildData = GetMaestroBuildDataFromMergedManifest(modelForManifest, manifest, cancellationToken);

                    IMaestroApi client = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                    var deps = await GetBuildDependenciesAsync(client, cancellationToken);

                    Log.LogMessage(MessageImportance.High, "Calculated Dependencies:");
                    foreach (var dep in deps)
                    {
                        Log.LogMessage(MessageImportance.High, $"    {dep.BuildId}, IsProduct: {dep.IsProduct}");
                    }

                    buildData.Dependencies = deps;
                    LookupForMatchingGitHubRepository(manifest);
                    buildData.GitHubBranch     = GitHubBranch;
                    buildData.GitHubRepository = GitHubRepository;

                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(buildData, cancellationToken);

                    BuildId = recordedBuild.Id;

                    Log.LogMessage(MessageImportance.High,
                                   $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                    Console.WriteLine($"##vso[build.addbuildtag]BAR ID - {recordedBuild.Id}");

                    // Only 'create' the AzDO (VSO) variables if running in an AzDO build
                    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_BUILDID")))
                    {
                        IEnumerable <DefaultChannel> defaultChannels =
                            await GetBuildDefaultChannelsAsync(client, recordedBuild);

                        HashSet <int> targetChannelIds = new HashSet <int>(defaultChannels.Select(dc => dc.Channel.Id));

                        var defaultChannelsStr = "[" + string.Join("][", targetChannelIds) + "]";
                        Log.LogMessage(MessageImportance.High,
                                       $"Determined build will be added to the following channels: {defaultChannelsStr}");

                        Console.WriteLine($"##vso[task.setvariable variable=BARBuildId]{recordedBuild.Id}");
                        Console.WriteLine($"##vso[task.setvariable variable=DefaultChannels]{defaultChannelsStr}");
                        Console.WriteLine($"##vso[task.setvariable variable=IsStableBuild]{IsStableBuild}");
                    }
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }
        public async Task <bool> PushMetadataAsync(CancellationToken cancellationToken)
        {
            try
            {
                cancellationToken.ThrowIfCancellationRequested();

                Log.LogMessage(MessageImportance.High, "Starting build metadata push to the Build Asset Registry...");

                if (!Directory.Exists(ManifestsPath))
                {
                    Log.LogError($"Required folder '{ManifestsPath}' does not exist.");
                }
                else
                {
                    (List <BuildData> buildsManifestMetadata,
                     List <SigningInformation> signingInformation,
                     ManifestBuildData manifestBuildData) = GetBuildManifestsMetadata(ManifestsPath, cancellationToken);

                    if (buildsManifestMetadata.Count == 0)
                    {
                        Log.LogError($"No build manifests found matching the search pattern {SearchPattern} in {ManifestsPath}");
                        return(!Log.HasLoggedErrors);
                    }

                    BuildData   finalBuild = MergeBuildManifests(buildsManifestMetadata);
                    IMaestroApi client     = ApiFactory.GetAuthenticated(MaestroApiEndpoint, BuildAssetRegistryToken);

                    var deps = await GetBuildDependenciesAsync(client, cancellationToken);

                    Log.LogMessage(MessageImportance.High, "Calculated Dependencies:");
                    foreach (var dep in deps)
                    {
                        Log.LogMessage(MessageImportance.High, $"    {dep.BuildId}, IsProduct: {dep.IsProduct}");
                    }
                    finalBuild.Dependencies = deps;

                    // Based on the in-memory merged manifest, create a physical XML file and
                    // upload it to the BlobArtifacts folder only when publishingVersion >= 3
                    if (manifestBuildData.PublishingVersion >= 3)
                    {
                        SigningInformation finalSigningInfo = MergeSigningInfo(signingInformation);

                        // Inject an entry of MergedManifest.xml to the in-memory merged manifest
                        string    location  = null;
                        AssetData assetData = finalBuild.Assets.FirstOrDefault();

                        if (assetData != null)
                        {
                            AssetLocationData assetLocationData = assetData.Locations.FirstOrDefault();

                            if (assetLocationData != null)
                            {
                                location = assetLocationData.Location;
                            }
                        }

                        finalBuild.Assets = finalBuild.Assets.Add(GetManifestAsAsset(finalBuild.Assets, location, MergedManifestFileName));

                        BuildModel modelForManifest = CreateMergedManifestBuildModel(finalBuild.Assets, manifestBuildData);
                        PushMergedManifest(modelForManifest, finalSigningInfo);
                    }

                    Client.Models.Build recordedBuild = await client.Builds.CreateAsync(finalBuild, cancellationToken);

                    BuildId = recordedBuild.Id;

                    Log.LogMessage(MessageImportance.High, $"Metadata has been pushed. Build id in the Build Asset Registry is '{recordedBuild.Id}'");
                    Console.WriteLine($"##vso[build.addbuildtag]BAR ID - {recordedBuild.Id}");

                    // Only 'create' the AzDO (VSO) variables if running in an AzDO build
                    if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("BUILD_BUILDID")))
                    {
                        IEnumerable <DefaultChannel> defaultChannels = await GetBuildDefaultChannelsAsync(client, recordedBuild);

                        HashSet <int> targetChannelIds = new HashSet <int>(defaultChannels.Select(dc => dc.Channel.Id));

                        var defaultChannelsStr = "[" + string.Join("][", targetChannelIds) + "]";
                        Log.LogMessage(MessageImportance.High, $"Determined build will be added to the following channels: { defaultChannelsStr}");

                        Console.WriteLine($"##vso[task.setvariable variable=BARBuildId]{recordedBuild.Id}");
                        Console.WriteLine($"##vso[task.setvariable variable=DefaultChannels]{defaultChannelsStr}");
                        Console.WriteLine($"##vso[task.setvariable variable=IsStableBuild]{IsStableBuild}");
                    }
                }
            }
            catch (Exception exc)
            {
                Log.LogErrorFromException(exc, true, true, null);
            }

            return(!Log.HasLoggedErrors);
        }