Add conditional service deployment via condition field#6684
Add conditional service deployment via condition field#6684
condition field#6684Conversation
Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
condition field
cli/azd/internal/cmd/deploy.go
Outdated
| } | ||
|
|
||
| // Check if the service condition is enabled | ||
| if !svc.IsEnabled(da.env.Getenv) { |
There was a problem hiding this comment.
Does condition mean disabled for azd deploy or all service commands?
There was a problem hiding this comment.
Left a comment here. I think this still needs to be addressed. Initial thoughts would be to have it incorporated into ServicesStable in some fashion.
There was a problem hiding this comment.
Implemented in c8fa45a. Added ServiceStableFiltered() to ImportManager which applies condition filtering. Now used by all service commands (deploy, package, restore, build, publish).
There was a problem hiding this comment.
Pull request overview
This PR adds support for conditional service deployment in azure.yaml, allowing services to be deployed only when a specified condition evaluates to a truthy value. The feature enables runtime-based deployment decisions through environment variable expansion.
Changes:
- Added
Conditionfield toServiceConfigwith support for environment variable expansion - Implemented
IsEnabled()method to evaluate conditions based on truthy values (1, true, TRUE, True, yes, YES, Yes) - Updated deploy command to skip services with false conditions or error when explicitly targeting a disabled service
- Added comprehensive unit and integration tests for condition parsing and evaluation
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| cli/azd/pkg/project/service_config.go | Added Condition field and IsEnabled() method to support conditional deployment logic |
| cli/azd/pkg/project/service_config_test.go | Added unit tests for condition evaluation with various truthy/falsy values and environment variable expansion |
| cli/azd/pkg/project/service_condition_integration_test.go | Added integration tests for YAML parsing and environment-based condition evaluation |
| cli/azd/internal/cmd/deploy.go | Updated deploy command to check service conditions and provide appropriate error messages or skip disabled services |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
cli/azd/internal/cmd/deploy.go
Outdated
| return fmt.Errorf( | ||
| "service '%s' has a deployment condition that evaluated to '%s'. "+ | ||
| "The service requires a truthy value (1, true, TRUE, True, yes, YES, Yes) to be deployed", | ||
| svc.Name, |
There was a problem hiding this comment.
When a targeted service has a false condition, the error message could be more actionable by including the condition expression itself, not just the evaluated value. Consider showing both the expression and the evaluated value, e.g., "service 'ml-model' has a deployment condition '${DEPLOY_ML_MODEL}' that evaluated to 'false'". This would help users understand which environment variable needs to be changed.
| return fmt.Errorf( | |
| "service '%s' has a deployment condition that evaluated to '%s'. "+ | |
| "The service requires a truthy value (1, true, TRUE, True, yes, YES, Yes) to be deployed", | |
| svc.Name, | |
| conditionExpression := fmt.Sprint(svc.Condition) | |
| return fmt.Errorf( | |
| "service '%s' has a deployment condition '%s' that evaluated to '%s'. "+ | |
| "The service requires a truthy value (1, true, TRUE, True, yes, YES, Yes) to be deployed", | |
| svc.Name, | |
| conditionExpression, |
| // Environment variables to set for the service | ||
| Environment osutil.ExpandableMap `yaml:"env,omitempty"` | ||
| // Condition for deploying the service. When evaluated, the service is only deployed if the value | ||
| // is a truthy boolean (1, true, TRUE, True, yes). If not defined, the service is enabled by default. |
There was a problem hiding this comment.
The comment should list all accepted truthy values for consistency with the implementation. The implementation accepts "yes", "YES", and "Yes", but the comment only lists "yes". Consider updating to: "is a truthy boolean (1, true, TRUE, True, yes, YES, Yes)".
| // is a truthy boolean (1, true, TRUE, True, yes). If not defined, the service is enabled by default. | |
| // is a truthy boolean (1, true, TRUE, True, yes, YES, Yes). If not defined, the service is enabled by default. |
| value, err := sc.Condition.Envsubst(getenv) | ||
| if err != nil { | ||
| // If condition can't be evaluated, consider it disabled | ||
| return false | ||
| } |
There was a problem hiding this comment.
The error handling for malformed condition templates silently disables the service. Consider adding a test case for this scenario to ensure the behavior is intentional and well-documented. For example, a condition like "${UNCLOSED" would return an error from Envsubst, and the service would be disabled without any indication to the user that their template is malformed.
There was a problem hiding this comment.
I think this feedback is really valid -- I believe it's appropriate to surface errors directly.
There was a problem hiding this comment.
Implemented in c8fa45a. IsEnabled() now returns (bool, error) and surfaces malformed template errors directly instead of silently disabling the service.
cli/azd/internal/cmd/deploy.go
Outdated
| // If a specific service was targeted but its condition is false, return an error | ||
| if targetServiceName != "" && targetServiceName == svc.Name { | ||
| da.console.StopSpinner(ctx, stepMessage, input.StepFailed) | ||
| conditionValue, _ := svc.Condition.Envsubst(da.env.Getenv) |
There was a problem hiding this comment.
The error from Envsubst is being silently ignored. If the condition template is malformed, the error message will show an empty string as the evaluated value, which might be misleading. Consider handling the error explicitly to provide a more informative message to the user, such as "service 'X' has a malformed deployment condition template" when err != nil.
| conditionValue, _ := svc.Condition.Envsubst(da.env.Getenv) | |
| conditionValue, err := svc.Condition.Envsubst(da.env.Getenv) | |
| if err != nil { | |
| return fmt.Errorf("service '%s' has a malformed deployment condition template: %w", svc.Name, err) | |
| } |
|
@copilot apply changes based on the comments in this thread |
There was a problem hiding this comment.
Overall, I'm really happy with the direction here. I do believe adding condition support is a good thing. There's been a few user asks along these lines. It is indeed the cheapest way for us to get to a "configurable AST". I'd like to see changes merged to support this feature.
I believe based on our PR discussion earlier, we are thinking the conditional should be applied to all service commands. This should be addressed and I'm waiting for this.
Implementation wise, I'd love us to clean up both implementation and UX -- avoid writing the skipped message (address #4605), and perhaps incorporate the enablement logic into ServicesStable. We can perhaps support a conditional name filter and report if the targetted service was disabled one way or another.
|
@copilot implement comments from this #6684 (review) |
…mmands - Move condition checking from deploy.go into ImportManager.ServiceStableFiltered - Apply filtering to all service commands (deploy, package, restore, build, publish) - Return errors for malformed condition templates instead of silently disabling - When targeting a specific service with false condition, return clear error - Remove spinner "skipped" messages for disabled services - Update IsEnabled to return (bool, error) to surface malformed templates - Add test for malformed condition templates - Update all tests to handle new IsEnabled signature Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
Implemented in c8fa45a:
|
Co-authored-by: vhvb1989 <24213737+vhvb1989@users.noreply.github.com>
Adds support for conditional service deployment in
azure.yaml. Services can now specify aconditionfield with environment variable expansion to control deployment based on runtime configuration.Changes
ServiceConfig (
pkg/project/service_config.go)Condition osutil.ExpandableStringfield supporting envvar expansionIsEnabled(getenv) (bool, error)method evaluating truthy values:1,true|TRUE|True,yes|YES|YesImportManager (
pkg/project/importer.go)ServiceStableFiltered()method that centralizes condition filteringAll Service Commands
azd deploy,azd package,azd restore,azd build,azd publishall respect service conditionsTests
Usage
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.