Skip to content

Commit 7e76087

Browse files
committed
Updates project service to support saving project/service configs for full object
1 parent f040d25 commit 7e76087

File tree

2 files changed

+346
-31
lines changed

2 files changed

+346
-31
lines changed

cli/azd/internal/grpcserver/project_service.go

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,20 @@ func NewProjectService(
5555
}
5656

5757
// reloadAndCacheProjectConfig reloads the project configuration from disk and updates the lazy cache.
58-
// It preserves the EventDispatcher from the previous instance to maintain event handler continuity.
58+
// It preserves the EventDispatcher from the previous instance to maintain event handler continuity
59+
// for both the project and all services.
60+
//
61+
// Event dispatchers must be preserved because they contain event handlers that were registered by:
62+
// - azure.yaml hooks (prepackage, postdeploy, etc.)
63+
// - azd extensions that registered custom event handlers
64+
//
65+
// Without preserving these dispatchers, any event handlers registered before the reload would be lost,
66+
// causing hooks and extension-registered handlers to stop working after configuration updates.
5967
func (s *projectService) reloadAndCacheProjectConfig(ctx context.Context, projectPath string) error {
60-
// Get the current config to preserve the EventDispatcher
68+
// Get the current config to preserve the EventDispatchers
6169
oldConfig, err := s.lazyProjectConfig.GetValue()
6270
if err != nil {
63-
// If we can't get old config, just reload without preserving dispatcher
71+
// If we can't get old config, just reload without preserving dispatchers
6472
reloadedConfig, err := project.Load(ctx, projectPath)
6573
if err != nil {
6674
return err
@@ -75,11 +83,20 @@ func (s *projectService) reloadAndCacheProjectConfig(ctx context.Context, projec
7583
return err
7684
}
7785

78-
// Preserve the EventDispatcher from the old config
86+
// Preserve the EventDispatcher from the old project config
7987
if oldConfig.EventDispatcher != nil {
8088
reloadedConfig.EventDispatcher = oldConfig.EventDispatcher
8189
}
8290

91+
// Preserve the EventDispatcher for each service
92+
if oldConfig.Services != nil && reloadedConfig.Services != nil {
93+
for serviceName, oldService := range oldConfig.Services {
94+
if reloadedService, exists := reloadedConfig.Services[serviceName]; exists && oldService.EventDispatcher != nil {
95+
reloadedService.EventDispatcher = oldService.EventDispatcher
96+
}
97+
}
98+
}
99+
83100
// Update the lazy cache
84101
s.lazyProjectConfig.SetValue(reloadedConfig)
85102
return nil
@@ -143,33 +160,9 @@ func (s *projectService) Get(ctx context.Context, req *azdext.EmptyRequest) (*az
143160
}
144161
}
145162

146-
project := &azdext.ProjectConfig{
147-
Name: projectConfig.Name,
148-
ResourceGroupName: projectConfig.ResourceGroupName.MustEnvsubst(envKeyMapper),
149-
Path: projectConfig.Path,
150-
Infra: &azdext.InfraOptions{
151-
Provider: string(projectConfig.Infra.Provider),
152-
Path: projectConfig.Infra.Path,
153-
Module: projectConfig.Infra.Module,
154-
},
155-
Services: map[string]*azdext.ServiceConfig{},
156-
}
157-
158-
if projectConfig.Metadata != nil {
159-
project.Metadata = &azdext.ProjectMetadata{
160-
Template: projectConfig.Metadata.Template,
161-
}
162-
}
163-
164-
for name, service := range projectConfig.Services {
165-
var protoService *azdext.ServiceConfig
166-
167-
// Use mapper with environment variable resolver
168-
if err := mapper.WithResolver(envKeyMapper).Convert(service, &protoService); err != nil {
169-
return nil, fmt.Errorf("converting service config to proto: %w", err)
170-
}
171-
172-
project.Services[name] = protoService
163+
var project *azdext.ProjectConfig
164+
if err := mapper.WithResolver(envKeyMapper).Convert(projectConfig, &project); err != nil {
165+
return nil, fmt.Errorf("converting project config to proto: %w", err)
173166
}
174167

175168
return &azdext.GetProjectResponse{

0 commit comments

Comments
 (0)