Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,58 @@ await CreatePullRequest(
}
}

public async Task AddChannelAsync(ConfigurationRepositoryOperationParameters parameters, ChannelYaml channel)
{
IGitRepo configurationRepo = await _configurationRepoFactory.CreateClient(parameters.RepositoryUri);

await ValidateConfigurationRepositoryParametersAsync(configurationRepo, parameters);
var workingBranch = await PrepareConfigurationBranchAsync(configurationRepo, parameters);

var newChannelFilePath = string.IsNullOrEmpty(parameters.ConfigurationFilePath)
? ConfigFilePathResolver.GetDefaultChannelFilePath(channel)
: parameters.ConfigurationFilePath;
_logger.LogInformation("Adding new channel to file {0}", newChannelFilePath);

var channelsInFile = await FetchAndParseRemoteConfiguration<ChannelYaml>(
configurationRepo,
parameters.RepositoryUri,
workingBranch,
newChannelFilePath);

// If we have a branch that hasn't been ingested yet, we need to check for equivalent channels in the file
var equivalentInFile = channelsInFile.FirstOrDefault(c => string.Equals(c.Name, channel.Name, StringComparison.OrdinalIgnoreCase));
if (equivalentInFile != null)
{
throw new ArgumentException($"Channel '{equivalentInFile.Name}' already exists in '{newChannelFilePath}'.");
}

channelsInFile.Add(channel);
await CommitConfigurationDataAsync(
configurationRepo,
parameters.RepositoryUri,
workingBranch,
newChannelFilePath,
channelsInFile,
new ChannelYamlComparer(),
$"Add new channel '{channel.Name}' with classification '{channel.Classification}'");

if (!parameters.DontOpenPr)
{
// Open a pull request for the new channel
await CreatePullRequest(
configurationRepo,
parameters.RepositoryUri,
workingBranch,
parameters.ConfigurationBaseBranch,
"Updating Maestro configuration");
}
else
{
_logger.LogInformation("Successfully added channel '{0}' to branch '{1}' of the configuration repository {2}",
channel.Name, parameters.ConfigurationBranch, parameters.RepositoryUri);
}
}


#region helper methods
private static async Task ValidateConfigurationRepositoryParametersAsync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ public interface IConfigurationRepositoryManager
Task AddSubscriptionAsync(ConfigurationRepositoryOperationParameters parameters, SubscriptionYaml subscription);
Task DeleteSubscriptionAsync(ConfigurationRepositoryOperationParameters parameters, SubscriptionYaml subscription);
Task UpdateSubscriptionAsync(ConfigurationRepositoryOperationParameters parameters, SubscriptionYaml updatedSubscription);
Task AddChannelAsync(ConfigurationRepositoryOperationParameters parameters, ChannelYaml channel);
}
73 changes: 56 additions & 17 deletions src/Microsoft.DotNet.Darc/Darc/Operations/AddChannelOperation.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable enable

using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Microsoft.DotNet.Darc.Options;
using Microsoft.DotNet.DarcLib;
using Microsoft.DotNet.MaestroConfiguration.Client;
using Microsoft.DotNet.MaestroConfiguration.Client.Models;
using Microsoft.DotNet.ProductConstructionService.Client;
using Microsoft.DotNet.ProductConstructionService.Client.Models;
using Microsoft.Extensions.Logging;
Expand All @@ -18,14 +23,17 @@ internal class AddChannelOperation : Operation
private readonly AddChannelCommandLineOptions _options;
private readonly ILogger<AddChannelOperation> _logger;
private readonly IBarApiClient _barClient;
private readonly IConfigurationRepositoryManager _configRepoManager;

public AddChannelOperation(
AddChannelCommandLineOptions options,
IBarApiClient barClient,
IConfigurationRepositoryManager configRepoManager,
ILogger<AddChannelOperation> logger)
{
_options = options;
_barClient = barClient;
_configRepoManager = configRepoManager;
_logger = logger;
}

Expand All @@ -45,24 +53,49 @@ public override async Task<int> ExecuteAsync()
return Constants.ErrorCode;
}

Channel newChannelInfo = await _barClient.CreateChannelAsync(_options.Name, _options.Classification);
switch (_options.OutputFormat)
if (_options.ShouldUseConfigurationRepository)
{
case DarcOutputType.json:
Console.WriteLine(JsonConvert.SerializeObject(
new
{
id = newChannelInfo.Id,
name = newChannelInfo.Name,
classification = newChannelInfo.Classification
},
Formatting.Indented));
break;
case DarcOutputType.text:
Console.WriteLine($"Successfully created new channel with name '{_options.Name}' and id {newChannelInfo.Id}.");
break;
default:
throw new NotImplementedException($"Output type {_options.OutputFormat} not supported by add-channel");
ChannelYaml channelYaml = new()
{
Name = _options.Name,
Classification = _options.Classification
};

// Check if channel already exists in the API
var existingChannel = await FindExistingChannelAsync(channelYaml.Name);
if (existingChannel != null)
{
_logger.LogError($"An existing channel with name '{_options.Name}' already exists");
return Constants.ErrorCode;
}

await _configRepoManager.AddChannelAsync(
_options.ToConfigurationRepositoryOperationParameters(),
channelYaml);

Console.WriteLine($"Successfully created new channel with name '{_options.Name}'.");
}
else
{
Channel newChannelInfo = await _barClient.CreateChannelAsync(_options.Name, _options.Classification);
switch (_options.OutputFormat)
{
case DarcOutputType.json:
Console.WriteLine(JsonConvert.SerializeObject(
new
{
id = newChannelInfo.Id,
name = newChannelInfo.Name,
classification = newChannelInfo.Classification
},
Formatting.Indented));
break;
case DarcOutputType.text:
Console.WriteLine($"Successfully created new channel with name '{_options.Name}' and id {newChannelInfo.Id}.");
break;
default:
throw new NotImplementedException($"Output type {_options.OutputFormat} not supported by add-channel");
}
}

return Constants.SuccessCode;
Expand All @@ -83,4 +116,10 @@ public override async Task<int> ExecuteAsync()
return Constants.ErrorCode;
}
}

private async Task<Channel?> FindExistingChannelAsync(string channelName)
{
var channels = await _barClient.GetChannelsAsync();
return channels.FirstOrDefault(c => string.Equals(c.Name, channelName, StringComparison.OrdinalIgnoreCase));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
namespace Microsoft.DotNet.Darc.Options;

[Verb("add-channel", HelpText = "Creates a new channel.")]
internal class AddChannelCommandLineOptions : CommandLineOptions<AddChannelOperation>
internal class AddChannelCommandLineOptions : ConfigurationManagementCommandLineOptions<AddChannelOperation>
{
[Option('n', "name", Required = true, HelpText = "Name of channel to create.")]
public string Name { get; set; }
Expand Down
Loading