-
Notifications
You must be signed in to change notification settings - Fork 268
Add azd config options command for config discoverability
#6390
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?
Conversation
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
azd config options command for config discoverability
|
@copilot does this also encompass the possible ENV values that azd uses for configs and feature flags? |
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Yes! I've updated the implementation to include environment variable information. The output now shows:
The command output now includes an "Environment Variable" column in table format, and the Commit: f20cebb Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot show what the command is and the help looks like for the command. |
Command Usageazd config optionsHelp OutputThe command appears in Output ExamplesTable format (default): JSON format: $ azd config options -o json | jq '.[0:2]'
[
{
"Key": "defaults.subscription",
"Description": "Default Azure subscription ID to use for operations.",
"Type": "string",
"AllowedValues": null,
"Example": "00000000-0000-0000-0000-000000000000",
"EnvVar": ""
},
{
"Key": "alpha.all",
"Description": "Enable or disable all alpha features at once.",
"Type": "string",
"AllowedValues": ["on", "off"],
"EnvVar": "AZD_ALPHA_ENABLE_ALL"
}
]Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
@copilot in the output of the command, the table, can we also show the current value that is set. |
Co-authored-by: spboyer <7681382+spboyer@users.noreply.github.com>
Added! The table now includes a "Current Value" column that shows the currently configured value for each setting. Example output with some values set: The column displays:
Commit: 6accc32 Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
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 adds a new azd config options command to improve discoverability of available configuration settings. Currently, azd config list only shows user-configured values, making it difficult to discover what options are available. The implementation follows established patterns in the codebase for resource loading and command structure.
Key Changes:
- New
azd config optionscommand with JSON and table output formats - Centralized YAML metadata file documenting all 14 configuration options
- API function
config.GetAllConfigOptions()following alpha features pattern - Current value display and environment variable mapping
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
cli/azd/resources/config_options.yaml |
New YAML resource file defining all 14 available config options with metadata |
cli/azd/resources/resources.go |
Embeds the new config_options.yaml file into the binary |
cli/azd/pkg/config/config_options.go |
Implements ConfigOption struct and GetAllConfigOptions() function with YAML loading |
cli/azd/pkg/config/config_options_test.go |
Unit tests validating config options structure and required fields |
cli/azd/cmd/config.go |
Implements configOptionsAction with table/JSON formatting and current value display |
cli/azd/cmd/testdata/TestUsage-azd-config.snap |
Updated snapshot showing new command in help text |
cli/azd/cmd/testdata/TestUsage-azd-config-options.snap |
New snapshot for the options command help output |
| - key: (env) AZD_CONFIG_DIR | ||
| description: "Override the default configuration directory location." | ||
| type: envvar |
Copilot
AI
Dec 17, 2025
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.
The environment variable entry uses "(env) AZD_CONFIG_DIR" as the key, which is a special prefix pattern. This breaks the standard key convention used elsewhere in config settings. Consider separating environment-only variables into a different section of the YAML or using a dedicated field (like 'environmentOnly: true') to mark these entries, rather than encoding this information in the key itself.
| - key: (env) AZD_CONFIG_DIR | |
| description: "Override the default configuration directory location." | |
| type: envvar | |
| - key: env.AZD_CONFIG_DIR | |
| description: "Override the default configuration directory location." | |
| type: envvar | |
| environmentOnly: true |
cli/azd/cmd/config.go
Outdated
| // Get current value from config | ||
| currentValue := "" | ||
| // Skip environment-only variables (those with keys starting with "(env)") | ||
| if !strings.HasPrefix(option.Key, "(env)") { |
Copilot
AI
Dec 17, 2025
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.
The check for environment-only variables uses strings.HasPrefix(option.Key, "(env)"), creating a tight coupling between the YAML structure and the code logic. This magic string constant should be defined as a package-level constant for better maintainability and to avoid typos. Additionally, consider adding validation in GetAllConfigOptions() or the init() function to ensure consistency.
| currentConfig, err := a.configManager.Load() | ||
| if err != nil { | ||
| // If config doesn't exist or can't be loaded, continue with empty config | ||
| currentConfig = config.NewEmptyConfig() | ||
| } |
Copilot
AI
Dec 17, 2025
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.
The error from configManager.Load() is silently ignored and replaced with an empty config. While the comment explains the intent, this could hide legitimate errors (e.g., permission issues, corrupted config files) that should be surfaced to users. Consider logging the error or only catching specific expected errors like os.ErrNotExist, similar to how userConfigManager.Load() handles this in user_config_manager.go:38-44.
| // Copyright (c) Microsoft Corporation. All rights reserved. | ||
| // Licensed under the MIT License. | ||
|
|
||
| package config | ||
|
|
||
| import ( | ||
| "testing" | ||
|
|
||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestGetAllConfigOptions(t *testing.T) { | ||
| options := GetAllConfigOptions() | ||
|
|
||
| // Should have at least some options | ||
| require.NotEmpty(t, options) | ||
| require.Greater(t, len(options), 0) | ||
|
|
||
| // Check that we have the expected default options | ||
| foundDefaultsSubscription := false | ||
| foundDefaultsLocation := false | ||
| foundAlphaAll := false | ||
|
|
||
| for _, option := range options { | ||
| require.NotEmpty(t, option.Key, "Config option key should not be empty") | ||
| require.NotEmpty(t, option.Description, "Config option description should not be empty") | ||
| require.NotEmpty(t, option.Type, "Config option type should not be empty") | ||
|
|
||
| switch option.Key { | ||
| case "defaults.subscription": | ||
| foundDefaultsSubscription = true | ||
| require.Equal(t, "string", option.Type) | ||
| require.Contains(t, option.Description, "subscription") | ||
| case "defaults.location": | ||
| foundDefaultsLocation = true | ||
| require.Equal(t, "string", option.Type) | ||
| require.Contains(t, option.Description, "location") | ||
| case "alpha.all": | ||
| foundAlphaAll = true | ||
| require.Equal(t, "string", option.Type) | ||
| require.Contains(t, option.AllowedValues, "on") | ||
| require.Contains(t, option.AllowedValues, "off") | ||
| require.Equal(t, "AZD_ALPHA_ENABLE_ALL", option.EnvVar) | ||
| } | ||
| } | ||
|
|
||
| // Verify expected options are present | ||
| require.True(t, foundDefaultsSubscription, "defaults.subscription option should be present") | ||
| require.True(t, foundDefaultsLocation, "defaults.location option should be present") | ||
| require.True(t, foundAlphaAll, "alpha.all option should be present") | ||
| } | ||
|
|
||
| func TestConfigOptionStructure(t *testing.T) { | ||
| options := GetAllConfigOptions() | ||
|
|
||
| for _, option := range options { | ||
| // All options should have required fields | ||
| require.NotEmpty(t, option.Key) | ||
| require.NotEmpty(t, option.Description) | ||
| require.NotEmpty(t, option.Type) | ||
|
|
||
| // If AllowedValues is set, it should not be empty | ||
| if len(option.AllowedValues) > 0 { | ||
| for _, val := range option.AllowedValues { | ||
| require.NotEmpty(t, val, "Allowed value should not be empty") | ||
| } | ||
| } | ||
| } | ||
| } |
Copilot
AI
Dec 17, 2025
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.
The command tests only unit test the GetAllConfigOptions function but don't test the configOptionsAction itself. Consider adding an integration test that verifies the action's behavior, including JSON and table output formats, error handling, and current value display. This follows the pattern seen in auth_token_test.go where action implementations are tested directly.
|
/azp run azure-dev - cli |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
@copilot , the Update the snapshots for this test |
- Define EnvOnlyPrefix constant for environment-only config keys - Improve error handling to log non-NotExist errors instead of silently ignoring - Update figspec test snapshots for new config options command - Use constant instead of magic string for environment-only check Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
... Fixed! The figspec snapshots have been updated to include the new The test now passes with the new command properly listed in the Fig autocomplete spec. Commit: cf82fd0 Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
If you need me to access, download, or install something from one of these locations, you can either:
|
|
/azp run azure-dev - cli |
|
Azure Pipelines successfully started running 1 pipeline(s). |
Implementation Plan: Add
azd config optionscommandazd config optionscommand actionChanges Made
resources/config_options.yamlwith all config settings (defaults, alpha features, templates, pipeline)pkg/config/config_options.goto load and expose config optionsazd config optionscommand incmd/config.gowith JSON and table output formatspkg/config/config_options_test.goEnvOnlyPrefixconstant to avoid magic stringsCommand Output Examples
Table format (default) - with Current Value column:
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.