diff --git a/cli/azd/internal/appdetect/appdetect.go b/cli/azd/internal/appdetect/appdetect.go index e6103d3cbd7..dc1b33841d4 100644 --- a/cli/azd/internal/appdetect/appdetect.go +++ b/cli/azd/internal/appdetect/appdetect.go @@ -13,6 +13,7 @@ import ( "path/filepath" "github.com/azure/azure-dev/cli/azd/pkg/exec" + "github.com/azure/azure-dev/cli/azd/pkg/osutil" "github.com/azure/azure-dev/cli/azd/pkg/tools/dotnet" "github.com/bmatcuk/doublestar/v4" ) @@ -167,8 +168,9 @@ type Port struct { } type Docker struct { - Path string - Ports []Port + Path string + Ports []Port + BuildArgs []osutil.ExpandableString } type projectDetector interface { diff --git a/cli/azd/internal/repository/app_init.go b/cli/azd/internal/repository/app_init.go index cb211bc14b1..afbe32a3c2b 100644 --- a/cli/azd/internal/repository/app_init.go +++ b/cli/azd/internal/repository/app_init.go @@ -1,6 +1,7 @@ package repository import ( + "bufio" "context" "fmt" "maps" @@ -44,6 +45,34 @@ var dbMap = map[appdetect.DatabaseDep]struct{}{ var featureCompose = alpha.MustFeatureKey("compose") +// parseDockerfileForArgs parses a Dockerfile to extract ARG instructions and returns them as ExpandableString values. +func parseDockerfileForArgs(dockerfilePath string) ([]osutil.ExpandableString, error) { + var buildArgs []osutil.ExpandableString + + file, err := os.Open(dockerfilePath) + if err != nil { + return nil, fmt.Errorf("failed to open Dockerfile: %w", err) + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := strings.TrimSpace(scanner.Text()) + if strings.HasPrefix(line, "ARG ") { + argLine := strings.TrimPrefix(line, "ARG ") + if len(argLine) > 0 { + buildArgs = append(buildArgs, osutil.NewExpandableString(argLine)) + } + } + } + + if err := scanner.Err(); err != nil { + return nil, fmt.Errorf("error reading Dockerfile: %w", err) + } + + return buildArgs, nil +} + // InitFromApp initializes the infra directory and project file from the current existing app. func (i *Initializer) InitFromApp( ctx context.Context, @@ -264,6 +293,23 @@ func (i *Initializer) InitFromApp( } } + for idx := range detect.Services { + servicePath := detect.Services[idx].Path + dockerfilePath := filepath.Join(servicePath, "Dockerfile") + + if _, err := os.Stat(dockerfilePath); err == nil { + + buildArgs, err := parseDockerfileForArgs(dockerfilePath) + if err != nil { + return fmt.Errorf("failed to parse Dockerfile ARGs at %s: %w", dockerfilePath, err) + } + + if len(buildArgs) > 0 { + detect.Services[idx].Docker.BuildArgs = buildArgs + } + } + } + tracing.SetUsageAttributes(fields.AppInitLastStep.String("generate")) title = "Generating " + output.WithHighLightFormat("./"+azdcontext.ProjectFileName) @@ -544,7 +590,8 @@ func ServiceFromDetect( } svc.Docker = project.DockerProjectOptions{ - Path: relDocker, + Path: relDocker, + BuildArgs: prj.Docker.BuildArgs, } } diff --git a/cli/azd/internal/repository/app_init_test.go b/cli/azd/internal/repository/app_init_test.go index 6a0b7a7dac6..632c0147bcf 100644 --- a/cli/azd/internal/repository/app_init_test.go +++ b/cli/azd/internal/repository/app_init_test.go @@ -11,6 +11,7 @@ import ( "github.com/azure/azure-dev/cli/azd/internal" "github.com/azure/azure-dev/cli/azd/internal/appdetect" "github.com/azure/azure-dev/cli/azd/pkg/input" + "github.com/azure/azure-dev/cli/azd/pkg/osutil" "github.com/azure/azure-dev/cli/azd/pkg/project" "github.com/stretchr/testify/require" ) @@ -93,7 +94,13 @@ func TestInitializer_prjConfigFromDetect(t *testing.T) { { Language: appdetect.DotNet, Path: "dotnet", - Docker: &appdetect.Docker{Path: "Dockerfile"}, + Docker: &appdetect.Docker{ + Path: "Dockerfile", + BuildArgs: []osutil.ExpandableString{ + osutil.NewExpandableString("ARG1"), + osutil.NewExpandableString("ARG2"), + }, + }, }, }, }, @@ -112,6 +119,10 @@ func TestInitializer_prjConfigFromDetect(t *testing.T) { RelativePath: "dotnet", Docker: project.DockerProjectOptions{ Path: "Dockerfile", + BuildArgs: []osutil.ExpandableString{ + osutil.NewExpandableString("ARG1"), + osutil.NewExpandableString("ARG2"), + }, }, }, },