Skip to content

Commit e43d69d

Browse files
committed
vsrpc: support non-aspire projects
1 parent 55aabaf commit e43d69d

File tree

3 files changed

+92
-38
lines changed

3 files changed

+92
-38
lines changed

cli/azd/internal/vsrpc/environment_service_create.go

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ import (
1212
"path/filepath"
1313
"strings"
1414

15+
"github.com/azure/azure-dev/cli/azd/internal/names"
1516
"github.com/azure/azure-dev/cli/azd/pkg/apphost"
1617
"github.com/azure/azure-dev/cli/azd/pkg/environment"
1718
"github.com/azure/azure-dev/cli/azd/pkg/environment/azdcontext"
1819
"github.com/azure/azure-dev/cli/azd/pkg/osutil"
20+
"github.com/azure/azure-dev/cli/azd/pkg/project"
1921
"github.com/azure/azure-dev/cli/azd/pkg/tools/dotnet"
2022
)
2123

@@ -64,32 +66,65 @@ func (s *environmentService) CreateEnvironmentAsync(
6466
// If an azure.yaml doesn't already exist, we need to create one. Creating an environment implies initializing the
6567
// azd project if it does not already exist.
6668
if _, err := os.Stat(c.azdContext.ProjectPath()); errors.Is(err, fs.ErrNotExist) {
67-
_ = observer.OnNext(ctx, newImportantProgressMessage("Analyzing Aspire Application (this might take a moment...)"))
68-
69-
manifest, err := apphost.ManifestFromAppHost(ctx, rc.HostProjectPath, c.dotnetCli, dotnetEnv)
70-
if err != nil {
71-
return false, fmt.Errorf("reading app host manifest: %w", err)
72-
}
73-
74-
projectName := azdcontext.ProjectName(strings.TrimSuffix(c.azdContext.ProjectDirectory(), ".AppHost"))
75-
76-
// Write an azure.yaml file to the project.
77-
files, err := apphost.GenerateProjectArtifacts(
78-
ctx,
79-
c.azdContext.ProjectDirectory(),
80-
projectName,
81-
manifest,
82-
rc.HostProjectPath,
83-
)
69+
isAspire, err := c.dotnetCli.IsAspireHostProject(ctx, rc.HostProjectPath)
8470
if err != nil {
85-
return false, fmt.Errorf("generating project artifacts: %w", err)
71+
return false, fmt.Errorf("checking if %s is an app host project: %w", rc.HostProjectPath, err)
8672
}
8773

88-
file := files["azure.yaml"]
89-
projectFilePath := filepath.Join(c.azdContext.ProjectDirectory(), "azure.yaml")
90-
91-
if err := os.WriteFile(projectFilePath, []byte(file.Contents), osutil.PermissionFile); err != nil {
92-
return false, fmt.Errorf("writing azure.yaml: %w", err)
74+
if isAspire {
75+
_ = observer.OnNext(ctx,
76+
newImportantProgressMessage("Analyzing Aspire Application (this might take a moment...)"))
77+
78+
manifest, err := apphost.ManifestFromAppHost(ctx, rc.HostProjectPath, c.dotnetCli, dotnetEnv)
79+
if err != nil {
80+
return false, fmt.Errorf("reading app host manifest: %w", err)
81+
}
82+
83+
projectName := azdcontext.ProjectName(strings.TrimSuffix(c.azdContext.ProjectDirectory(), ".AppHost"))
84+
85+
// Write an azure.yaml file to the project.
86+
files, err := apphost.GenerateProjectArtifacts(
87+
ctx,
88+
c.azdContext.ProjectDirectory(),
89+
projectName,
90+
manifest,
91+
rc.HostProjectPath,
92+
)
93+
if err != nil {
94+
return false, fmt.Errorf("generating project artifacts: %w", err)
95+
}
96+
97+
file := files["azure.yaml"]
98+
projectFilePath := filepath.Join(c.azdContext.ProjectDirectory(), "azure.yaml")
99+
100+
if err := os.WriteFile(projectFilePath, []byte(file.Contents), osutil.PermissionFile); err != nil {
101+
return false, fmt.Errorf("writing azure.yaml: %w", err)
102+
}
103+
} else {
104+
rel, err := filepath.Rel(c.azdContext.ProjectDirectory(), rc.HostProjectPath)
105+
if err != nil {
106+
return false, fmt.Errorf("determining relative path: %w", err)
107+
}
108+
109+
projectName := azdcontext.ProjectName(c.azdContext.ProjectDirectory())
110+
111+
ext := filepath.Ext(rc.HostProjectPath)
112+
serviceName := names.LabelName(strings.TrimSuffix(filepath.Base(rc.HostProjectPath), ext))
113+
114+
prjConfig := project.ProjectConfig{
115+
Name: projectName,
116+
Services: map[string]*project.ServiceConfig{
117+
serviceName: {
118+
Name: serviceName,
119+
RelativePath: fmt.Sprintf("./%s", filepath.ToSlash(rel)),
120+
},
121+
},
122+
}
123+
124+
err = project.Save(ctx, &prjConfig, c.azdContext.ProjectPath())
125+
if err != nil {
126+
return false, fmt.Errorf("saving project config: %w", err)
127+
}
93128
}
94129
} else if err != nil {
95130
return false, fmt.Errorf("checking for project: %w", err)

cli/azd/internal/vsrpc/environment_service_load.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,14 +120,17 @@ func (s *environmentService) loadEnvironmentAsync(
120120
appHost, err := appHostForProject(ctx, c.projectConfig, c.dotnetCli)
121121
if err != nil {
122122
return nil, fmt.Errorf("failed to find Aspire app host: %w", err)
123-
}
123+
} else if appHost != nil {
124+
manifest, err := c.dotnetImporter.ReadManifest(ctx, appHost)
125+
if err != nil {
126+
return nil, fmt.Errorf("reading app host manifest: %w", err)
127+
}
124128

125-
manifest, err := c.dotnetImporter.ReadManifest(ctx, appHost)
126-
if err != nil {
127-
return nil, fmt.Errorf("reading app host manifest: %w", err)
128-
}
129+
ret.Services = servicesFromManifest(manifest)
129130

130-
ret.Services = servicesFromManifest(manifest)
131+
return ret, nil
132+
}
131133

134+
ret.Services = servicesFromProjectConfig(ctx, c.projectConfig)
132135
return ret, nil
133136
}

cli/azd/internal/vsrpc/utils.go

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,25 @@ import (
1717
)
1818

1919
// appHostServiceForProject returns the ServiceConfig of the service for the AppHost project for the given azd project.
20+
//
21+
// If the project does not have an AppHost project, nil is returned.
2022
func appHostForProject(
2123
ctx context.Context, pc *project.ProjectConfig, dotnetCli *dotnet.Cli,
2224
) (*project.ServiceConfig, error) {
2325
for _, service := range pc.Services {
2426
if service.Language == project.ServiceLanguageDotNet {
2527
isAppHost, err := dotnetCli.IsAspireHostProject(ctx, service.Path())
2628
if err != nil {
27-
log.Printf("error checking if %s is an app host project: %v", service.Path(), err)
29+
return nil, fmt.Errorf("error checking if %s is an app host project: %w", service.Path(), err)
2830
}
31+
2932
if isAppHost {
3033
return service, nil
3134
}
3235
}
3336
}
3437

35-
return nil, fmt.Errorf("no app host project found for project: %s", pc.Name)
38+
return nil, nil
3639
}
3740

3841
func servicesFromManifest(manifest *apphost.Manifest) []*Service {
@@ -50,6 +53,19 @@ func servicesFromManifest(manifest *apphost.Manifest) []*Service {
5053
return services
5154
}
5255

56+
func servicesFromProjectConfig(ctx context.Context, pc *project.ProjectConfig) []*Service {
57+
var services []*Service
58+
59+
for _, service := range pc.Services {
60+
services = append(services, &Service{
61+
Name: service.Name,
62+
Path: service.Path(),
63+
})
64+
}
65+
66+
return services
67+
}
68+
5369
// azdContext resolves the azd context directory to use.
5470
//
5571
// - If the host project directory contains azure.yaml, the host project directory is used.
@@ -77,16 +93,16 @@ func azdContext(hostProjectPath string) (*azdcontext.AzdContext, error) {
7793
return nil, err
7894
}
7995

96+
found := false
8097
for _, svc := range prjConfig.Services {
81-
if svc.Language == project.ServiceLanguageDotNet && svc.Host == project.ContainerAppTarget {
82-
if svc.Path() != hostProjectPath {
83-
log.Printf("ignoring %s due to mismatch, using app host directory", azdCtx.ProjectPath())
84-
return azdcontext.NewAzdContextWithDirectory(hostProjectDir), nil
85-
}
98+
if svc.Path() == hostProjectPath {
99+
found = true
86100
}
101+
}
87102

88-
// there can only be one app host project
89-
break
103+
if !found {
104+
log.Printf("ignoring %s due to non-matching project found, using app host directory", azdCtx.ProjectPath())
105+
return azdcontext.NewAzdContextWithDirectory(hostProjectDir), nil
90106
}
91107

92108
log.Printf("use nearest directory: %s", azdCtx.ProjectDirectory())

0 commit comments

Comments
 (0)