Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Dec 22, 2025

Description

Extends darc add-default-channel to modify the configuration repository directly, following the pattern established by add-subscription. This enables the transition from API-based to file-based default channel management.

Changes

  • ConfigurationRepositoryManager: Added AddDefaultChannelAsync method that writes DefaultChannelYaml objects to repo-specific files (e.g., configuration/default-channels/dotnet-runtime.yml)
  • AddDefaultChannelCommandLineOptions: Changed base class to ConfigurationManagementCommandLineOptions to inherit config repo flags (--configuration-repository, --configuration-branch, --configuration-base-branch, --configuration-file, --no-pr)
  • AddDefaultChannelOperation: Dual-mode operation routing via DARC_USE_CONFIGURATION_REPOSITORY environment variable; validates against existing BAR entries before writing to config repo
  • Tests: Added AddDefaultChannelOperationConfigRepoTests covering file creation, appending, duplicate detection, and YAML validation

Usage

export DARC_USE_CONFIGURATION_REPOSITORY=true

darc add-default-channel \
  --channel ".NET 9" \
  --branch main \
  --repo "https://github.com/dotnet/runtime" \
  --configuration-repository /path/to/maestro-configuration \
  --no-pr

Without the environment variable, existing API-based behavior is unchanged.

Original prompt

This section details on the original issue you should resolve

<issue_title>Make darc add-default-channel work with the Configuration Repo</issue_title>
<issue_description>Depends on #5480

Context

With the default channel configuration moving to the configuration repo, we should make it so darc add-default-channel can modifies the repo config. During the transition period, this should be behind a flag in the command.

Goal

Modify the existing darc add-default-channel command so it adds the default-channel by modifying the configuration repo in whichever structure we agree on, using the available yaml models. We'll need to add a few flags to the command:

  • Flag to target the repo instead of the API
  • Flag to specify configuration repository
  • Flag to specify which branch to commit the config changes to (if we already have a PR, or for scenario tests)
  • Flag to specify which base branch to use for the PR creation
  • Flag to specify we don't want to open a PR (for scenario tests)
  • Flag to overwrite default file for the default channel, and put the new default channel in the provided file

This should be written so it makes it easy to remove the API part, and use the configuration repo as one and only way to modify the configuration
</issue_description>

Comments on the Issue (you are @copilot in this section)

@dkurepa The operation should look similar to `add-subscriptions`, adding a method to the IConfigurationRepositoryManager and then implementing it. It should also have a test similar to `AddSubscriptionOperationConfigRepoTests`

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Co-authored-by: dkurepa <91743470+dkurepa@users.noreply.github.com>
Copilot AI changed the title [WIP] Update darc add-default-channel command for configuration repo Add configuration repository support to darc add-default-channel Dec 22, 2025
Copilot AI requested a review from dkurepa December 22, 2025 12:33
@dkurepa dkurepa marked this pull request as ready for review December 25, 2025 10:20
Copilot AI review requested due to automatic review settings December 25, 2025 10:20
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the darc add-default-channel command to support writing default channel configurations directly to the maestro-configuration repository, enabling a dual-mode operation during the transition from API-based to file-based configuration management. The implementation follows the established pattern from add-subscription and is controlled by the DARC_USE_CONFIGURATION_REPOSITORY environment variable.

Key Changes

  • Added configuration repository support to darc add-default-channel with dual-mode operation (API vs. config repo)
  • Implemented BAR validation before writing to config repo to prevent duplicates across both systems
  • Comprehensive test suite covering file creation, appending, and duplicate detection scenarios

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/Microsoft.DotNet.Darc/Darc/Options/AddDefaultChannelCommandLineOptions.cs Changed base class to ConfigurationManagementCommandLineOptions to inherit configuration repository flags
src/Microsoft.DotNet.Darc/Darc/Operations/AddDefaultChannelOperation.cs Added dual-mode operation routing, BAR validation, and config repo integration for default channel management
src/MaestroConfiguration/src/Microsoft.DotNet.MaestroConfiguration.Client/IConfigurationRepositoryManager.cs Added AddDefaultChannelAsync method signature to the interface
src/MaestroConfiguration/src/Microsoft.DotNet.MaestroConfiguration.Client/ConfigurationRepositoryManager.cs Implemented AddDefaultChannelAsync with duplicate detection and proper file path resolution
test/Microsoft.DotNet.Darc.Tests/Operations/AddDefaultChannelOperationConfigRepoTests.cs Added comprehensive test suite covering file creation, appending to existing files, and duplicate detection in YAML files

Enabled = true
};

await ValidateNoEquivalentDefaultChannel(defaultChannelYaml);
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ValidateNoEquivalentDefaultChannel method is called before AddDefaultChannelAsync, but AddDefaultChannelAsync also performs its own duplicate detection in the ConfigurationRepositoryManager. This means duplicate default channels in YAML files will be caught twice - once by the BAR validation here and again by the YAML file check in ConfigurationRepositoryManager. However, if a default channel exists only in BAR but not in the YAML file being written to, the BAR validation will catch it correctly. If a default channel exists in the YAML file but not in BAR, only the ConfigurationRepositoryManager validation will catch it. This dual-layer validation is inconsistent with the AddSubscriptionOperation pattern, where ValidateNoEquivalentSubscription only checks BAR, and the ConfigurationRepositoryManager handles YAML duplicates separately. Consider whether the BAR validation should remain or be removed for consistency with the subscription pattern.

Copilot uses AI. Check for mistakes.
}

/// <summary>
/// Validates that no equivalent default channel already exists in BAR or YAML files.
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment states "Validates that no equivalent default channel already exists in BAR or YAML files" but the implementation only checks BAR via _barClient.GetDefaultChannelsAsync. The YAML file validation is performed separately by ConfigurationRepositoryManager.AddDefaultChannelAsync. Update the comment to accurately reflect that this method only validates against BAR entries.

Suggested change
/// Validates that no equivalent default channel already exists in BAR or YAML files.
/// Validates that no equivalent default channel already exists in BAR.

Copilot uses AI. Check for mistakes.
var content = await File.ReadAllTextAsync(filePath);
return YamlDeserializer.Deserialize<List<DefaultChannelYaml>>(content) ?? [];
}
}
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test suite is missing a test case for when ValidateNoEquivalentDefaultChannel fails because a default channel already exists in BAR. This is an important scenario to test since it validates the BAR-level duplicate detection logic. Consider adding a test that mocks _barClient.GetDefaultChannelsAsync to return an existing default channel, then verifies that ExecuteAsync returns Constants.ErrorCode and logs the appropriate error message.

Copilot uses AI. Check for mistakes.
[SetUp]
public override async Task SetupAsync()
{
await base.SetupAsync();
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ConfigurationManagementTestBase does not set up a mock for GetDefaultChannelsAsync, which is called by ValidateNoEquivalentDefaultChannel in AddDefaultChannelOperation. Without this mock setup, the tests will fail when ExecuteAsync tries to validate against BAR. You need to add a mock setup in either ConfigurationManagementTestBase.SetupBarClientMock or in the test class's SetUp method to return an empty list for GetDefaultChannelsAsync, similar to how GetSubscriptionsAsync is already mocked in the base class.

Suggested change
await base.SetupAsync();
await base.SetupAsync();
// Ensure BAR client returns no default channels so validation passes without querying real BAR.
BarClientMock
.Setup(client => client.GetDefaultChannelsAsync(
It.IsAny<string?>(),
It.IsAny<string?>(),
It.IsAny<string?>(),
It.IsAny<string?>(),
It.IsAny<bool?>(),
It.IsAny<bool?>(),
It.IsAny<int?>(),
It.IsAny<int?>()))
.ReturnsAsync(new List<DefaultChannel>());

Copilot uses AI. Check for mistakes.
{
_logger.LogError("A default channel with the same repository, branch, and channel already exists (ID: {id})",
existingDefaultChannel.Id);
throw new ArgumentException($"A default channel with the repository {existingDefaultChannel.Repository}, branch {existingDefaultChannel.Branch} and channel {existingDefaultChannel.Channel} already exists");
Copy link

Copilot AI Dec 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Default 'ToString()': Channel inherits 'ToString()' from 'Object', and so is not suitable for printing.

Suggested change
throw new ArgumentException($"A default channel with the repository {existingDefaultChannel.Repository}, branch {existingDefaultChannel.Branch} and channel {existingDefaultChannel.Channel} already exists");
throw new ArgumentException($"A default channel with the repository {existingDefaultChannel.Repository}, branch {existingDefaultChannel.Branch} and channel {existingDefaultChannel.Channel.Name} already exists");

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Make darc add-default-channel work with the Configuration Repo

2 participants