public override async Task <int> ExecuteAsync()
        {
            try
            {
                RemoteFactory remoteFactory = new RemoteFactory(_options);
                var           barOnlyRemote = await remoteFactory.GetBarOnlyRemoteAsync(Logger);

                List <DefaultChannel> defaultChannels = (await barOnlyRemote.GetDefaultChannelsAsync()).ToList();
                defaultChannels.Add(
                    new DefaultChannel(0, "https://github.com/dotnet/arcade", true)
                {
                    Branch  = "master",
                    Channel = await barOnlyRemote.GetChannelAsync(".NET Tools - Latest")
                }
                    );
                defaultChannels.Add(
                    new DefaultChannel(0, "https://github.com/dotnet/arcade", true)
                {
                    Branch  = "release/3.x",
                    Channel = await barOnlyRemote.GetChannelAsync(".NET 3 Tools")
                }
                    );
                List <Subscription> subscriptions = (await barOnlyRemote.GetSubscriptionsAsync()).ToList();

                // Build, then prune out what we don't want to see if the user specified
                // channels.
                DependencyFlowGraph flowGraph = DependencyFlowGraph.Build(defaultChannels, subscriptions);

                Channel targetChannel = null;
                if (!string.IsNullOrEmpty(_options.Channel))
                {
                    // Resolve the channel.
                    targetChannel = await UxHelpers.ResolveSingleChannel(barOnlyRemote, _options.Channel);

                    if (targetChannel == null)
                    {
                        return(Constants.ErrorCode);
                    }
                }

                if (targetChannel != null)
                {
                    flowGraph.PruneGraph(node => IsInterestingNode(targetChannel, node), edge => IsInterestingEdge(edge));
                }

                await LogGraphViz(targetChannel, flowGraph);

                return(Constants.SuccessCode);
            }
            catch (Exception exc)
            {
                Logger.LogError(exc, "Something failed while getting the dependency graph.");
                return(Constants.ErrorCode);
            }
        }
        /// <summary>
        ///     Deletes a build from a channel.
        /// </summary>
        /// <returns>Process exit code.</returns>
        public override async Task <int> ExecuteAsync()
        {
            try
            {
                IRemote remote = RemoteFactory.GetBarOnlyRemote(_options, Logger);

                // Find the build to give someone info
                Build build = await remote.GetBuildAsync(_options.Id);

                if (build == null)
                {
                    Console.WriteLine($"Could not find a build with id '{_options.Id}'");
                    return(Constants.ErrorCode);
                }

                Channel targetChannel = await UxHelpers.ResolveSingleChannel(remote, _options.Channel);

                if (targetChannel == null)
                {
                    return(Constants.ErrorCode);
                }

                if (!build.Channels.Any(c => c.Id == targetChannel.Id))
                {
                    Console.WriteLine($"Build '{build.Id}' is not assigned to channel '{targetChannel.Name}'");
                    return(Constants.SuccessCode);
                }

                Console.WriteLine($"Deleting the following build from channel '{targetChannel.Name}':");
                Console.WriteLine();
                Console.Write(UxHelpers.GetTextBuildDescription(build));

                await remote.DeleteBuildFromChannelAsync(_options.Id, targetChannel.Id);

                // Let the user know they can trigger subscriptions if they'd like.
                Console.WriteLine("Subscriptions can be triggered to revert to the previous state using the following command:");
                Console.WriteLine($"darc trigger-subscriptions --source-repo {build.GitHubRepository ?? build.AzureDevOpsRepository} --channel {targetChannel.Name}");

                return(Constants.SuccessCode);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine(e.Message);
                return(Constants.ErrorCode);
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Error: Failed to delete build '{_options.Id}' from channel '{_options.Channel}'.");
                return(Constants.ErrorCode);
            }
        }
示例#3
0
        /// <summary>
        ///     Assigns a build to a channel.
        /// </summary>
        /// <returns>Process exit code.</returns>
        public override async Task <int> ExecuteAsync()
        {
            try
            {
                IRemote remote = RemoteFactory.GetBarOnlyRemote(_options, Logger);

                // Find the build to give someone info
                Build build = await remote.GetBuildAsync(_options.Id);

                if (build == null)
                {
                    Console.WriteLine($"Could not find a build with id '{_options.Id}'");
                    return(Constants.ErrorCode);
                }

                Channel targetChannel = await UxHelpers.ResolveSingleChannel(remote, _options.Channel);

                if (targetChannel == null)
                {
                    return(Constants.ErrorCode);
                }

                if (build.Channels.Any(c => c.Id == targetChannel.Id))
                {
                    Console.WriteLine($"Build '{build.Id}' has already been assigned to '{targetChannel.Name}'");
                    return(Constants.SuccessCode);
                }

                Console.WriteLine($"Assigning the following build to channel '{targetChannel.Name}':");
                Console.WriteLine();
                OutputHelpers.PrintBuild(build);

                await remote.AssignBuildToChannel(_options.Id, targetChannel.Id);

                // Be helpful. Let the user know what will happen.
                string buildRepo = build.GitHubRepository ?? build.AzureDevOpsRepository;
                List <Subscription> applicableSubscriptions = (await remote.GetSubscriptionsAsync(
                                                                   sourceRepo: buildRepo, channelId: targetChannel.Id)).ToList();

                PrintSubscriptionInfo(applicableSubscriptions);

                return(Constants.SuccessCode);
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Error: Failed to assign build '{_options.Id}' to channel '{_options.Channel}'.");
                return(Constants.ErrorCode);
            }
        }
        public override async Task <int> ExecuteAsync()
        {
            try
            {
                RemoteFactory remoteFactory = new RemoteFactory(_options);
                var           barOnlyRemote = await remoteFactory.GetBarOnlyRemoteAsync(Logger);

                Channel targetChannel = null;
                if (!string.IsNullOrEmpty(_options.Channel))
                {
                    // Resolve the channel.
                    targetChannel = await UxHelpers.ResolveSingleChannel(barOnlyRemote, _options.Channel);

                    if (targetChannel == null)
                    {
                        return(Constants.ErrorCode);
                    }
                }

                var flowGraph = await barOnlyRemote.GetDependencyFlowGraph(
                    targetChannel?.Id ?? 0,
                    _options.Days,
                    includeArcade : true,
                    includeBuildTimes : _options.IncludeBuildTimes,
                    includeDisabledSubscriptions : _options.IncludeDisabledSubscriptions,
                    includedFrequencies : _options.IncludedFrequencies?.ToList());

                await LogGraphVizAsync(targetChannel, flowGraph, _options.IncludeBuildTimes);

                return(Constants.SuccessCode);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine(e.Message);
                return(Constants.ErrorCode);
            }
            catch (Exception exc)
            {
                Logger.LogError(exc, "Something failed while getting the dependency graph.");
                return(Constants.ErrorCode);
            }
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="channels"></param>
        /// <returns></returns>
        private HashSet <string> ComputeChannelsToEvaluate(IEnumerable <Channel> channels)
        {
            if (!string.IsNullOrEmpty(_options.Channel))
            {
                HashSet <string> channelsToTarget = new HashSet <string>(StringComparer.OrdinalIgnoreCase);
                Channel          targetChannel    = UxHelpers.ResolveSingleChannel(channels, _options.Channel);

                if (targetChannel != null)
                {
                    channelsToTarget.Add(targetChannel.Name);
                }

                return(channelsToTarget);
            }
            else
            {
                // Look up all channels
                return(channels.Select(c => c.Name).ToHashSet());
            }
        }
        public override async Task <int> ExecuteAsync()
        {
            IRemote remote = RemoteFactory.GetBarOnlyRemote(_options, Logger);

            try
            {
                Channel targetChannel = null;
                if (!string.IsNullOrEmpty(_options.Channel))
                {
                    targetChannel = await UxHelpers.ResolveSingleChannel(remote, _options.Channel);

                    if (targetChannel == null)
                    {
                        return(Constants.ErrorCode);
                    }
                }

                // Starting with the remote, get information on the asset name + version
                List <Asset> matchingAssets =
                    (await remote.GetAssetsAsync(name: _options.Name, version: _options.Version)).ToList();

                string queryDescriptionString =
                    $"name '{_options.Name}'{(!string.IsNullOrEmpty(_options.Version) ? $" and version '{_options.Version}'" : "")}" +
                    $"{(targetChannel != null ? $" on channel '{targetChannel.Name}'" : "")} in the last {_options.MaxAgeInDays} days";

                // Only print the lookup string if the output type is text.
                if (_options.OutputFormat == DarcOutputType.text)
                {
                    Console.WriteLine($"Looking up assets with {queryDescriptionString}");
                }

                // Walk the assets and look up the corresponding builds, potentially filtering based on channel
                // if there is a target channel
                int maxAgeInDays  = _options.MaxAgeInDays;
                var now           = DateTimeOffset.Now;
                int checkedAssets = 0;

                List <(Asset asset, Build build)> matchingAssetsAfterDate = new List <(Asset, Build)>();

                foreach (Asset asset in matchingAssets)
                {
                    // Get build info for asset
                    Build buildInfo = await remote.GetBuildAsync(asset.BuildId);

                    if (now.Subtract(buildInfo.DateProduced).TotalDays > maxAgeInDays)
                    {
                        break;
                    }

                    checkedAssets++;

                    if (targetChannel != null && !buildInfo.Channels.Any(c => c.Id == targetChannel.Id))
                    {
                        continue;
                    }

                    matchingAssetsAfterDate.Add((asset, buildInfo));
                }

                if (!matchingAssetsAfterDate.Any())
                {
                    Console.WriteLine($"No assets found with {queryDescriptionString}");
                    int remaining = matchingAssets.Count - checkedAssets;
                    if (remaining > 0)
                    {
                        Console.WriteLine($"Skipping build lookup for {remaining} assets. Consider increasing --max-age to check the rest.");
                    }

                    return(Constants.ErrorCode);
                }

                switch (_options.OutputFormat)
                {
                case DarcOutputType.text:
                    foreach ((Asset asset, Build build) in matchingAssetsAfterDate)
                    {
                        Console.WriteLine($"{asset.Name} @ {asset.Version}");
                        Console.Write(UxHelpers.GetTextBuildDescription(build));
                        Console.WriteLine("Locations:");
                        if (asset.Locations.Any())
                        {
                            foreach (var location in asset.Locations)
                            {
                                if (location.IsValid)
                                {
                                    Console.WriteLine($"- {location.Location} ({location.Type})");
                                }
                            }
                        }
                        else
                        {
                            Console.WriteLine("- None");
                        }
                        Console.WriteLine();
                    }
                    break;

                case DarcOutputType.json:
                    var assets = matchingAssetsAfterDate.Select(assetAndBuild =>
                    {
                        return(new
                        {
                            name = assetAndBuild.asset.Name,
                            version = assetAndBuild.asset.Version,
                            build = UxHelpers.GetJsonBuildDescription(assetAndBuild.build),
                            locations = assetAndBuild.asset.Locations.Select(location => location.Location)
                        });
                    });
                    Console.WriteLine(JsonConvert.SerializeObject(assets, Formatting.Indented));
                    break;
                }

                return(Constants.SuccessCode);
            }
            catch (AuthenticationException e)
            {
                Console.WriteLine(e.Message);
                return(Constants.ErrorCode);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Error: Failed to retrieve information about assets.");
                return(Constants.ErrorCode);
            }
        }
        public override async Task <int> ExecuteAsync()
        {
            try
            {
                RemoteFactory remoteFactory = new RemoteFactory(_options);
                var           barOnlyRemote = await remoteFactory.GetBarOnlyRemoteAsync(Logger);

                Channel engLatestChannel = await barOnlyRemote.GetChannelAsync(engLatestChannelId);

                Channel eng3Channel = await barOnlyRemote.GetChannelAsync(eng3ChannelId);

                List <DefaultChannel> defaultChannels = (await barOnlyRemote.GetDefaultChannelsAsync()).ToList();
                if (engLatestChannel != null)
                {
                    defaultChannels.Add(
                        new DefaultChannel(0, "https://github.com/dotnet/arcade", true)
                    {
                        Branch  = "master",
                        Channel = engLatestChannel
                    }
                        );
                }
                if (eng3Channel != null)
                {
                    defaultChannels.Add(
                        new DefaultChannel(0, "https://github.com/dotnet/arcade", true)
                    {
                        Branch  = "release/3.x",
                        Channel = eng3Channel
                    }
                        );
                }
                List <Subscription> subscriptions = (await barOnlyRemote.GetSubscriptionsAsync()).ToList();

                // Build, then prune out what we don't want to see if the user specified
                // channels.
                DependencyFlowGraph flowGraph = await DependencyFlowGraph.BuildAsync(defaultChannels, subscriptions, barOnlyRemote, _options.Days);

                Channel targetChannel = null;
                if (!string.IsNullOrEmpty(_options.Channel))
                {
                    // Resolve the channel.
                    targetChannel = await UxHelpers.ResolveSingleChannel(barOnlyRemote, _options.Channel);

                    if (targetChannel == null)
                    {
                        return(Constants.ErrorCode);
                    }
                }

                if (targetChannel != null)
                {
                    flowGraph.PruneGraph(
                        node => DependencyFlowGraph.IsInterestingNode(targetChannel.Name, node),
                        edge => DependencyFlowGraph.IsInterestingEdge(edge, _options.IncludeDisabledSubscriptions, _options.IncludedFrequencies));
                }

                if (_options.IncludeBuildTimes)
                {
                    flowGraph.MarkBackEdges();
                    flowGraph.CalculateLongestBuildPaths();
                    flowGraph.MarkLongestBuildPath();
                }

                await LogGraphVizAsync(targetChannel, flowGraph, _options.IncludeBuildTimes);

                return(Constants.SuccessCode);
            }
            catch (Exception exc)
            {
                Logger.LogError(exc, "Something failed while getting the dependency graph.");
                return(Constants.ErrorCode);
            }
        }
示例#8
0
        public override async Task <int> ExecuteAsync()
        {
            IRemote remote = RemoteFactory.GetBarOnlyRemote(_options, Logger);

            try
            {
                Channel targetChannel = null;
                if (!string.IsNullOrEmpty(_options.Channel))
                {
                    targetChannel = await UxHelpers.ResolveSingleChannel(remote, _options.Channel);

                    if (targetChannel == null)
                    {
                        return(Constants.ErrorCode);
                    }
                }

                // Starting with the remote, get information on the asset name + version
                List <Asset> matchingAssets =
                    (await remote.GetAssetsAsync(name: _options.Name, version: _options.Version)).ToList();

                string queryDescriptionString =
                    $"name '{_options.Name}'{(!string.IsNullOrEmpty(_options.Version) ? $"and version '{_options.Version}'" : "")}" +
                    $"{(targetChannel != null ? $" on channel '{targetChannel.Name}'" : "")} in the last {_options.MaxAgeInDays} days";

                Console.WriteLine($"Looking up assets with {queryDescriptionString}");

                // Walk the assets and look up the corresponding builds, potentially filtering based on channel
                // if there is a target channel
                bool foundMatching = false;
                int  maxAgeInDays  = _options.MaxAgeInDays;
                var  now           = DateTimeOffset.Now;
                int  checkedAssets = 0;

                foreach (var asset in matchingAssets)
                {
                    checkedAssets++;

                    // Get build info for asset
                    Build buildInfo = await remote.GetBuildAsync(asset.BuildId);

                    if (targetChannel != null && !buildInfo.Channels.Any(c => c.Id == targetChannel.Id))
                    {
                        continue;
                    }

                    if (now.Subtract(buildInfo.DateProduced).TotalDays > maxAgeInDays)
                    {
                        break;
                    }

                    foundMatching = true;

                    Console.WriteLine($"{asset.Name} @ {asset.Version}");
                    Console.Write(UxHelpers.GetBuildDescription(buildInfo));
                    Console.WriteLine("Locations:");
                    if (asset.Locations.Any())
                    {
                        foreach (var location in asset.Locations)
                        {
                            if (location.IsValid)
                            {
                                Console.WriteLine($"- {location.Location} ({location.Type})");
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("- None");
                    }
                    Console.WriteLine();
                }

                if (!foundMatching)
                {
                    Console.WriteLine($"No assets found with {queryDescriptionString}");
                    int remaining = matchingAssets.Count - checkedAssets;
                    if (remaining > 0)
                    {
                        Console.WriteLine($"Skipping build lookup for {remaining} assets. Consider increasing --max-age to check the rest.");
                    }
                }

                return(Constants.SuccessCode);
            }
            catch (Exception e)
            {
                Logger.LogError(e, "Error: Failed to retrieve information about assets.");
                return(Constants.ErrorCode);
            }
        }