-
Notifications
You must be signed in to change notification settings - Fork 79
Implement configuration ingestion #5636
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Implement configuration ingestion #5636
Conversation
5835a33 to
898d740
Compare
898d740 to
2407049
Compare
There was a problem hiding this 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 implements configuration ingestion functionality to allow the Product Construction Service to validate and persist configuration data (subscriptions, channels, default channels, and branch merge policies) from external sources. The implementation introduces a new interface for externally synced entities, validation logic for entity uniqueness and field constraints, and CRUD operations for managing configuration data.
Key changes:
- Introduces
IExternallySyncedEntity<TId>interface to standardize entity identification across YAML models and database models - Implements comprehensive validation framework for configuration entities with uniqueness checking
- Adds CRUD operations in
SqlBarClientandConfigurationIngestorto create, update, and delete configuration entities with proper namespace isolation
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 14 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Microsoft.DotNet.Darc/DarcLib/Models/Yaml/IExternallySyncedEntity.cs | New interface defining contract for externally synced entities with unique identifiers |
| src/Microsoft.DotNet.Darc/DarcLib/Models/Yaml/SubscriptionYaml.cs | Implements IExternallySyncedEntity using subscription Id as unique identifier |
| src/Microsoft.DotNet.Darc/DarcLib/Models/Yaml/ChannelYaml.cs | Implements IExternallySyncedEntity using channel name as unique identifier |
| src/Microsoft.DotNet.Darc/DarcLib/Models/Yaml/DefaultChannelYaml.cs | Implements IExternallySyncedEntity using repository/branch/channel tuple; adds Id field for ingestion |
| src/Microsoft.DotNet.Darc/DarcLib/Models/Yaml/BranchMergePoliciesYaml.cs | Implements IExternallySyncedEntity using repository/branch tuple as unique identifier |
| src/Maestro/Maestro.Data/Models/Repository.cs | Adds UniqueId property to RepositoryBranch for consistency with IExternallySyncedEntity pattern |
| src/Maestro/Maestro.Data/Models/DefaultChannel.cs | Implements IExternallySyncedEntity on database model for alignment with YAML model |
| src/Maestro/Maestro.DataProviders/ISqlBarClient.cs | Adds interface methods for subscription CRUD operations used in configuration ingestion |
| src/Maestro/Maestro.DataProviders/SqlBarClient.cs | Implements CRUD methods with conflict detection, validation, and conversion between client/DAO models |
| src/Maestro/Maestro.DataProviders/Exceptions/EntityConflictException.cs | New exception type for handling duplicate entity conflicts during ingestion |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/IConfigurationIngestor.cs | Updated interface signature to return entity changes and require namespace parameter |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationIngestor.cs | Core ingestion orchestration including validation, entity comparison, and database persistence |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationData.cs | Changed to use YAML models instead of DAO models for external configuration representation |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationDataUpdate.cs | New record types capturing created, updated, and removed entities for each configuration type |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationDataHelper.cs | Helper methods for computing entity differences and converting between YAML and DAO models |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/Validations/EntityValidator.cs | Generic validator for checking entity uniqueness across IExternallySyncedEntity collections |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/Validations/SubscriptionValidator.cs | Updated to validate collections and work with SubscriptionYaml instead of DAO models |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/Validations/ChannelValidator.cs | Updated to validate collections and work with ChannelYaml instead of DAO models |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/Validations/DefaultChannelValidator.cs | Updated to validate collections and work with DefaultChannelYaml instead of DAO models |
| src/Maestro/Maestro.DataProviders/ConfigurationIngestor/Validations/BranchMergePolicyValidator.cs | Updated to validate collections and work with BranchMergePoliciesYaml instead of DAO models |
Comments suppressed due to low confidence (6)
src/Maestro/Maestro.DataProviders/SqlBarClient.cs:641
- This assignment assigns Enabled to itself.
existingSubscription.SourceRepository = existingSubscription.SourceRepository;
src/Maestro/Maestro.DataProviders/SqlBarClient.cs:642
- This assignment assigns SourceEnabled to itself.
existingSubscription.TargetRepository = existingSubscription.TargetRepository;
src/Maestro/Maestro.DataProviders/SqlBarClient.cs:643
- This assignment assigns SourceDirectory to itself.
existingSubscription.Enabled = existingSubscription.Enabled;
src/Maestro/Maestro.DataProviders/SqlBarClient.cs:644
- This assignment assigns TargetDirectory to itself.
existingSubscription.SourceEnabled = existingSubscription.SourceEnabled;
src/Maestro/Maestro.DataProviders/SqlBarClient.cs:646
- This assignment assigns PullRequestFailureNotificationTags to itself.
existingSubscription.TargetDirectory = existingSubscription.TargetDirectory;
src/Maestro/Maestro.DataProviders/SqlBarClient.cs:546
- The contents of this container are never initialized.
var newSubscriptionHashes = new HashSet<string>();
src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationIngestor.cs
Show resolved
Hide resolved
src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationIngestor.cs
Show resolved
Hide resolved
src/Maestro/Maestro.DataProviders/ConfigurationIngestor/Validations/EntityValidator.cs
Outdated
Show resolved
Hide resolved
src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationIngestor.cs
Show resolved
Hide resolved
src/Maestro/Maestro.DataProviders/ConfigurationIngestor/ConfigurationDataHelper.cs
Show resolved
Hide resolved
…urationDataHelper.cs Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
…dEntity.cs Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
| return new EntityChanges<T>(creations, updates, removals); | ||
| } | ||
|
|
||
| internal static Subscription ConvertSubscriptionYamlToDao( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if it'd be better if we had this on the DAOs?
At least it would be immediately visible if we ever add a field to the DAO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed, that would've been a good place. What bothered me is that this isn't a pure converter (i.e. One type of entity in -> Another type of entity out), but it requires other contextual data like existingChannelsByName.
It makes sense in the context of the ingestor because we do query all the existing channels, but if you're developing a feature somewhere else in the codebase and you see that Subscription has a converter that requires existingChannelsByName, we don't have a way to force the caller to truly provide a list of all existing channels. So I find its reusability impractical and/or dangerous
| if (subscription.SourceRepository != existingSubscription.SourceRepository) | ||
| { | ||
| illegalFieldChanges.Add("SourceRepository"); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think source repository can change? Maybe not for codeflow subscriptions only
| .Where(e => !externalEntitiesById.ContainsKey(e.UniqueId))]; | ||
|
|
||
| IEnumerable<T> updates = [.. externalEntitiesById.Values | ||
| .Where(e => dbEntitiesById.ContainsKey(e.UniqueId))]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| .Where(e => dbEntitiesById.ContainsKey(e.UniqueId))]; | |
| .Where(e => dbEntitiesById.ContainsKey(e.UniqueId))]; |
#5494