Skip to content

Add dot notation support for aspire config commands #10035

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

Merged
merged 13 commits into from
Jun 27, 2025

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jun 25, 2025

Summary

Enhances the aspire config set, get, and delete commands to support dot notation for creating and managing nested JSON configuration structures.

Changes

Before

aspire config set foo.bar baz
# Created: { "foo.bar": "baz" }  # Flat key with literal dots

After

aspire config set foo.bar baz
# Creates: { "foo": { "bar": "baz" } }  # Nested object structure

Key Features

  • Nested object creation: aspire config set foo.bar.baz hello creates { "foo": { "bar": { "baz": "hello" } } }
  • Primitive replacement: Setting foo.bar after foo exists as a string automatically converts it to an object
  • Smart cleanup: Deleting nested values removes empty parent objects automatically
  • Backward compatibility: Existing flat keys continue to work unchanged
  • Proper retrieval: aspire config get foo.bar.baz correctly navigates nested structures
  • Flattened listing: aspire config list shows nested keys with dot notation (e.g., foo.bar.baz=hello)

Implementation Details

ConfigurationService Enhancements

  • SetNestedValue(): Parses dot-separated keys and creates nested JSON objects
  • DeleteNestedValue(): Removes values and cleans up empty parent objects
  • GetNestedValue(): Traverses nested paths for value retrieval
  • FlattenJsonObject(): Recursively flattens JSON for list operations
  • GetConfigurationAsync(): New method for single key lookups with dot notation support

Updated Commands

  • GetCommand: Now uses ConfigurationService.GetConfigurationAsync() instead of flat IConfiguration lookup
  • SetCommand: Automatically handles nested object creation and primitive replacement
  • DeleteCommand: Includes smart cleanup of empty parent objects
  • ListCommand: Displays all keys in flattened dot notation format

Examples

# Set nested values
aspire config set database.host localhost
aspire config set database.port 5432
aspire config set logging.level debug

# Results in:
{
  "database": {
    "host": "localhost", 
    "port": "5432"
  },
  "logging": {
    "level": "debug"
  }
}

# Retrieve nested values
aspire config get database.host    # Returns: localhost
aspire config get logging.level    # Returns: debug

# List shows flattened view
aspire config list
# Output:
# database.host=localhost
# database.port=5432
# logging.level=debug

# Delete with automatic cleanup
aspire config delete database.port
aspire config delete database.host
# The entire "database" object is removed since it becomes empty

Testing

  • 81 tests pass including comprehensive new test suite
  • Tests cover all scenarios: nested creation, primitive replacement, deletion cleanup, error handling
  • Backward compatibility verified - all existing flat key functionality preserved
  • Manual testing confirms real-world usage works as expected

Breaking Changes

None. This is a fully backward-compatible enhancement. Existing configurations and usage patterns continue to work unchanged.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

…hensive tests

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] Support dot notation for nested configuration in aspire config set/get/delete commands Add dot notation support for aspire config commands Jun 25, 2025
@Copilot Copilot AI requested a review from mitchdenny June 25, 2025 06:01
Copilot finished work on behalf of mitchdenny June 25, 2025 06:01
…stead of custom GetConfigurationAsync

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
@Copilot Copilot AI requested a review from mitchdenny June 25, 2025 06:51
Copilot finished work on behalf of mitchdenny June 25, 2025 06:51
@mitchdenny
Copy link
Member

@copilot I now want you to extend the work you've done so far by implementing an IFeatureFlags interface. The IFeatureFlags interface is internal to the CLI and should look like the following:

internal interface IFeatureFlags
{
  bool IsFeatureEnabled(string featureFlag);
}

This service will read configuration keys with the form featureFlags.[featureFlag] with a default value of false. If the value is present and set to true then it is enabled. Modify the deploy command so that it is not enabled unless the deployCommandEnabled feature flag is set.

This shouldn't require changing any of the existing configuration code that you've already added so far in this PR, this would just be a new API injected into DI which uses IConfigurationService.

- Add IFeatureFlags interface and FeatureFlags implementation
- Feature flags read from config keys with pattern featureFlags.[featureName]
- Deploy command is only available when deployCommandEnabled feature flag is true
- Add comprehensive tests for feature flag functionality
- Backward compatible: all existing commands work unchanged

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Jun 25, 2025

@copilot I now want you to extend the work you've done so far by implementing an IFeatureFlags interface. The IFeatureFlags interface is internal to the CLI and should look like the following:

...

I've implemented the IFeatureFlags interface as requested. The interface provides a IsFeatureEnabled(string featureFlag) method that reads configuration keys with the pattern featureFlags.[featureFlag] and defaults to false if not set.

The deploy command is now controlled by the deployCommandEnabled feature flag and will only appear in the CLI when this flag is set to true. The implementation uses the existing IConfigurationService and doesn't require any changes to the previous dot notation configuration work.

Key features:

  • IFeatureFlags interface with IsFeatureEnabled method
  • Reads from featureFlags.deployCommandEnabled configuration key
  • Deploy command conditionally registered in DI based on feature flag
  • Comprehensive tests for all feature flag scenarios
  • Backward compatible - all existing functionality preserved

(commit fadb1de)

Copilot finished work on behalf of mitchdenny June 25, 2025 08:20
Copy link
Member

Choose a reason for hiding this comment

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

@copilot remove this file from the PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the .aspire/settings.json file from the PR as requested.


if (value is not null)
{
Console.WriteLine(value);
return Task.FromResult(0);
return 0;
Copy link
Member

Choose a reason for hiding this comment

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

@copilot use the success exit code constants here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to use ExitCodeConstants.Success instead of hardcoded return 0;.

…o use IConfiguration, implement factory pattern, remove .aspire/settings.json

Co-authored-by: mitchdenny <513398+mitchdenny@users.noreply.github.com>
@Copilot Copilot AI requested a review from mitchdenny June 26, 2025 04:11
Copilot finished work on behalf of mitchdenny June 26, 2025 04:11
@mitchdenny mitchdenny marked this pull request as ready for review June 26, 2025 09:29
@mitchdenny
Copy link
Member

@davidfowl this is ready to go.

@captainsafia as a heads up this PR introduces feature flagging. Currently as a proof point I've put the deploy command behind a feature flag. To enable it for local testing you will need to do this:

aspire config set --global featureFlags.deployCommandEnabled true

@mitchdenny mitchdenny requested a review from davidfowl June 27, 2025 00:22
@mitchdenny mitchdenny added this to the 9.4 milestone Jun 27, 2025
@mitchdenny mitchdenny merged commit 328b15e into main Jun 27, 2025
252 checks passed
@mitchdenny mitchdenny deleted the copilot/fix-f3630775-1d30-4f4c-be17-ea2171b18df9 branch June 27, 2025 01:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants