From 371c1371791c9dc1add7e1cadcaf68c547e23144 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Tue, 29 Apr 2025 21:42:31 +0000 Subject: [PATCH 01/20] remove setting from sample projects and create a note about it for backwards compatibility --- cli/azd/pkg/environment/environment.go | 9 +++++++++ cli/azd/resources/pipeline/.azdo/azure-dev-tf.yml | 1 - cli/azd/resources/pipeline/.github/azure-dev-tf.yml | 1 - templates/common/.azdo/pipelines/bicep/azure-dev.yml | 1 - templates/common/.azdo/pipelines/java/azure-dev.yml | 1 - .../common/.azdo/pipelines/nodejs/aks/azure-dev.yml | 1 - templates/common/.azdo/pipelines/terraform/azure-dev.yml | 1 - .../common/.azdo/pipelines/terraform/java/azure-dev.yml | 1 - templates/common/.github/workflows/bicep/azure-dev.yml | 2 -- templates/common/.github/workflows/func/azure-dev.yml | 1 - templates/common/.github/workflows/java/azure-dev.yml | 1 - .../.github/workflows/java/terraform/azure-dev.yml | 1 - .../common/.github/workflows/nodejs/aks/azure-dev.yml | 1 - .../common/.github/workflows/nodejs/bicep/azure-dev.yml | 1 - .../common/.github/workflows/nodejs/func/azure-dev.yml | 1 - .../.github/workflows/nodejs/terraform/azure-dev.yml | 1 - .../common/.github/workflows/terraform/azure-dev.yml | 1 - 17 files changed, 9 insertions(+), 17 deletions(-) diff --git a/cli/azd/pkg/environment/environment.go b/cli/azd/pkg/environment/environment.go index 170e58decfe..4882c4495a7 100644 --- a/cli/azd/pkg/environment/environment.go +++ b/cli/azd/pkg/environment/environment.go @@ -66,6 +66,15 @@ type Environment struct { Config config.Config } +// AzdInitialEnvironmentConfigName is part of a strategy to re-construct AZD environment in CI/CD from an initial state. +// This strategy was introduced for templates which takes input parameters. Parameters are saved to azd's environment +// configuration (.azure/env-name/config.json). This file is not committed to source control, so the saved values can't +// be used during CI/CD. AZD uses AZD_INITIAL_ENVIRONMENT_CONFIG to smuggle all saved parameters into a CI/CD secret and +// use it to create the environment configuration file (the first time AZD runs and creates a new environment). +// +// While AZD_INITIAL_ENVIRONMENT_CONFIG is still supported for backwards compatibility, it is deprecated. +// The currently strategy is to create individual variables or secrets for the CI/CD pipeline depending on the parameter +// configuration. const AzdInitialEnvironmentConfigName = "AZD_INITIAL_ENVIRONMENT_CONFIG" // New returns a new environment with the specified name. diff --git a/cli/azd/resources/pipeline/.azdo/azure-dev-tf.yml b/cli/azd/resources/pipeline/.azdo/azure-dev-tf.yml index abbe56c9561..c3aa3f49c1b 100644 --- a/cli/azd/resources/pipeline/.azdo/azure-dev-tf.yml +++ b/cli/azd/resources/pipeline/.azdo/azure-dev-tf.yml @@ -47,7 +47,6 @@ steps: RS_RESOURCE_GROUP: $(RS_RESOURCE_GROUP) RS_STORAGE_ACCOUNT: $(RS_STORAGE_ACCOUNT) RS_CONTAINER_NAME: $(RS_CONTAINER_NAME) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(secrets.AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application diff --git a/cli/azd/resources/pipeline/.github/azure-dev-tf.yml b/cli/azd/resources/pipeline/.github/azure-dev-tf.yml index daa8b7ec4ee..1f390d80bd3 100644 --- a/cli/azd/resources/pipeline/.github/azure-dev-tf.yml +++ b/cli/azd/resources/pipeline/.github/azure-dev-tf.yml @@ -61,7 +61,6 @@ jobs: RS_RESOURCE_GROUP: ${{ vars.RS_RESOURCE_GROUP }} RS_STORAGE_ACCOUNT: ${{ vars.RS_STORAGE_ACCOUNT }} RS_CONTAINER_NAME: ${{ vars.RS_CONTAINER_NAME }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.azdo/pipelines/bicep/azure-dev.yml b/templates/common/.azdo/pipelines/bicep/azure-dev.yml index 96ff1d5a0c8..d6f82d9d829 100644 --- a/templates/common/.azdo/pipelines/bicep/azure-dev.yml +++ b/templates/common/.azdo/pipelines/bicep/azure-dev.yml @@ -41,7 +41,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(secrets.AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application diff --git a/templates/common/.azdo/pipelines/java/azure-dev.yml b/templates/common/.azdo/pipelines/java/azure-dev.yml index cc9f0a02244..815ee04a6d7 100644 --- a/templates/common/.azdo/pipelines/java/azure-dev.yml +++ b/templates/common/.azdo/pipelines/java/azure-dev.yml @@ -47,7 +47,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(secrets.AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application diff --git a/templates/common/.azdo/pipelines/nodejs/aks/azure-dev.yml b/templates/common/.azdo/pipelines/nodejs/aks/azure-dev.yml index 130f7d40e60..677cb9b12e2 100644 --- a/templates/common/.azdo/pipelines/nodejs/aks/azure-dev.yml +++ b/templates/common/.azdo/pipelines/nodejs/aks/azure-dev.yml @@ -64,7 +64,6 @@ steps: AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) AZURE_PRINCIPAL_TYPE: $(AZURE_PRINCIPAL_TYPE) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(secrets.AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application diff --git a/templates/common/.azdo/pipelines/terraform/azure-dev.yml b/templates/common/.azdo/pipelines/terraform/azure-dev.yml index 4a39d574891..808de69fc37 100644 --- a/templates/common/.azdo/pipelines/terraform/azure-dev.yml +++ b/templates/common/.azdo/pipelines/terraform/azure-dev.yml @@ -47,7 +47,6 @@ steps: RS_RESOURCE_GROUP: $(RS_RESOURCE_GROUP) RS_STORAGE_ACCOUNT: $(RS_STORAGE_ACCOUNT) RS_CONTAINER_NAME: $(RS_CONTAINER_NAME) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(secrets.AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application diff --git a/templates/common/.azdo/pipelines/terraform/java/azure-dev.yml b/templates/common/.azdo/pipelines/terraform/java/azure-dev.yml index 16f63540299..8c847f27298 100644 --- a/templates/common/.azdo/pipelines/terraform/java/azure-dev.yml +++ b/templates/common/.azdo/pipelines/terraform/java/azure-dev.yml @@ -53,7 +53,6 @@ steps: RS_RESOURCE_GROUP: $(RS_RESOURCE_GROUP) RS_STORAGE_ACCOUNT: $(RS_STORAGE_ACCOUNT) RS_CONTAINER_NAME: $(RS_CONTAINER_NAME) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(secrets.AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application diff --git a/templates/common/.github/workflows/bicep/azure-dev.yml b/templates/common/.github/workflows/bicep/azure-dev.yml index 10a705f3017..2e70116bb15 100644 --- a/templates/common/.github/workflows/bicep/azure-dev.yml +++ b/templates/common/.github/workflows/bicep/azure-dev.yml @@ -57,8 +57,6 @@ jobs: - name: Provision Infrastructure run: azd provision --no-prompt - env: - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/func/azure-dev.yml b/templates/common/.github/workflows/func/azure-dev.yml index 4372940b2ee..3dd8a16c757 100644 --- a/templates/common/.github/workflows/func/azure-dev.yml +++ b/templates/common/.github/workflows/func/azure-dev.yml @@ -65,7 +65,6 @@ jobs: AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/java/azure-dev.yml b/templates/common/.github/workflows/java/azure-dev.yml index ed41fc4a70c..bb0567f7c13 100644 --- a/templates/common/.github/workflows/java/azure-dev.yml +++ b/templates/common/.github/workflows/java/azure-dev.yml @@ -68,7 +68,6 @@ jobs: AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/java/terraform/azure-dev.yml b/templates/common/.github/workflows/java/terraform/azure-dev.yml index 0363acb735e..a87daaec3be 100644 --- a/templates/common/.github/workflows/java/terraform/azure-dev.yml +++ b/templates/common/.github/workflows/java/terraform/azure-dev.yml @@ -69,7 +69,6 @@ jobs: RS_RESOURCE_GROUP: ${{ vars.RS_RESOURCE_GROUP }} RS_STORAGE_ACCOUNT: ${{ vars.RS_STORAGE_ACCOUNT }} RS_CONTAINER_NAME: ${{ vars.RS_CONTAINER_NAME }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/nodejs/aks/azure-dev.yml b/templates/common/.github/workflows/nodejs/aks/azure-dev.yml index bccd3611d1c..065ab4c38da 100644 --- a/templates/common/.github/workflows/nodejs/aks/azure-dev.yml +++ b/templates/common/.github/workflows/nodejs/aks/azure-dev.yml @@ -90,7 +90,6 @@ jobs: AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/nodejs/bicep/azure-dev.yml b/templates/common/.github/workflows/nodejs/bicep/azure-dev.yml index 42cbdd732dd..8b0cb41dcb1 100644 --- a/templates/common/.github/workflows/nodejs/bicep/azure-dev.yml +++ b/templates/common/.github/workflows/nodejs/bicep/azure-dev.yml @@ -65,7 +65,6 @@ jobs: AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/nodejs/func/azure-dev.yml b/templates/common/.github/workflows/nodejs/func/azure-dev.yml index cf1c9aa97b7..87d7e521d51 100644 --- a/templates/common/.github/workflows/nodejs/func/azure-dev.yml +++ b/templates/common/.github/workflows/nodejs/func/azure-dev.yml @@ -70,7 +70,6 @@ jobs: AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/nodejs/terraform/azure-dev.yml b/templates/common/.github/workflows/nodejs/terraform/azure-dev.yml index 338e15985ea..81d7a7eda81 100644 --- a/templates/common/.github/workflows/nodejs/terraform/azure-dev.yml +++ b/templates/common/.github/workflows/nodejs/terraform/azure-dev.yml @@ -61,7 +61,6 @@ jobs: RS_RESOURCE_GROUP: ${{ vars.RS_RESOURCE_GROUP }} RS_STORAGE_ACCOUNT: ${{ vars.RS_STORAGE_ACCOUNT }} RS_CONTAINER_NAME: ${{ vars.RS_CONTAINER_NAME }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/templates/common/.github/workflows/terraform/azure-dev.yml b/templates/common/.github/workflows/terraform/azure-dev.yml index 338e15985ea..81d7a7eda81 100644 --- a/templates/common/.github/workflows/terraform/azure-dev.yml +++ b/templates/common/.github/workflows/terraform/azure-dev.yml @@ -61,7 +61,6 @@ jobs: RS_RESOURCE_GROUP: ${{ vars.RS_RESOURCE_GROUP }} RS_STORAGE_ACCOUNT: ${{ vars.RS_STORAGE_ACCOUNT }} RS_CONTAINER_NAME: ${{ vars.RS_CONTAINER_NAME }} - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt From 2a6a6fb52c8bbe3030cb168887409643ed8b379f Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Tue, 29 Apr 2025 23:13:46 +0000 Subject: [PATCH 02/20] remove the need of need for deployment param. This is not required after fixing the parameters mapping to env vars resolution --- cli/azd/pkg/apphost/generate.go | 2 -- cli/azd/pkg/azure/arm_template.go | 1 - .../infra/provisioning/bicep/bicep_provider.go | 16 ---------------- 3 files changed, 19 deletions(-) diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index 1769b124f69..12023b8f026 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -337,8 +337,6 @@ func BicepTemplate(name string, manifest *Manifest, options AppHostOptions) (*me // if not nil, like empty string or any other string, it is used as `= ''` if parameter.Default.Value != nil { parameterDefaultValue = parameter.Default.Value - metadataType = azure.AzdMetadataTypeNeedForDeploy - parameterMetadata = "{}" } else if parameter.Default.Generate != nil { // Note: .Value and .Generate are mutually exclusive pMetadata, err := inputMetadata(*parameter.Default.Generate) if err != nil { diff --git a/cli/azd/pkg/azure/arm_template.go b/cli/azd/pkg/azure/arm_template.go index 6738ea76ac8..027c75a9a47 100644 --- a/cli/azd/pkg/azure/arm_template.go +++ b/cli/azd/pkg/azure/arm_template.go @@ -137,7 +137,6 @@ type AzdMetadataType string const AzdMetadataTypeLocation AzdMetadataType = "location" const AzdMetadataTypeGenerate AzdMetadataType = "generate" const AzdMetadataTypeGenerateOrManual AzdMetadataType = "generateOrManual" -const AzdMetadataTypeNeedForDeploy AzdMetadataType = "needForDeploy" const AzdMetadataTypeResourceGroup AzdMetadataType = "resourceGroup" type AzdMetadata struct { diff --git a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go index 407c2aa643d..2b6da7cfc25 100644 --- a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go +++ b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go @@ -2003,7 +2003,6 @@ func (p *BicepProvider) ensureParameters( azdMetadata, hasMetadata := param.AzdMetadata() // If a value is explicitly configured via a parameters file, use it. - // unless the parameter value inference is nil/empty if v, has := parameters[key]; has { // Directly pass through Key Vault references without prompting. if v.KeyVaultReference != nil { @@ -2027,24 +2026,9 @@ func (p *BicepProvider) ensureParameters( } } - needForDeployParameter := hasMetadata && - azdMetadata.Type != nil && - *azdMetadata.Type == azure.AzdMetadataTypeNeedForDeploy - if needForDeployParameter && paramValue == "" && param.DefaultValue != nil { - // Parameters with needForDeploy metadata don't support overriding with empty values when a default - // value is present. If the value is empty, we'll use the default value instead. - defValue, castOk := param.DefaultValue.(string) - if castOk { - paramValue = defValue - } - } configuredParameters[key] = azure.ArmParameter{ Value: paramValue, } - if needForDeployParameter { - mustSetParamAsConfig(key, paramValue, p.env.Config, param.Secure()) - configModified = true - } continue } } From 56e5296a79d88e662b83d760affa85ae118d0a89 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Tue, 29 Apr 2025 23:14:22 +0000 Subject: [PATCH 03/20] allow using prefixed env vars during azd deploy for Aspire (dotnet + containerapp) --- .../service_target_dotnet_containerapp.go | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index c9c660c5f8c..c01a123a1c4 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -290,13 +290,31 @@ func (at *dotnetContainerAppTarget) Deploy( return nil, fmt.Errorf("failing parsing manifest template: %w", err) } + // Both bicepparam and yaml go-template can reference all variables from AZD environment and those variables + // from system environment variables that are prefixed either AZURE_ or AZD_ + // Variables from AZD environment override those from system environment variables. + env := make(map[string]string) + for _, envVar := range os.Environ() { + parts := strings.SplitN(envVar, "=", 2) + if len(parts) != 2 { + continue + } + if strings.HasPrefix(parts[0], "AZURE_") || strings.HasPrefix(parts[0], "AZD_") { + env[parts[0]] = parts[1] + } + } + // Add the environment variables from the azd environment + for key, value := range at.env.Dotenv() { + env[key] = value + } + builder := strings.Builder{} err = tmpl.Execute(&builder, struct { Env map[string]string Image string Inputs map[string]any }{ - Env: at.env.Dotenv(), + Env: env, Image: remoteImageName, Inputs: inputs, }) From d108984eba3c8d88560e85bf1c5b8e2b8f46421b Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Tue, 29 Apr 2025 23:51:55 +0000 Subject: [PATCH 04/20] Link parameters with default value to outputs in bicep generation --- cli/azd/internal/scaffold/funcs.go | 8 ++++++-- cli/azd/pkg/apphost/generate.go | 5 +++-- .../TestAspireContainerGeneration-main.bicep.snap | 12 ++---------- cli/azd/resources/apphost/templates/main.bicept | 5 +++++ .../testdata/snaps/aspire-full/infra/main.bicep | 6 +----- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/cli/azd/internal/scaffold/funcs.go b/cli/azd/internal/scaffold/funcs.go index a6e6fe7d98a..aa48e203794 100644 --- a/cli/azd/internal/scaffold/funcs.go +++ b/cli/azd/internal/scaffold/funcs.go @@ -210,8 +210,12 @@ var camelCaseRegex = regexp.MustCompile(`([a-z0-9])([A-Z])`) // EnvFormat takes an input parameter like `fooParam` which is expected to be in camel case and returns it in // upper snake case with env var template, like `${AZURE_FOO_PARAM}`. func EnvFormat(src string) string { - snake := strings.ReplaceAll(strings.ToUpper(camelCaseRegex.ReplaceAllString(src, "${1}_${2}")), "-", "_") - return fmt.Sprintf("${AZURE_%s}", snake) + return fmt.Sprintf("${%s}", AzureSnakeCase(src)) +} + +func AzureSnakeCase(src string) string { + return fmt.Sprintf( + "AZURE_%s", strings.ReplaceAll(strings.ToUpper(camelCaseRegex.ReplaceAllString(src, "${1}_${2}")), "-", "_")) } func HasACA(services []ServiceSpec) bool { diff --git a/cli/azd/pkg/apphost/generate.go b/cli/azd/pkg/apphost/generate.go index 12023b8f026..ab5c49718ba 100644 --- a/cli/azd/pkg/apphost/generate.go +++ b/cli/azd/pkg/apphost/generate.go @@ -89,8 +89,9 @@ func init() { "bicepParameterName": func(src string) string { return strings.ReplaceAll(src, "-", "_") }, - "removeDot": scaffold.RemoveDotAndDash, - "envFormat": scaffold.EnvFormat, + "removeDot": scaffold.RemoveDotAndDash, + "envFormat": scaffold.EnvFormat, + "azureSnakeCase": scaffold.AzureSnakeCase, "bicepParameterValue": func(value *string) string { if value == nil { return "" diff --git a/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap b/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap index 8df5b524cca..5b904777991 100644 --- a/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap +++ b/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap @@ -54,17 +54,7 @@ param noVolume_pas_sw_ord string }) @secure() param noVolume_password string -@metadata({azd: { - type: 'needForDeploy' - config: {} - } -}) param param_with_empty_value string = '' -@metadata({azd: { - type: 'needForDeploy' - config: {} - } -}) param param_with_value string = 'default value for param' var tags = { @@ -100,4 +90,6 @@ output SERVICE_NOVOLUME_FILE_SHARE_BM0_NAME string = resources.outputs.SERVICE_N output SERVICE_NOVOLUME_VOLUME_BM1_NAME string = resources.outputs.SERVICE_NOVOLUME_VOLUME_BM1_NAME output SERVICE_NOVOLUME_FILE_SHARE_BM1_NAME string = resources.outputs.SERVICE_NOVOLUME_FILE_SHARE_BM1_NAME output AZURE_VOLUMES_STORAGE_ACCOUNT string = resources.outputs.AZURE_VOLUMES_STORAGE_ACCOUNT +output AZURE_PARAM_WITH_EMPTY_VALUE = param-with-empty-value +output AZURE_PARAM_WITH_VALUE = param-with-value diff --git a/cli/azd/resources/apphost/templates/main.bicept b/cli/azd/resources/apphost/templates/main.bicept index 9f90a32ad24..1a0cacb09b9 100644 --- a/cli/azd/resources/apphost/templates/main.bicept +++ b/cli/azd/resources/apphost/templates/main.bicept @@ -100,4 +100,9 @@ output AZURE_VOLUMES_STORAGE_ACCOUNT string = resources.outputs.AZURE_VOLUMES_ST {{range $param, $value := .OutputParameters -}} output {{bicepParameterName $param}} {{$value.Type}} = {{bicepParameterName $value.Value}} {{end -}} +{{range $parameter := .WithMetadataParameters -}} +{{if $parameter.Value -}} +output {{azureSnakeCase $parameter.Name}} {{$parameter.Type}} = {{$parameter.Name}} +{{end -}} +{{end -}} {{ end}} diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep index 1208d4970b3..ccbf69bb4bd 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep @@ -12,11 +12,6 @@ param location string @description('Id of the user or app to assign application roles') param principalId string = '' -@metadata({azd: { - type: 'needForDeploy' - config: {} - } -}) param goversion string = '1.22' var tags = { @@ -60,4 +55,5 @@ output AZURE_CONTAINER_APPS_ENVIRONMENT_DEFAULT_DOMAIN string = resources.output output STORAGE_BLOBENDPOINT string = storage.outputs.blobEndpoint output STORAGE_QUEUEENDPOINT string = storage.outputs.queueEndpoint output STORAGE_TABLEENDPOINT string = storage.outputs.tableEndpoint +output AZURE_GOVERSION string = goversion From cd82e621c5e2c5aea138015bf4fbeb7a92235c78 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Tue, 29 Apr 2025 23:59:28 +0000 Subject: [PATCH 05/20] fix generating the name for env var mapping --- cli/azd/pkg/project/service_target_dotnet_containerapp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index c01a123a1c4..9c3149431e1 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -604,7 +604,7 @@ const infraParametersKey = "infra.parameters." // Parameter resolves the name of a parameter defined in the ACA yaml definition. The parameter can be mapped to a system // environment variable or persisted in the azd environment configuration. func (fns *containerAppTemplateManifestFuncs) Parameter(name string) (string, error) { - envVarMapping := scaffold.EnvFormat(name) + envVarMapping := scaffold.AzureSnakeCase(name) // map only to system environment variables. Not adding support for mapping to azd environment by design (b/c // parameters could be secured) if val, found := os.LookupEnv(envVarMapping); found { @@ -626,7 +626,7 @@ func (fns *containerAppTemplateManifestFuncs) Parameter(name string) (string, er // ParameterWithDefault resolves the name of a parameter defined in the ACA yaml definition. // The parameter can be mapped to a system environment variable or be default to a value directly. func (fns *containerAppTemplateManifestFuncs) ParameterWithDefault(name string, defaultValue string) (string, error) { - envVarMapping := scaffold.EnvFormat(name) + envVarMapping := scaffold.AzureSnakeCase(name) // map only to system environment variables. Not adding support for mapping to azd environment by design (b/c // parameters could be secured) if val, found := os.LookupEnv(envVarMapping); found { From f2371d86a233304dcf52149d95f4637d4a152f8b Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Wed, 30 Apr 2025 00:06:27 +0000 Subject: [PATCH 06/20] ParameterWithDefault can use azd env as state --- cli/azd/pkg/project/service_target_dotnet_containerapp.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/cli/azd/pkg/project/service_target_dotnet_containerapp.go b/cli/azd/pkg/project/service_target_dotnet_containerapp.go index 9c3149431e1..db16d448e93 100644 --- a/cli/azd/pkg/project/service_target_dotnet_containerapp.go +++ b/cli/azd/pkg/project/service_target_dotnet_containerapp.go @@ -602,7 +602,7 @@ func (_ *containerAppTemplateManifestFuncs) UrlHost(s string) (string, error) { const infraParametersKey = "infra.parameters." // Parameter resolves the name of a parameter defined in the ACA yaml definition. The parameter can be mapped to a system -// environment variable or persisted in the azd environment configuration. +// environment variable ONLY. func (fns *containerAppTemplateManifestFuncs) Parameter(name string) (string, error) { envVarMapping := scaffold.AzureSnakeCase(name) // map only to system environment variables. Not adding support for mapping to azd environment by design (b/c @@ -627,9 +627,7 @@ func (fns *containerAppTemplateManifestFuncs) Parameter(name string) (string, er // The parameter can be mapped to a system environment variable or be default to a value directly. func (fns *containerAppTemplateManifestFuncs) ParameterWithDefault(name string, defaultValue string) (string, error) { envVarMapping := scaffold.AzureSnakeCase(name) - // map only to system environment variables. Not adding support for mapping to azd environment by design (b/c - // parameters could be secured) - if val, found := os.LookupEnv(envVarMapping); found { + if val, found := fns.env.LookupEnv(envVarMapping); found { return val, nil } return defaultValue, nil From 927b734fb52a07f9d32031f94c12fb1955883afc Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Wed, 30 Apr 2025 17:39:13 +0000 Subject: [PATCH 07/20] wip --- .../provisioning/bicep/bicep_provider.go | 50 +++++++++++++++++++ cli/azd/pkg/infra/provisioning/manager.go | 8 +++ cli/azd/pkg/infra/provisioning/provider.go | 8 +++ .../terraform/terraform_provider.go | 4 ++ cli/azd/pkg/pipeline/pipeline_manager.go | 11 ++-- 5 files changed, 75 insertions(+), 6 deletions(-) diff --git a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go index 2b6da7cfc25..ad12f91c61f 100644 --- a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go +++ b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go @@ -1524,6 +1524,13 @@ func (p *BicepProvider) createOutputParameters( type loadParametersResult struct { parameters map[string]azure.ArmParameter locationParams []string + // envMapping is a map of parameter name to environment variable names + // holds information about which parameters are mapped to which env vars for + // cases like "param": "${env:AZURE_FOO}-${env:AZURE_BAR}", envMapping will + // contain {"param": ["AZURE_FOO", "AZURE_BAR"]} + // This information is useful for setting a CI/CD automatically. Each env var + // will be set to the value of the parameter as variable or secret. + envMapping map[string][]string } // loadParameters reads the parameters file template for environment/module specified by Options, @@ -1561,6 +1568,7 @@ func (p *BicepProvider) loadParameters(ctx context.Context) (loadParametersResul parametersMappedToAzureLocation := []string{} resolvedParams := map[string]azure.ArmParameter{} + envMapping := map[string][]string{} // resolving each parameter to keep track of the name during the resolution. // We used to resolve all the file before, supporting env var substitution at any part of the file. @@ -1568,6 +1576,7 @@ func (p *BicepProvider) loadParameters(ctx context.Context) (loadParametersResul // We also need to identify which parameters are mapped to AZURE_LOCATION (if any). // We also want to exclude parameters mapped to env vars which env var is not set (instead of using empty string). for paramName, param := range decodedParamsFile.Parameters { + mappedEnvVars := []string{} paramBytes, err := json.Marshal(param) if err != nil { return loadParametersResult{}, fmt.Errorf("error decoding deployment parameter %s: %w", paramName, err) @@ -1581,6 +1590,9 @@ func (p *BicepProvider) loadParameters(ctx context.Context) (loadParametersResul if name == environment.LocationEnvVarName { parametersMappedToAzureLocation = append(parametersMappedToAzureLocation, paramName) } + // principalId and locations are intentionally excluded from the mapped env vars as + // they are global env vars + mappedEnvVars = append(mappedEnvVars, name) if _, isDefined := p.env.LookupEnv(name); !isDefined { hasUnsetEnvVar = true } @@ -1589,6 +1601,7 @@ func (p *BicepProvider) loadParameters(ctx context.Context) (loadParametersResul if err != nil { return loadParametersResult{}, fmt.Errorf("substituting environment variables for %s: %w", paramName, err) } + envMapping[paramName] = mappedEnvVars // resolve `secretOrRandomPassword` -> this is a way to ask AZD to generate a password for the user and // store it in a Key Vault. But if the Key Vault and secret exists, AZD just takes the secret from there. if cmdsubst.ContainsCommandInvocation(replaced, cmdsubst.SecretOrRandomPasswordCommandName) { @@ -1634,6 +1647,7 @@ func (p *BicepProvider) loadParameters(ctx context.Context) (loadParametersResul return loadParametersResult{ parameters: resolvedParams, locationParams: parametersMappedToAzureLocation, + envMapping: envMapping, }, nil } @@ -2277,3 +2291,39 @@ func NewBicepProvider( azureClient: azureClient, } } + +func (p *BicepProvider) Parameters(ctx context.Context) ([]provisioning.Parameter, error) { + modulePath := p.modulePath() + compileResult, err := p.compileBicep(ctx, modulePath) + if err != nil { + return nil, fmt.Errorf("creating template: %w", err) + } + // templateParameters are the parameters defined in the bicep template. We know when a parameter is secured, + // its type and its default value from this definition. + templateParameters := compileResult.Template.Parameters + + // parametersInfo contains the env vars mappings (from a parameters file). bicepparam is not supported yet. + parametersInfo, err := p.loadParameters(ctx) + if err != nil { + return nil, fmt.Errorf("loading parameters: %w", err) + } + + // resolved parameters contains the final value for the parameters after evaluating. The final value can be + // from env var, from default value or from user input (prompt). + resolvedParams, err := p.ensureParameters(ctx, compileResult.Template) + if err != nil { + return nil, fmt.Errorf("resolving parameters: %w", err) + } + + provisionParameters := make([]provisioning.Parameter, 0, len(templateParameters)) + for key, param := range templateParameters { + provisionParameters = append(provisionParameters, provisioning.Parameter{ + Name: key, + Secret: param.Secure(), + Value: resolvedParams[key].Value, + EnvVarMapping: parametersInfo.envMapping[key], + }) + } + + return provisionParameters, nil +} diff --git a/cli/azd/pkg/infra/provisioning/manager.go b/cli/azd/pkg/infra/provisioning/manager.go index bc972fef1ad..974a16af124 100644 --- a/cli/azd/pkg/infra/provisioning/manager.go +++ b/cli/azd/pkg/infra/provisioning/manager.go @@ -69,6 +69,14 @@ func (m *Manager) Initialize(ctx context.Context, projectPath string, options Op return m.provider.Initialize(ctx, projectPath, options) } +// Parameters gets the list of parameters and its value which will be used to provision the infrastructure. +func (m *Manager) Parameters(ctx context.Context) ([]Parameter, error) { + if m.provider == nil { + panic("called parameters() with provider not initialized. Make sure to call manager.Initialize() first.") + } + return m.provider.Parameters(ctx) +} + // Gets the latest deployment details for the specified scope func (m *Manager) State(ctx context.Context, options *StateOptions) (*StateResult, error) { result, err := m.provider.State(ctx, options) diff --git a/cli/azd/pkg/infra/provisioning/provider.go b/cli/azd/pkg/infra/provisioning/provider.go index f1094ec4661..87ffc5e2132 100644 --- a/cli/azd/pkg/infra/provisioning/provider.go +++ b/cli/azd/pkg/infra/provisioning/provider.go @@ -51,6 +51,13 @@ type StateResult struct { State *State } +type Parameter struct { + Name string + Secret bool + Value any + EnvVarMapping []string +} + type Provider interface { Name() string Initialize(ctx context.Context, projectPath string, options Options) error @@ -59,4 +66,5 @@ type Provider interface { Preview(ctx context.Context) (*DeployPreviewResult, error) Destroy(ctx context.Context, options DestroyOptions) (*DestroyResult, error) EnsureEnv(ctx context.Context) error + Parameters(ctx context.Context) ([]Parameter, error) } diff --git a/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go b/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go index 2757cb95d7d..25f22997ed6 100644 --- a/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go +++ b/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go @@ -765,3 +765,7 @@ type terraformChildModule struct { Resources []terraformResource `json:"resources"` ChildModules []terraformChildModule `json:"child_modules"` } + +func (t *TerraformProvider) Parameters(ctx context.Context) ([]provisioning.Parameter, error) { + return nil, nil +} diff --git a/cli/azd/pkg/pipeline/pipeline_manager.go b/cli/azd/pkg/pipeline/pipeline_manager.go index b2d1c2627b9..7c5a5bce266 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager.go +++ b/cli/azd/pkg/pipeline/pipeline_manager.go @@ -5,7 +5,6 @@ package pipeline import ( "context" - "encoding/json" "errors" "fmt" "html/template" @@ -391,13 +390,13 @@ func (pm *PipelineManager) Configure(ctx context.Context, projectName string) (r // Adding environment.AzdInitialEnvironmentConfigName as a secret to the pipeline as the base configuration for // whenever a new environment is created. This means loading the local environment config into a pipeline secret which // azd will use to restore the the config on CI - localEnvConfig, err := json.Marshal(pm.env.Config.ResolvedRaw()) - if err != nil { - return result, fmt.Errorf("failed to marshal environment config: %w", err) - } + // localEnvConfig, err := json.Marshal(pm.env.Config.ResolvedRaw()) + // if err != nil { + // return result, fmt.Errorf("failed to marshal environment config: %w", err) + // } defaultAzdSecrets := map[string]string{ - environment.AzdInitialEnvironmentConfigName: string(localEnvConfig), + // environment.AzdInitialEnvironmentConfigName: string(localEnvConfig), } defaultAzdVariables := map[string]string{} From 2e6d097d49298c56d6ec489749247848a5d31a38 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 01:02:00 +0000 Subject: [PATCH 08/20] ready to test --- cli/azd/cmd/pipeline.go | 7 +++ cli/azd/pkg/devcenter/provision_provider.go | 5 ++ .../provisioning/bicep/bicep_provider.go | 5 ++ cli/azd/pkg/infra/provisioning/provider.go | 2 + .../terraform/terraform_provider.go | 1 + .../infra/provisioning/test/test_provider.go | 5 ++ cli/azd/pkg/pipeline/pipeline.go | 63 ++++++++++++++++++- cli/azd/pkg/pipeline/pipeline_manager.go | 29 ++++----- cli/azd/pkg/pipeline/pipeline_test.go | 5 +- 9 files changed, 103 insertions(+), 19 deletions(-) diff --git a/cli/azd/cmd/pipeline.go b/cli/azd/cmd/pipeline.go index 92f39a55160..523e99b4d52 100644 --- a/cli/azd/cmd/pipeline.go +++ b/cli/azd/cmd/pipeline.go @@ -177,6 +177,13 @@ func (p *pipelineConfigAction) Run(ctx context.Context) (*actions.ActionResult, Title: fmt.Sprintf("Configure your %s pipeline", pipelineProviderName), }) + // Pull provider specific parameters + providerParameters, err := p.provisioningManager.Parameters(ctx) + if err != nil { + return nil, fmt.Errorf("failed to get parameters for provider %s: %w", pipelineProviderName, err) + } + p.manager.SetParameters(providerParameters) + pipelineResult, err := p.manager.Configure(ctx, p.projectConfig.Name) if err != nil { return nil, err diff --git a/cli/azd/pkg/devcenter/provision_provider.go b/cli/azd/pkg/devcenter/provision_provider.go index bc05e17ab0a..0b638065859 100644 --- a/cli/azd/pkg/devcenter/provision_provider.go +++ b/cli/azd/pkg/devcenter/provision_provider.go @@ -531,3 +531,8 @@ func hasInfraTemplates(path string) bool { return len(entries) > 0 } + +func (p *ProvisionProvider) Parameters(ctx context.Context) ([]provisioning.Parameter, error) { + // not supported (no-op) + return nil, nil +} diff --git a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go index ad12f91c61f..cfcda22c83f 100644 --- a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go +++ b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go @@ -2317,11 +2317,16 @@ func (p *BicepProvider) Parameters(ctx context.Context) ([]provisioning.Paramete provisionParameters := make([]provisioning.Parameter, 0, len(templateParameters)) for key, param := range templateParameters { + _, isPrompt := p.env.Config.Get(fmt.Sprintf("infra.parameters.%s", key)) provisionParameters = append(provisionParameters, provisioning.Parameter{ Name: key, Secret: param.Secure(), Value: resolvedParams[key].Value, EnvVarMapping: parametersInfo.envMapping[key], + // No env var mapping and param is persisted in env config infra.parameters means local prompt only + // If user set an env var mapping after a local prompt, the env var overrides the value persisted in config + // which turns local prompt false + LocalPrompt: isPrompt && len(parametersInfo.envMapping[key]) == 0, }) } diff --git a/cli/azd/pkg/infra/provisioning/provider.go b/cli/azd/pkg/infra/provisioning/provider.go index 87ffc5e2132..48ac424c368 100644 --- a/cli/azd/pkg/infra/provisioning/provider.go +++ b/cli/azd/pkg/infra/provisioning/provider.go @@ -56,6 +56,8 @@ type Parameter struct { Secret bool Value any EnvVarMapping []string + // true when the parameter value was set by the user from the command line (prompt) + LocalPrompt bool } type Provider interface { diff --git a/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go b/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go index 25f22997ed6..2c0fb92b025 100644 --- a/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go +++ b/cli/azd/pkg/infra/provisioning/terraform/terraform_provider.go @@ -767,5 +767,6 @@ type terraformChildModule struct { } func (t *TerraformProvider) Parameters(ctx context.Context) ([]provisioning.Parameter, error) { + // not supported (no-op) return nil, nil } diff --git a/cli/azd/pkg/infra/provisioning/test/test_provider.go b/cli/azd/pkg/infra/provisioning/test/test_provider.go index 6fc5a29933b..d5251072f22 100644 --- a/cli/azd/pkg/infra/provisioning/test/test_provider.go +++ b/cli/azd/pkg/infra/provisioning/test/test_provider.go @@ -131,6 +131,11 @@ func (p *TestProvider) Destroy( return &destroyResult, nil } +func (p *TestProvider) Parameters(ctx context.Context) ([]provisioning.Parameter, error) { + // not supported (no-op) + return nil, nil +} + func NewTestProvider( envManager environment.Manager, env *environment.Environment, diff --git a/cli/azd/pkg/pipeline/pipeline.go b/cli/azd/pkg/pipeline/pipeline.go index 5f350c29aa8..3c4d1a5e1a3 100644 --- a/cli/azd/pkg/pipeline/pipeline.go +++ b/cli/azd/pkg/pipeline/pipeline.go @@ -5,8 +5,10 @@ package pipeline import ( "context" + "encoding/json" "fmt" "maps" + "os" "path/filepath" "slices" @@ -103,6 +105,10 @@ type configurePipelineOptions struct { // projectSecrets are the keys defined on the project (azure.yaml) to be collected form the env and set it as // secrets in the CI provider when their values are not empty. projectSecrets []string + // providerParameters can be used to automatically set variables and secrets by the provisioning provider. + // This is useful for fully-managed scenarios like Aspire, where user is not manually defining the variables and secrets + // in the azure.yaml file. The provider can provide the parameters and values required in CI. + providerParameters []provisioning.Parameter } // CiProvider defines the base behavior for a continuous integration provider. @@ -136,13 +142,64 @@ type CiProvider interface { } // mergeProjectVariablesAndSecrets returns the list of variables and secrets to be used in the pipeline -// The initial values reference azd known values, which are merged with the ones defined on azure.yaml by the user. +// The initial values reference azd known values, which are merged with the ones defined on azure.yaml by the user and the +// provider parameters. func mergeProjectVariablesAndSecrets( projectVariables, projectSecrets []string, - initialVariables, initialSecrets, env map[string]string) (variables, secrets map[string]string) { + initialVariables, initialSecrets map[string]string, + providerParameters []provisioning.Parameter, + env map[string]string) (variables, secrets map[string]string, err error) { + + // initial state comes from the list of initial variables and secrets variables = maps.Clone(initialVariables) secrets = maps.Clone(initialSecrets) + // second override is based on the provider parameters + for _, parameter := range providerParameters { + envVarsCount := len(parameter.EnvVarMapping) + if envVarsCount == 0 && parameter.LocalPrompt { + return nil, nil, + fmt.Errorf("parameter %s got its value from a local prompt and it has not a mapped environment variable. "+ + "The local value can't be configured in CI without having a map to one ENV VAR. "+ + "Define a mapping for %s to one ENV VAR as part of the infra parameters definition", + parameter.Name, parameter.Name) + } + if envVarsCount > 1 { + // for parameters mapped to more than one ENV VAR, each env var becomes either a variable or a secret + for _, envVar := range parameter.EnvVarMapping { + // see if the env var is set in the system env or azd env + // NOTE: provider parameters have access to system env vars but not project env vars/secrets. + value := env[envVar] + if value == "" { + value = os.Getenv(envVar) + } + if value == "" { + // env var not set, ignore it + continue + } + if parameter.Secret { + secrets[envVar] = value + } else { + variables[envVar] = value + } + } + // nothing else to do for parameters mapped to multiple env vars + continue + } + // Param mapped to a single env var, use that ENV VAR to set the link in CI + // marshall the value to a string + value, err := json.Marshal(parameter.Value) + if err != nil { + return nil, nil, fmt.Errorf("failed to marshal parameter %s: %w", parameter.Name, err) + } + if parameter.Secret { + secrets[parameter.EnvVarMapping[0]] = string(value) + } else { + variables[parameter.EnvVarMapping[0]] = string(value) + } + } + + // Last override is based on the user explicitly defined variables and secrets for key, value := range env { if value == "" { // skip empty values @@ -156,7 +213,7 @@ func mergeProjectVariablesAndSecrets( } } - return variables, secrets + return variables, secrets, nil } const ( diff --git a/cli/azd/pkg/pipeline/pipeline_manager.go b/cli/azd/pkg/pipeline/pipeline_manager.go index 7c5a5bce266..6f58cc52fb0 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager.go +++ b/cli/azd/pkg/pipeline/pipeline_manager.go @@ -387,18 +387,7 @@ func (pm *PipelineManager) Configure(ctx context.Context, projectName string) (r return result, err } - // Adding environment.AzdInitialEnvironmentConfigName as a secret to the pipeline as the base configuration for - // whenever a new environment is created. This means loading the local environment config into a pipeline secret which - // azd will use to restore the the config on CI - // localEnvConfig, err := json.Marshal(pm.env.Config.ResolvedRaw()) - // if err != nil { - // return result, fmt.Errorf("failed to marshal environment config: %w", err) - // } - - defaultAzdSecrets := map[string]string{ - // environment.AzdInitialEnvironmentConfigName: string(localEnvConfig), - } - + defaultAzdSecrets := map[string]string{} defaultAzdVariables := map[string]string{} // If the user has set the resource group name as an environment variable, we need to pass it to the pipeline // as this likely means rg-deployment @@ -407,9 +396,12 @@ func (pm *PipelineManager) Configure(ctx context.Context, projectName string) (r } // Merge azd default variables and secrets with the ones defined on azure.yaml - pm.configOptions.variables, pm.configOptions.secrets = mergeProjectVariablesAndSecrets( + pm.configOptions.variables, pm.configOptions.secrets, err = mergeProjectVariablesAndSecrets( pm.configOptions.projectVariables, pm.configOptions.projectSecrets, - defaultAzdVariables, defaultAzdSecrets, pm.env.Dotenv()) + defaultAzdVariables, defaultAzdSecrets, pm.configOptions.providerParameters, pm.env.Dotenv()) + if err != nil { + return result, fmt.Errorf("failed to merge variables and secrets: %w", err) + } // resolve akvs secrets // For each akvs in the secrets array: @@ -1166,3 +1158,12 @@ func resolveSmr(smrArg string, projectConfig config.Config, userConfig config.Co // no smr configuration return nil } + +// SetParameters adds parameter configuration for the manager to use during pipeline config. +// Parameters passed here are automatically defined as variables or secrets in the pipeline without user explicitly +// defining them in the azure.yaml -> pipeline file. +// This is useful for provisioning providers to define a list of parameters that are required for the pipeline. +// If parameters is nil, it means that the pipeline manager should not set up any parameters automatically. +func (pm *PipelineManager) SetParameters(parameters []provisioning.Parameter) { + pm.configOptions.providerParameters = parameters +} diff --git a/cli/azd/pkg/pipeline/pipeline_test.go b/cli/azd/pkg/pipeline/pipeline_test.go index 0ca9dbfb4c1..cab72f86112 100644 --- a/cli/azd/pkg/pipeline/pipeline_test.go +++ b/cli/azd/pkg/pipeline/pipeline_test.go @@ -29,8 +29,9 @@ func Test_ConfigOptions_SecretsAndVars(t *testing.T) { } // Call the SecretsAndVars function - variables, secrets := mergeProjectVariablesAndSecrets( - projectVariables, projectSecrets, initialVariables, initialSecrets, env) + variables, secrets, err := mergeProjectVariablesAndSecrets( + projectVariables, projectSecrets, initialVariables, initialSecrets, nil, env) + assert.NoError(t, err) // Assert the expected results expectedVariables := map[string]string{ From 05e5ab9c669fad6ce2470f81f88a00802390c038 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 01:17:02 +0000 Subject: [PATCH 09/20] Configure Azure Developer Pipeline --- .../AspireAzdTests.AppHost.sln | 24 +++++++++++++++++++ .../AspireAzdTests.AppHost/Program.cs | 5 +++- 2 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln diff --git a/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln b/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln new file mode 100644 index 00000000000..8f8398201a5 --- /dev/null +++ b/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln @@ -0,0 +1,24 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.5.2.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspireAzdTests.AppHost", "AspireAzdTests.AppHost.csproj", "{4910A9C9-446F-C43C-34AE-C0FDBB84848C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {12AD2908-0B7B-4530-8DA6-99143A068AD6} + EndGlobalSection +EndGlobal diff --git a/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs b/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs index 891d296a6d3..5ce554fe3ab 100644 --- a/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs +++ b/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs @@ -5,6 +5,8 @@ // test param with default value var goVersion = builder.AddParameter("goversion", "1.22", publishValueAsDefault: true); +var goVersion2 = builder.AddParameter("goversion2"); + // redis instance the app will use for simple messages var redisPubSub = builder.AddRedis("pubsub"); @@ -38,6 +40,7 @@ .WithReference(messageQueue) .WithReference(apiservice) .WithReference(workerProj) - .WithEnvironment("GOVERSION", goVersion); + .WithEnvironment("GOVERSION", goVersion) + .WithEnvironment("GOVERSION2", goVersion2); builder.Build().Run(); From da82601f7aed5553f10ea5d413fd762cbb31c95f Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 01:19:05 +0000 Subject: [PATCH 10/20] fix error condition --- cli/azd/pkg/pipeline/pipeline.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cli/azd/pkg/pipeline/pipeline.go b/cli/azd/pkg/pipeline/pipeline.go index 3c4d1a5e1a3..15228efe444 100644 --- a/cli/azd/pkg/pipeline/pipeline.go +++ b/cli/azd/pkg/pipeline/pipeline.go @@ -157,12 +157,16 @@ func mergeProjectVariablesAndSecrets( // second override is based on the provider parameters for _, parameter := range providerParameters { envVarsCount := len(parameter.EnvVarMapping) - if envVarsCount == 0 && parameter.LocalPrompt { - return nil, nil, - fmt.Errorf("parameter %s got its value from a local prompt and it has not a mapped environment variable. "+ - "The local value can't be configured in CI without having a map to one ENV VAR. "+ - "Define a mapping for %s to one ENV VAR as part of the infra parameters definition", - parameter.Name, parameter.Name) + if envVarsCount == 0 { + if parameter.LocalPrompt { + return nil, nil, + fmt.Errorf("parameter %s got its value from a local prompt and it has not a mapped environment variable. "+ + "The local value can't be configured in CI without having a map to one ENV VAR. "+ + "Define a mapping for %s to one ENV VAR as part of the infra parameters definition", + parameter.Name, parameter.Name) + } + // env var == 0 AND no local prompt, ignore it + continue } if envVarsCount > 1 { // for parameters mapped to more than one ENV VAR, each env var becomes either a variable or a secret From 08fc120511a470493567ebf064c10dbd91584bee Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 01:22:15 +0000 Subject: [PATCH 11/20] fix unmarshall value --- cli/azd/pkg/pipeline/pipeline.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cli/azd/pkg/pipeline/pipeline.go b/cli/azd/pkg/pipeline/pipeline.go index 15228efe444..7b6f6486c64 100644 --- a/cli/azd/pkg/pipeline/pipeline.go +++ b/cli/azd/pkg/pipeline/pipeline.go @@ -196,10 +196,15 @@ func mergeProjectVariablesAndSecrets( if err != nil { return nil, nil, fmt.Errorf("failed to marshal parameter %s: %w", parameter.Name, err) } + var strValue string + if err := json.Unmarshal(value, &strValue); err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal parameter %s: %w", parameter.Name, err) + } + if parameter.Secret { - secrets[parameter.EnvVarMapping[0]] = string(value) + secrets[parameter.EnvVarMapping[0]] = strValue } else { - variables[parameter.EnvVarMapping[0]] = string(value) + variables[parameter.EnvVarMapping[0]] = strValue } } From d3e614eb99d9e2b1dad743c8b647248cc16b7337 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 01:30:01 +0000 Subject: [PATCH 12/20] remove solution --- .../AspireAzdTests.AppHost.sln | 24 ------------------- 1 file changed, 24 deletions(-) delete mode 100644 cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln diff --git a/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln b/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln deleted file mode 100644 index 8f8398201a5..00000000000 --- a/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/AspireAzdTests.AppHost.sln +++ /dev/null @@ -1,24 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.5.2.0 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspireAzdTests.AppHost", "AspireAzdTests.AppHost.csproj", "{4910A9C9-446F-C43C-34AE-C0FDBB84848C}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4910A9C9-446F-C43C-34AE-C0FDBB84848C}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {12AD2908-0B7B-4530-8DA6-99143A068AD6} - EndGlobalSection -EndGlobal From d8c62205d5ca5fdadaab3b74db9f63ea9654a7e2 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 04:27:34 +0000 Subject: [PATCH 13/20] move workflow auto creation to manager configure --- cli/azd/cmd/pipeline.go | 2 +- .../provisioning/bicep/bicep_provider.go | 4 + cli/azd/pkg/pipeline/pipeline.go | 8 +- cli/azd/pkg/pipeline/pipeline_manager.go | 196 ++++++++++++------ .../resources/pipeline/.azdo/azure-dev.ymlt | 1 - .../resources/pipeline/.github/azure-dev.ymlt | 3 +- 6 files changed, 148 insertions(+), 66 deletions(-) diff --git a/cli/azd/cmd/pipeline.go b/cli/azd/cmd/pipeline.go index 523e99b4d52..5500bc78b60 100644 --- a/cli/azd/cmd/pipeline.go +++ b/cli/azd/cmd/pipeline.go @@ -184,7 +184,7 @@ func (p *pipelineConfigAction) Run(ctx context.Context) (*actions.ActionResult, } p.manager.SetParameters(providerParameters) - pipelineResult, err := p.manager.Configure(ctx, p.projectConfig.Name) + pipelineResult, err := p.manager.Configure(ctx, p.projectConfig.Name, infra) if err != nil { return nil, err } diff --git a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go index cfcda22c83f..668c6880c2a 100644 --- a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go +++ b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go @@ -2317,6 +2317,10 @@ func (p *BicepProvider) Parameters(ctx context.Context) ([]provisioning.Paramete provisionParameters := make([]provisioning.Parameter, 0, len(templateParameters)) for key, param := range templateParameters { + if _, usingParam := resolvedParams[key]; !usingParam { + // No resolved param for this parameter definition. + continue + } _, isPrompt := p.env.Config.Get(fmt.Sprintf("infra.parameters.%s", key)) provisionParameters = append(provisionParameters, provisioning.Parameter{ Name: key, diff --git a/cli/azd/pkg/pipeline/pipeline.go b/cli/azd/pkg/pipeline/pipeline.go index 7b6f6486c64..5f21ec36eb1 100644 --- a/cli/azd/pkg/pipeline/pipeline.go +++ b/cli/azd/pkg/pipeline/pipeline.go @@ -160,9 +160,10 @@ func mergeProjectVariablesAndSecrets( if envVarsCount == 0 { if parameter.LocalPrompt { return nil, nil, - fmt.Errorf("parameter %s got its value from a local prompt and it has not a mapped environment variable. "+ - "The local value can't be configured in CI without having a map to one ENV VAR. "+ - "Define a mapping for %s to one ENV VAR as part of the infra parameters definition", + fmt.Errorf( + "parameter %s got its value from a local prompt and it has not a mapped environment variable. "+ + "The local value can't be configured in CI without having a map to one ENV VAR. "+ + "Define a mapping for %s to one ENV VAR as part of the infra parameters definition", parameter.Name, parameter.Name) } // env var == 0 AND no local prompt, ignore it @@ -320,4 +321,5 @@ type projectProperties struct { Variables []string Secrets []string RequiredAlphaFeatures []string + providerParameters []provisioning.Parameter } diff --git a/cli/azd/pkg/pipeline/pipeline_manager.go b/cli/azd/pkg/pipeline/pipeline_manager.go index 6f58cc52fb0..5b076f9e01e 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager.go +++ b/cli/azd/pkg/pipeline/pipeline_manager.go @@ -95,6 +95,7 @@ type PipelineManager struct { infra *project.Infra userConfigManager config.UserConfigManager keyVaultService keyvault.KeyVaultService + prjConfig *project.ProjectConfig } func NewPipelineManager( @@ -223,7 +224,10 @@ func servicePrincipal( // Configure is the main function from the pipeline manager which takes care // of creating or setting up the git project, the ci pipeline and the Azure connection. -func (pm *PipelineManager) Configure(ctx context.Context, projectName string) (result *PipelineConfigResult, err error) { +func (pm *PipelineManager) Configure( + ctx context.Context, projectName string, infra *project.Infra) (result *PipelineConfigResult, err error) { + pm.infra = infra + // check all required tools are installed requiredTools, err := pm.requiredTools(ctx) if err != nil { @@ -233,6 +237,61 @@ func (pm *PipelineManager) Configure(ctx context.Context, projectName string) (r return result, err } + // pipeline definition files + hasAppHost := pm.importManager.HasAppHost(ctx, pm.prjConfig) + + infraProvider, err := toInfraProviderType(string(pm.infra.Options.Provider)) + if err != nil { + return nil, err + } + + var requiredAlphaFeatures []string + if infra.IsCompose { + requiredAlphaFeatures = append(requiredAlphaFeatures, "compose") + } + // There are 2 possible options, for the git branch name, when running azd pipeline config: + // - There is not a git repo, so the branch name is empty. In this case, we default to "main". + // - There is a git repo and we can get the name of the current branch. + branchName := "main" + projectDir := pm.azdCtx.ProjectDirectory() + repoRoot, err := pm.gitCli.GetRepoRoot(ctx, projectDir) + if err != nil { + return nil, fmt.Errorf("getting git repo root: %w", err) + } + customBranchName, err := pm.gitCli.GetCurrentBranch(ctx, repoRoot) + // It is fine if we can't get the branch name, we will default to "main" + if err == nil { + branchName = customBranchName + } + + // default auth type for all providers + authType := AuthTypeFederated + if pm.args.PipelineAuthTypeName == "" && infraProvider == infraProviderTerraform { + // empty arg for auth and terraform forces client credentials, otherwise, it will be federated + authType = AuthTypeClientCredentials + } + + // Check and prompt for missing CI/CD files + err = pm.checkAndPromptForProviderFiles( + ctx, projectProperties{ + CiProvider: ciProviderType(strings.ToLower(pm.ciProvider.Name())), + RepoRoot: repoRoot, + InfraProvider: infraProvider, + HasAppHost: hasAppHost, + BranchName: branchName, + AuthType: authType, + Variables: pm.prjConfig.Pipeline.Variables, + Secrets: pm.prjConfig.Pipeline.Secrets, + RequiredAlphaFeatures: requiredAlphaFeatures, + providerParameters: pm.configOptions.providerParameters, + }) + if err != nil { + return nil, err + } + pm.configOptions.projectSecrets = slices.Clone(pm.prjConfig.Pipeline.Secrets) + pm.configOptions.projectVariables = slices.Clone(pm.prjConfig.Pipeline.Variables) + pm.configOptions.provisioningProvider = &infra.Options + userConfig, err := pm.userConfigManager.Load() if err != nil { return result, fmt.Errorf("loading user configuration: %w", err) @@ -244,7 +303,6 @@ func (pm *PipelineManager) Configure(ctx context.Context, projectName string) (r } } - infra := pm.infra // run pre-config validations. rootPath := pm.azdCtx.ProjectDirectory() updatedConfig, errorsFromPreConfig := pm.preConfigureCheck(ctx, infra.Options, rootPath) @@ -786,57 +844,59 @@ func (pm *PipelineManager) initialize(ctx context.Context, override string) erro if err != nil { return fmt.Errorf("Loading project configuration: %w", err) } - - infra, err := pm.importManager.ProjectInfrastructure(ctx, prjConfig) - if err != nil { - return err - } - defer func() { _ = infra.Cleanup() }() - pm.infra = infra - - hasAppHost := pm.importManager.HasAppHost(ctx, prjConfig) - - infraProvider, err := toInfraProviderType(string(pm.infra.Options.Provider)) - if err != nil { - return err - } - - var requiredAlphaFeatures []string - if infra.IsCompose { - requiredAlphaFeatures = append(requiredAlphaFeatures, "compose") - } - // There are 2 possible options, for the git branch name, when running azd pipeline config: - // - There is not a git repo, so the branch name is empty. In this case, we default to "main". - // - There is a git repo and we can get the name of the current branch. - branchName := "main" - customBranchName, err := pm.gitCli.GetCurrentBranch(ctx, repoRoot) - // It is fine if we can't get the branch name, we will default to "main" - if err == nil { - branchName = customBranchName - } - - // default auth type for all providers - authType := AuthTypeFederated - if pm.args.PipelineAuthTypeName == "" && infraProvider == infraProviderTerraform { - // empty arg for auth and terraform forces client credentials, otherwise, it will be federated - authType = AuthTypeClientCredentials - } - - // Check and prompt for missing CI/CD files - if err := pm.checkAndPromptForProviderFiles( - ctx, projectProperties{ - CiProvider: pipelineProvider, - RepoRoot: repoRoot, - InfraProvider: infraProvider, - HasAppHost: hasAppHost, - BranchName: branchName, - AuthType: authType, - Variables: prjConfig.Pipeline.Variables, - Secrets: prjConfig.Pipeline.Secrets, - RequiredAlphaFeatures: requiredAlphaFeatures, - }); err != nil { - return err - } + pm.prjConfig = prjConfig + + // infra, err := pm.importManager.ProjectInfrastructure(ctx, prjConfig) + // if err != nil { + // return err + // } + // defer func() { _ = infra.Cleanup() }() + // pm.infra = infra + + // hasAppHost := pm.importManager.HasAppHost(ctx, prjConfig) + + // infraProvider, err := toInfraProviderType(string(pm.infra.Options.Provider)) + // if err != nil { + // return err + // } + + // var requiredAlphaFeatures []string + // if infra.IsCompose { + // requiredAlphaFeatures = append(requiredAlphaFeatures, "compose") + // } + // // There are 2 possible options, for the git branch name, when running azd pipeline config: + // // - There is not a git repo, so the branch name is empty. In this case, we default to "main". + // // - There is a git repo and we can get the name of the current branch. + // branchName := "main" + // customBranchName, err := pm.gitCli.GetCurrentBranch(ctx, repoRoot) + // // It is fine if we can't get the branch name, we will default to "main" + // if err == nil { + // branchName = customBranchName + // } + + // // default auth type for all providers + // authType := AuthTypeFederated + // if pm.args.PipelineAuthTypeName == "" && infraProvider == infraProviderTerraform { + // // empty arg for auth and terraform forces client credentials, otherwise, it will be federated + // authType = AuthTypeClientCredentials + // } + + // // Check and prompt for missing CI/CD files + // if err := pm.checkAndPromptForProviderFiles( + // ctx, projectProperties{ + // CiProvider: pipelineProvider, + // RepoRoot: repoRoot, + // InfraProvider: infraProvider, + // HasAppHost: hasAppHost, + // BranchName: branchName, + // AuthType: authType, + // Variables: prjConfig.Pipeline.Variables, + // Secrets: prjConfig.Pipeline.Secrets, + // RequiredAlphaFeatures: requiredAlphaFeatures, + // providerParameters: pm.configOptions.providerParameters, + // }); err != nil { + // return err + // } // Save the provider to the environment if err := pm.savePipelineProviderToEnv(ctx, pipelineProvider, pm.env); err != nil { @@ -868,11 +928,11 @@ func (pm *PipelineManager) initialize(ctx context.Context, override string) erro pm.scmProvider = scmProvider pm.ciProvider = ciProvider - pm.configOptions = &configurePipelineOptions{ - projectVariables: slices.Clone(prjConfig.Pipeline.Variables), - projectSecrets: slices.Clone(prjConfig.Pipeline.Secrets), - provisioningProvider: &pm.infra.Options, - } + // pm.configOptions = &configurePipelineOptions{ + // projectVariables: slices.Clone(prjConfig.Pipeline.Variables), + // projectSecrets: slices.Clone(prjConfig.Pipeline.Secrets), + // provisioningProvider: &pm.infra.Options, + // } return nil } @@ -1039,7 +1099,7 @@ func generatePipelineDefinition(path string, props projectProperties) error { return fmt.Errorf("parsing embedded file %s: %w", embedFilePath, err) } builder := strings.Builder{} - err = tmpl.Execute(&builder, struct { + tmplContext := struct { BranchName string FedCredLogIn bool InstallDotNetForAspire bool @@ -1053,7 +1113,20 @@ func generatePipelineDefinition(path string, props projectProperties) error { Variables: props.Variables, Secrets: props.Secrets, AlphaFeatures: props.RequiredAlphaFeatures, - }) + } + + // Apply provider parameters + for _, param := range props.providerParameters { + for _, envVarName := range param.EnvVarMapping { + if param.Secret { + tmplContext.Secrets = append(tmplContext.Secrets, envVarName) + } else { + tmplContext.Variables = append(tmplContext.Variables, envVarName) + } + } + } + + err = tmpl.Execute(&builder, tmplContext) if err != nil { return fmt.Errorf("executing template: %w", err) } @@ -1165,5 +1238,8 @@ func resolveSmr(smrArg string, projectConfig config.Config, userConfig config.Co // This is useful for provisioning providers to define a list of parameters that are required for the pipeline. // If parameters is nil, it means that the pipeline manager should not set up any parameters automatically. func (pm *PipelineManager) SetParameters(parameters []provisioning.Parameter) { + if pm.configOptions == nil { + pm.configOptions = &configurePipelineOptions{} + } pm.configOptions.providerParameters = parameters } diff --git a/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt b/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt index 98d102b52ff..b863ac17980 100644 --- a/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt +++ b/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt @@ -55,7 +55,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) {{- range $variable := .Variables }} {{ $variable }}: $({{ $variable }}) {{- end}} diff --git a/cli/azd/resources/pipeline/.github/azure-dev.ymlt b/cli/azd/resources/pipeline/.github/azure-dev.ymlt index c8093a58dbb..8308bceadf9 100644 --- a/cli/azd/resources/pipeline/.github/azure-dev.ymlt +++ b/cli/azd/resources/pipeline/.github/azure-dev.ymlt @@ -77,11 +77,12 @@ jobs: - name: Provision Infrastructure run: azd provision --no-prompt +{{- if .Secrets }} env: - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ "{{" }} secrets.AZD_INITIAL_ENVIRONMENT_CONFIG {{ "}}" }} {{- range $secret := .Secrets }} {{ $secret }}: ${{ "{{" }} secrets.{{ $secret }} {{ "}}" }} {{- end}} +{{- end }} - name: Deploy Application run: azd deploy --no-prompt From d86d688955f50ae24219b921fabab1640ee165c8 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 05:37:08 +0000 Subject: [PATCH 14/20] updating tests... WIP --- cli/azd/pkg/pipeline/pipeline_manager.go | 114 ++++++++++-------- cli/azd/pkg/pipeline/pipeline_manager_test.go | 21 +++- ...-_azdo_selected_-_App_host_-_fed_Cred.snap | 3 - ...o_files_-_azdo_selected_-_branch_name.snap | 3 - ..._selected_-_no_app_host_-_client_cred.snap | 3 - ...zdo_selected_-_no_app_host_-_fed_Cred.snap | 3 - ...-_no_app_host_-_variables_and_secrets.snap | 3 - ...github_selected_-_App_host_-_fed_Cred.snap | 4 - ...thub_selected_-_Variables_and_Secrets.snap | 3 - ...files_-_github_selected_-_branch_name.snap | 4 - ..._selected_-_no_app_host_-_client_cred.snap | 4 - ...hub_selected_-_no_app_host_-_fed_Cred.snap | 4 - ...ected_-_azuredevops_dir_-_client_cred.snap | 3 - ...selected_-_azuredevops_dir_-_fed_Cred.snap | 3 - .../resources/pipeline/.azdo/azure-dev.ymlt | 2 - .../resources/pipeline/.github/azure-dev.ymlt | 9 +- 16 files changed, 86 insertions(+), 100 deletions(-) diff --git a/cli/azd/pkg/pipeline/pipeline_manager.go b/cli/azd/pkg/pipeline/pipeline_manager.go index 5b076f9e01e..790cfc579c7 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager.go +++ b/cli/azd/pkg/pipeline/pipeline_manager.go @@ -96,6 +96,7 @@ type PipelineManager struct { userConfigManager config.UserConfigManager keyVaultService keyvault.KeyVaultService prjConfig *project.ProjectConfig + ciProviderType ciProviderType } func NewPipelineManager( @@ -238,59 +239,7 @@ func (pm *PipelineManager) Configure( } // pipeline definition files - hasAppHost := pm.importManager.HasAppHost(ctx, pm.prjConfig) - - infraProvider, err := toInfraProviderType(string(pm.infra.Options.Provider)) - if err != nil { - return nil, err - } - - var requiredAlphaFeatures []string - if infra.IsCompose { - requiredAlphaFeatures = append(requiredAlphaFeatures, "compose") - } - // There are 2 possible options, for the git branch name, when running azd pipeline config: - // - There is not a git repo, so the branch name is empty. In this case, we default to "main". - // - There is a git repo and we can get the name of the current branch. - branchName := "main" - projectDir := pm.azdCtx.ProjectDirectory() - repoRoot, err := pm.gitCli.GetRepoRoot(ctx, projectDir) - if err != nil { - return nil, fmt.Errorf("getting git repo root: %w", err) - } - customBranchName, err := pm.gitCli.GetCurrentBranch(ctx, repoRoot) - // It is fine if we can't get the branch name, we will default to "main" - if err == nil { - branchName = customBranchName - } - - // default auth type for all providers - authType := AuthTypeFederated - if pm.args.PipelineAuthTypeName == "" && infraProvider == infraProviderTerraform { - // empty arg for auth and terraform forces client credentials, otherwise, it will be federated - authType = AuthTypeClientCredentials - } - - // Check and prompt for missing CI/CD files - err = pm.checkAndPromptForProviderFiles( - ctx, projectProperties{ - CiProvider: ciProviderType(strings.ToLower(pm.ciProvider.Name())), - RepoRoot: repoRoot, - InfraProvider: infraProvider, - HasAppHost: hasAppHost, - BranchName: branchName, - AuthType: authType, - Variables: pm.prjConfig.Pipeline.Variables, - Secrets: pm.prjConfig.Pipeline.Secrets, - RequiredAlphaFeatures: requiredAlphaFeatures, - providerParameters: pm.configOptions.providerParameters, - }) - if err != nil { - return nil, err - } - pm.configOptions.projectSecrets = slices.Clone(pm.prjConfig.Pipeline.Secrets) - pm.configOptions.projectVariables = slices.Clone(pm.prjConfig.Pipeline.Variables) - pm.configOptions.provisioningProvider = &infra.Options + pm.ensurePipelineDefinition(ctx) userConfig, err := pm.userConfigManager.Load() if err != nil { @@ -839,6 +788,7 @@ func (pm *PipelineManager) initialize(ctx context.Context, override string) erro } pipelineProvider = p } + pm.ciProviderType = pipelineProvider prjConfig, err := project.Load(ctx, projectPath) if err != nil { @@ -1243,3 +1193,61 @@ func (pm *PipelineManager) SetParameters(parameters []provisioning.Parameter) { } pm.configOptions.providerParameters = parameters } + +func (pm *PipelineManager) ensurePipelineDefinition(ctx context.Context) error { + // pipeline definition files + hasAppHost := pm.importManager.HasAppHost(ctx, pm.prjConfig) + + infraProvider, err := toInfraProviderType(string(pm.infra.Options.Provider)) + if err != nil { + return err + } + + var requiredAlphaFeatures []string + if pm.infra.IsCompose { + requiredAlphaFeatures = append(requiredAlphaFeatures, "compose") + } + // There are 2 possible options, for the git branch name, when running azd pipeline config: + // - There is not a git repo, so the branch name is empty. In this case, we default to "main". + // - There is a git repo and we can get the name of the current branch. + branchName := "main" + projectDir := pm.azdCtx.ProjectDirectory() + repoRoot, err := pm.gitCli.GetRepoRoot(ctx, projectDir) + if err != nil { + return fmt.Errorf("getting git repo root: %w", err) + } + customBranchName, err := pm.gitCli.GetCurrentBranch(ctx, repoRoot) + // It is fine if we can't get the branch name, we will default to "main" + if err == nil { + branchName = customBranchName + } + + // default auth type for all providers + authType := AuthTypeFederated + if pm.args.PipelineAuthTypeName == "" && infraProvider == infraProviderTerraform { + // empty arg for auth and terraform forces client credentials, otherwise, it will be federated + authType = AuthTypeClientCredentials + } + + // Check and prompt for missing CI/CD files + err = pm.checkAndPromptForProviderFiles( + ctx, projectProperties{ + CiProvider: pm.ciProviderType, + RepoRoot: repoRoot, + InfraProvider: infraProvider, + HasAppHost: hasAppHost, + BranchName: branchName, + AuthType: authType, + Variables: pm.prjConfig.Pipeline.Variables, + Secrets: pm.prjConfig.Pipeline.Secrets, + RequiredAlphaFeatures: requiredAlphaFeatures, + providerParameters: pm.configOptions.providerParameters, + }) + if err != nil { + return err + } + pm.configOptions.projectSecrets = slices.Clone(pm.prjConfig.Pipeline.Secrets) + pm.configOptions.projectVariables = slices.Clone(pm.prjConfig.Pipeline.Variables) + pm.configOptions.provisioningProvider = &pm.infra.Options + return nil +} diff --git a/cli/azd/pkg/pipeline/pipeline_manager_test.go b/cli/azd/pkg/pipeline/pipeline_manager_test.go index 15aa6f60755..da9ab05d3c7 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager_test.go +++ b/cli/azd/pkg/pipeline/pipeline_manager_test.go @@ -17,6 +17,7 @@ import ( "github.com/azure/azure-dev/cli/azd/pkg/environment" "github.com/azure/azure-dev/cli/azd/pkg/environment/azdcontext" "github.com/azure/azure-dev/cli/azd/pkg/exec" + "github.com/azure/azure-dev/cli/azd/pkg/infra/provisioning" "github.com/azure/azure-dev/cli/azd/pkg/input" "github.com/azure/azure-dev/cli/azd/pkg/ioc" "github.com/azure/azure-dev/cli/azd/pkg/osutil" @@ -78,9 +79,16 @@ func Test_PipelineManager_Initialize(t *testing.T) { simulateUserInteraction(mockContext, ciProviderGitHubActions, false) - _, err := createPipelineManager(mockContext, azdContext, nil, nil) + m, err := createPipelineManager(mockContext, azdContext, nil, nil) // No error for GitHub, just a message to the console assert.NoError(t, err) + m.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + m.configOptions = &configurePipelineOptions{} + err = m.ensurePipelineDefinition(ctx) assert.Contains(t, mockContext.Console.Output(), fmt.Sprintf( @@ -97,8 +105,15 @@ func Test_PipelineManager_Initialize(t *testing.T) { simulateUserInteraction(mockContext, ciProviderAzureDevOps, false) - manager, err := createPipelineManager(mockContext, azdContext, nil, nil) - assert.Nil(t, manager) + m, err := createPipelineManager(mockContext, azdContext, nil, nil) + assert.NoError(t, err) + m.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + m.configOptions = &configurePipelineOptions{} + err = m.ensurePipelineDefinition(ctx) assert.EqualError(t, err, fmt.Sprintf( "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ "Please add pipeline files and try again.", diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_App_host_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_App_host_-_fed_Cred.snap index fb686d664da..10e885e0b1e 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_App_host_-_fed_Cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_App_host_-_fed_Cred.snap @@ -46,7 +46,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application @@ -59,7 +58,5 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_branch_name.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_branch_name.snap index 20e8bbe14fc..02616b5f6e1 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_branch_name.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_branch_name.snap @@ -37,7 +37,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application @@ -50,7 +49,5 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_client_cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_client_cred.snap index 50f875d3b72..753454f1bf2 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_client_cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_client_cred.snap @@ -37,7 +37,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application @@ -50,7 +49,5 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_fed_Cred.snap index 50f875d3b72..753454f1bf2 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_fed_Cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_fed_Cred.snap @@ -37,7 +37,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application @@ -50,7 +49,5 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_variables_and_secrets.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_variables_and_secrets.snap index fe0bae3d889..7cf01715e2d 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_variables_and_secrets.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_azdo_selected_-_no_app_host_-_variables_and_secrets.snap @@ -37,7 +37,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) VAR_1: $(VAR_1) VAR_2: $(VAR_2) SECRET_1: $(SECRET_1) @@ -54,8 +53,6 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) VAR_1: $(VAR_1) VAR_2: $(VAR_2) SECRET_1: $(SECRET_1) diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap index e7a2151d847..305397ff35c 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap @@ -21,8 +21,6 @@ jobs: AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} - AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} steps: - name: Checkout uses: actions/checkout@v4 @@ -46,8 +44,6 @@ jobs: - name: Provision Infrastructure run: azd provision --no-prompt - env: - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap index 84fd89b3812..0fd455daf47 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap @@ -21,8 +21,6 @@ jobs: AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} - AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} VAR_1: ${{ vars.VAR_1 }} VAR_2: ${{ vars.VAR_2 }} steps: @@ -49,7 +47,6 @@ jobs: - name: Provision Infrastructure run: azd provision --no-prompt env: - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} SECRET_1: ${{ secrets.SECRET_1 }} SECRET_2: ${{ secrets.SECRET_2 }} diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap index c3f3c9b7053..9930bfb6470 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap @@ -21,8 +21,6 @@ jobs: AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} - AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} steps: - name: Checkout uses: actions/checkout@v4 @@ -39,8 +37,6 @@ jobs: - name: Provision Infrastructure run: azd provision --no-prompt - env: - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap index 0a2adabb9dc..4b0650deb0d 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap @@ -16,8 +16,6 @@ jobs: AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} - AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} steps: - name: Checkout uses: actions/checkout@v4 @@ -39,8 +37,6 @@ jobs: - name: Provision Infrastructure run: azd provision --no-prompt - env: - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap index 170f5e9286b..17c1d53358d 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap @@ -21,8 +21,6 @@ jobs: AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }} AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }} AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }} - AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }} - AZURE_LOCATION: ${{ vars.AZURE_LOCATION }} steps: - name: Checkout uses: actions/checkout@v4 @@ -39,8 +37,6 @@ jobs: - name: Provision Infrastructure run: azd provision --no-prompt - env: - AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }} - name: Deploy Application run: azd deploy --no-prompt diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_client_cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_client_cred.snap index 50f875d3b72..753454f1bf2 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_client_cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_client_cred.snap @@ -37,7 +37,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application @@ -50,7 +49,5 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_fed_Cred.snap index 50f875d3b72..753454f1bf2 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_fed_Cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles_azureDevOpsDirectory-no_files_-_azdo_selected_-_azuredevops_dir_-_fed_Cred.snap @@ -37,7 +37,6 @@ steps: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) AZURE_ENV_NAME: $(AZURE_ENV_NAME) AZURE_LOCATION: $(AZURE_LOCATION) - AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) - task: AzureCLI@2 displayName: Deploy Application @@ -50,7 +49,5 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) diff --git a/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt b/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt index b863ac17980..30e6ab7d1be 100644 --- a/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt +++ b/cli/azd/resources/pipeline/.azdo/azure-dev.ymlt @@ -73,8 +73,6 @@ steps: azd deploy --no-prompt env: AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID) - AZURE_ENV_NAME: $(AZURE_ENV_NAME) - AZURE_LOCATION: $(AZURE_LOCATION) {{- range $variable := .Variables }} {{ $variable }}: $({{ $variable }}) {{- end}} diff --git a/cli/azd/resources/pipeline/.github/azure-dev.ymlt b/cli/azd/resources/pipeline/.github/azure-dev.ymlt index 8308bceadf9..aef8646e11b 100644 --- a/cli/azd/resources/pipeline/.github/azure-dev.ymlt +++ b/cli/azd/resources/pipeline/.github/azure-dev.ymlt @@ -23,8 +23,6 @@ jobs: AZURE_CLIENT_ID: ${{ "{{" }} vars.AZURE_CLIENT_ID {{ "}}" }} AZURE_TENANT_ID: ${{ "{{" }} vars.AZURE_TENANT_ID {{ "}}" }} AZURE_SUBSCRIPTION_ID: ${{ "{{" }} vars.AZURE_SUBSCRIPTION_ID {{ "}}" }} - AZURE_ENV_NAME: ${{ "{{" }} vars.AZURE_ENV_NAME {{ "}}" }} - AZURE_LOCATION: ${{ "{{" }} vars.AZURE_LOCATION {{ "}}" }} {{- range $variable := .Variables }} {{ $variable }}: ${{ "{{" }} vars.{{ $variable }} {{ "}}" }} {{- end}} @@ -86,4 +84,11 @@ jobs: - name: Deploy Application run: azd deploy --no-prompt +{{- if .Secrets }} + env: +{{- range $secret := .Secrets }} + {{ $secret }}: ${{ "{{" }} secrets.{{ $secret }} {{ "}}" }} +{{- end}} +{{- end }} + {{ end}} \ No newline at end of file From bf75f095d4fad2939fe130edd6564370083c0fdf Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 06:30:20 +0000 Subject: [PATCH 15/20] ready to test --- cli/azd/pkg/pipeline/pipeline_manager_test.go | 70 ++++++++++++++++++- ...github_selected_-_App_host_-_fed_Cred.snap | 1 + ...thub_selected_-_Variables_and_Secrets.snap | 4 ++ ...files_-_github_selected_-_branch_name.snap | 1 + ..._selected_-_no_app_host_-_client_cred.snap | 1 + ...hub_selected_-_no_app_host_-_fed_Cred.snap | 1 + 6 files changed, 76 insertions(+), 2 deletions(-) diff --git a/cli/azd/pkg/pipeline/pipeline_manager_test.go b/cli/azd/pkg/pipeline/pipeline_manager_test.go index da9ab05d3c7..7558cd71f58 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager_test.go +++ b/cli/azd/pkg/pipeline/pipeline_manager_test.go @@ -64,6 +64,14 @@ func Test_PipelineManager_Initialize(t *testing.T) { // Execute the initialize method, which should trigger the confirmation prompt err = manager.initialize(ctx, "") assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + err = manager.ensurePipelineDefinition(ctx) + assert.NoError(t, err) // Check if the azure-dev.yml file was created in the expected path gitHubYmlPath := filepath.Join(tempDir, pipelineProviderFiles[ciProviderGitHubActions].Files[0]) @@ -135,6 +143,15 @@ func Test_PipelineManager_Initialize(t *testing.T) { // Execute the initialize method, which should trigger the confirmation prompt err = manager.initialize(ctx, "") + assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + err = manager.ensurePipelineDefinition(ctx) + assert.NoError(t, err) verifyProvider(t, manager, ciProviderAzureDevOps, err) // Check if the azure-dev.yml file was created in the expected path @@ -154,7 +171,14 @@ func Test_PipelineManager_Initialize(t *testing.T) { simulateUserInteraction(mockContext, ciProviderAzureDevOps, false) manager, err := createPipelineManager(mockContext, azdContext, env, nil) - assert.Nil(t, manager) + assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + err = manager.ensurePipelineDefinition(ctx) assert.EqualError(t, err, fmt.Sprintf( "%s provider selected, but no pipeline files were found in any expected directories:\n%s\n"+ "Please add pipeline files and try again.", @@ -188,9 +212,16 @@ func Test_PipelineManager_Initialize(t *testing.T) { simulateUserInteraction(mockContext, ciProviderGitHubActions, false) - _, err := createPipelineManager(mockContext, azdContext, env, nil) + m, err := createPipelineManager(mockContext, azdContext, env, nil) // No error for GitHub, just a message to the console assert.NoError(t, err) + m.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + m.configOptions = &configurePipelineOptions{} + err = m.ensurePipelineDefinition(ctx) assert.Contains(t, mockContext.Console.Output(), fmt.Sprintf( @@ -336,6 +367,13 @@ func Test_PipelineManager_Initialize(t *testing.T) { assert.NotNil(t, manager) assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + // Execute the initialize method, which should trigger the provider selection prompt err = manager.initialize(ctx, "") @@ -354,6 +392,13 @@ func Test_PipelineManager_Initialize(t *testing.T) { assert.NotNil(t, manager) assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + // Execute the initialize method, which should trigger the provider selection prompt err = manager.initialize(ctx, "") @@ -372,6 +417,13 @@ func Test_PipelineManager_Initialize(t *testing.T) { assert.NotNil(t, manager) assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + // Execute the initialize method, which should trigger the provider selection prompt err = manager.initialize(ctx, "") @@ -391,6 +443,13 @@ func Test_PipelineManager_Initialize(t *testing.T) { assert.NotNil(t, manager) assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + // Execute the initialize method, which should trigger the provider selection prompt err = manager.initialize(ctx, "") @@ -411,6 +470,13 @@ func Test_PipelineManager_Initialize(t *testing.T) { assert.NotNil(t, manager) assert.NoError(t, err) + manager.infra = &project.Infra{ + Options: provisioning.Options{ + Provider: provisioning.Bicep, + }, + IsCompose: false} + manager.configOptions = &configurePipelineOptions{} + // Execute the initialize method, which should trigger the provider selection prompt err = manager.initialize(ctx, "") diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap index 305397ff35c..40bfa7c920b 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_App_host_-_fed_Cred.snap @@ -47,4 +47,5 @@ jobs: - name: Deploy Application run: azd deploy --no-prompt + diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap index 0fd455daf47..2e57caaf9fe 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_Variables_and_Secrets.snap @@ -52,4 +52,8 @@ jobs: - name: Deploy Application run: azd deploy --no-prompt + env: + SECRET_1: ${{ secrets.SECRET_1 }} + SECRET_2: ${{ secrets.SECRET_2 }} + diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap index 9930bfb6470..5f299008abf 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_branch_name.snap @@ -40,4 +40,5 @@ jobs: - name: Deploy Application run: azd deploy --no-prompt + diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap index 4b0650deb0d..63eac357512 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_client_cred.snap @@ -40,4 +40,5 @@ jobs: - name: Deploy Application run: azd deploy --no-prompt + diff --git a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap index 17c1d53358d..25732faa1be 100644 --- a/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap +++ b/cli/azd/pkg/pipeline/testdata/Test_promptForCiFiles-no_files_-_github_selected_-_no_app_host_-_fed_Cred.snap @@ -40,4 +40,5 @@ jobs: - name: Deploy Application run: azd deploy --no-prompt + From 7fdbeb1e4e774754bd778703e220437459a8110f Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 06:48:40 +0000 Subject: [PATCH 16/20] lint --- cli/azd/pkg/pipeline/pipeline_manager_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cli/azd/pkg/pipeline/pipeline_manager_test.go b/cli/azd/pkg/pipeline/pipeline_manager_test.go index 7558cd71f58..26c6baa7d09 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager_test.go +++ b/cli/azd/pkg/pipeline/pipeline_manager_test.go @@ -97,6 +97,7 @@ func Test_PipelineManager_Initialize(t *testing.T) { IsCompose: false} m.configOptions = &configurePipelineOptions{} err = m.ensurePipelineDefinition(ctx) + assert.NoError(t, err) assert.Contains(t, mockContext.Console.Output(), fmt.Sprintf( @@ -222,6 +223,7 @@ func Test_PipelineManager_Initialize(t *testing.T) { IsCompose: false} m.configOptions = &configurePipelineOptions{} err = m.ensurePipelineDefinition(ctx) + assert.NoError(t, err) assert.Contains(t, mockContext.Console.Output(), fmt.Sprintf( From 2d1ad2dfc50ec527afb087e7b91aaec12d50ed73 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 16:46:10 +0000 Subject: [PATCH 17/20] aspire snap --- .../infra/webfrontend.tmpl.yaml | 2 ++ .../testdata/snaps/aspire-full/infra/main.bicep | 1 + .../snaps/aspire-full/infra/main.parameters.json | 3 +++ .../testdata/snaps/aspire-full/manifest.json | 12 +++++++++++- 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml b/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml index b991d41e7ca..01e4a031957 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml @@ -40,6 +40,8 @@ properties: value: "true" - name: GOVERSION value: '{{ parameterWithDefault "goversion" "1.22"}}' + - name: GOVERSION2 + value: '{{ parameter "goversion2" }}' - name: HTTP_PORTS value: '{{ targetPortOrDefault 0 }}' - name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep index ccbf69bb4bd..d3b4226fa5d 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep @@ -13,6 +13,7 @@ param location string param principalId string = '' param goversion string = '1.22' +param goversion2 string var tags = { 'azd-env-name': environmentName diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json index 14214609dae..0f5b5935142 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json @@ -8,6 +8,9 @@ "goversion": { "value": "${AZURE_GOVERSION}" }, + "goversion2": { + "value": "${AZURE_GOVERSION2}" + }, "environmentName": { "value": "${AZURE_ENV_NAME}" }, diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json b/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json index 1ba7eace0a3..72f03222534 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json @@ -13,6 +13,15 @@ } } }, + "goversion2": { + "type": "parameter.v0", + "value": "{goversion2.inputs.value}", + "inputs": { + "value": { + "type": "string" + } + } + }, "pubsub": { "type": "container.v0", "connectionString": "{pubsub.bindings.tcp.host}:{pubsub.bindings.tcp.port}", @@ -93,7 +102,8 @@ "ConnectionStrings__messages": "{messages.connectionString}", "services__apiservice__http__0": "{apiservice.bindings.http.url}", "services__apiservice__https__0": "{apiservice.bindings.https.url}", - "GOVERSION": "{goversion.value}" + "GOVERSION": "{goversion.value}", + "GOVERSION2": "{goversion2.value}" }, "bindings": { "http": { From be26c328f6a34f28f43071cae513fd937c3d5ab1 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 17:25:14 +0000 Subject: [PATCH 18/20] update snap --- .../testdata/TestAspireContainerGeneration-main.bicep.snap | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap b/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap index 5b904777991..110d7f5322a 100644 --- a/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap +++ b/cli/azd/pkg/apphost/testdata/TestAspireContainerGeneration-main.bicep.snap @@ -90,6 +90,6 @@ output SERVICE_NOVOLUME_FILE_SHARE_BM0_NAME string = resources.outputs.SERVICE_N output SERVICE_NOVOLUME_VOLUME_BM1_NAME string = resources.outputs.SERVICE_NOVOLUME_VOLUME_BM1_NAME output SERVICE_NOVOLUME_FILE_SHARE_BM1_NAME string = resources.outputs.SERVICE_NOVOLUME_FILE_SHARE_BM1_NAME output AZURE_VOLUMES_STORAGE_ACCOUNT string = resources.outputs.AZURE_VOLUMES_STORAGE_ACCOUNT -output AZURE_PARAM_WITH_EMPTY_VALUE = param-with-empty-value -output AZURE_PARAM_WITH_VALUE = param-with-value +output AZURE_PARAM_WITH_EMPTY_VALUE string = param-with-empty-value +output AZURE_PARAM_WITH_VALUE string = param-with-value From 9dc6cbd4ee06e839e0d7e679ba35b1db926a752b Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Thu, 1 May 2025 17:59:34 +0000 Subject: [PATCH 19/20] remove param bc vsserver test can't handle prompt --- cli/azd/pkg/pipeline/pipeline_manager.go | 55 +------------------ .../AspireAzdTests.AppHost/Program.cs | 5 +- .../infra/webfrontend.tmpl.yaml | 2 - .../snaps/aspire-full/infra/main.bicep | 1 - .../aspire-full/infra/main.parameters.json | 3 - .../testdata/snaps/aspire-full/manifest.json | 12 +--- 6 files changed, 4 insertions(+), 74 deletions(-) diff --git a/cli/azd/pkg/pipeline/pipeline_manager.go b/cli/azd/pkg/pipeline/pipeline_manager.go index 790cfc579c7..979adec8487 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager.go +++ b/cli/azd/pkg/pipeline/pipeline_manager.go @@ -796,58 +796,6 @@ func (pm *PipelineManager) initialize(ctx context.Context, override string) erro } pm.prjConfig = prjConfig - // infra, err := pm.importManager.ProjectInfrastructure(ctx, prjConfig) - // if err != nil { - // return err - // } - // defer func() { _ = infra.Cleanup() }() - // pm.infra = infra - - // hasAppHost := pm.importManager.HasAppHost(ctx, prjConfig) - - // infraProvider, err := toInfraProviderType(string(pm.infra.Options.Provider)) - // if err != nil { - // return err - // } - - // var requiredAlphaFeatures []string - // if infra.IsCompose { - // requiredAlphaFeatures = append(requiredAlphaFeatures, "compose") - // } - // // There are 2 possible options, for the git branch name, when running azd pipeline config: - // // - There is not a git repo, so the branch name is empty. In this case, we default to "main". - // // - There is a git repo and we can get the name of the current branch. - // branchName := "main" - // customBranchName, err := pm.gitCli.GetCurrentBranch(ctx, repoRoot) - // // It is fine if we can't get the branch name, we will default to "main" - // if err == nil { - // branchName = customBranchName - // } - - // // default auth type for all providers - // authType := AuthTypeFederated - // if pm.args.PipelineAuthTypeName == "" && infraProvider == infraProviderTerraform { - // // empty arg for auth and terraform forces client credentials, otherwise, it will be federated - // authType = AuthTypeClientCredentials - // } - - // // Check and prompt for missing CI/CD files - // if err := pm.checkAndPromptForProviderFiles( - // ctx, projectProperties{ - // CiProvider: pipelineProvider, - // RepoRoot: repoRoot, - // InfraProvider: infraProvider, - // HasAppHost: hasAppHost, - // BranchName: branchName, - // AuthType: authType, - // Variables: prjConfig.Pipeline.Variables, - // Secrets: prjConfig.Pipeline.Secrets, - // RequiredAlphaFeatures: requiredAlphaFeatures, - // providerParameters: pm.configOptions.providerParameters, - // }); err != nil { - // return err - // } - // Save the provider to the environment if err := pm.savePipelineProviderToEnv(ctx, pipelineProvider, pm.env); err != nil { return err @@ -1214,7 +1162,8 @@ func (pm *PipelineManager) ensurePipelineDefinition(ctx context.Context) error { projectDir := pm.azdCtx.ProjectDirectory() repoRoot, err := pm.gitCli.GetRepoRoot(ctx, projectDir) if err != nil { - return fmt.Errorf("getting git repo root: %w", err) + repoRoot = projectDir + log.Printf("using project root as repo root, since git repo wasn't available: %s", err) } customBranchName, err := pm.gitCli.GetCurrentBranch(ctx, repoRoot) // It is fine if we can't get the branch name, we will default to "main" diff --git a/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs b/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs index 5ce554fe3ab..891d296a6d3 100644 --- a/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs +++ b/cli/azd/test/functional/testdata/samples/aspire-full/AspireAzdTests.AppHost/Program.cs @@ -5,8 +5,6 @@ // test param with default value var goVersion = builder.AddParameter("goversion", "1.22", publishValueAsDefault: true); -var goVersion2 = builder.AddParameter("goversion2"); - // redis instance the app will use for simple messages var redisPubSub = builder.AddRedis("pubsub"); @@ -40,7 +38,6 @@ .WithReference(messageQueue) .WithReference(apiservice) .WithReference(workerProj) - .WithEnvironment("GOVERSION", goVersion) - .WithEnvironment("GOVERSION2", goVersion2); + .WithEnvironment("GOVERSION", goVersion); builder.Build().Run(); diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml b/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml index 01e4a031957..b991d41e7ca 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/AspireAzdTests.AppHost/infra/webfrontend.tmpl.yaml @@ -40,8 +40,6 @@ properties: value: "true" - name: GOVERSION value: '{{ parameterWithDefault "goversion" "1.22"}}' - - name: GOVERSION2 - value: '{{ parameter "goversion2" }}' - name: HTTP_PORTS value: '{{ targetPortOrDefault 0 }}' - name: OTEL_DOTNET_EXPERIMENTAL_OTLP_EMIT_EVENT_LOG_ATTRIBUTES diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep index d3b4226fa5d..ccbf69bb4bd 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.bicep @@ -13,7 +13,6 @@ param location string param principalId string = '' param goversion string = '1.22' -param goversion2 string var tags = { 'azd-env-name': environmentName diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json index 0f5b5935142..14214609dae 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/infra/main.parameters.json @@ -8,9 +8,6 @@ "goversion": { "value": "${AZURE_GOVERSION}" }, - "goversion2": { - "value": "${AZURE_GOVERSION2}" - }, "environmentName": { "value": "${AZURE_ENV_NAME}" }, diff --git a/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json b/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json index 72f03222534..1ba7eace0a3 100644 --- a/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json +++ b/cli/azd/test/functional/testdata/snaps/aspire-full/manifest.json @@ -13,15 +13,6 @@ } } }, - "goversion2": { - "type": "parameter.v0", - "value": "{goversion2.inputs.value}", - "inputs": { - "value": { - "type": "string" - } - } - }, "pubsub": { "type": "container.v0", "connectionString": "{pubsub.bindings.tcp.host}:{pubsub.bindings.tcp.port}", @@ -102,8 +93,7 @@ "ConnectionStrings__messages": "{messages.connectionString}", "services__apiservice__http__0": "{apiservice.bindings.http.url}", "services__apiservice__https__0": "{apiservice.bindings.https.url}", - "GOVERSION": "{goversion.value}", - "GOVERSION2": "{goversion2.value}" + "GOVERSION": "{goversion.value}" }, "bindings": { "http": { From 9b7bc43dce9194b3e64d082b9abc9d189ceea093 Mon Sep 17 00:00:00 2001 From: Victor Vazquez Date: Fri, 9 May 2025 20:24:26 +0000 Subject: [PATCH 20/20] apply PR suggestions --- cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go | 2 +- cli/azd/pkg/pipeline/pipeline_manager.go | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go index 3c5a1a108c4..4ce99819947 100644 --- a/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go +++ b/cli/azd/pkg/infra/provisioning/bicep/bicep_provider.go @@ -2315,7 +2315,7 @@ func (p *BicepProvider) Parameters(ctx context.Context) ([]provisioning.Paramete return nil, fmt.Errorf("resolving parameters: %w", err) } - provisionParameters := make([]provisioning.Parameter, 0, len(templateParameters)) + provisionParameters := []provisioning.Parameter{} for key, param := range templateParameters { if _, usingParam := resolvedParams[key]; !usingParam { // No resolved param for this parameter definition. diff --git a/cli/azd/pkg/pipeline/pipeline_manager.go b/cli/azd/pkg/pipeline/pipeline_manager.go index 979adec8487..533cf2f800e 100644 --- a/cli/azd/pkg/pipeline/pipeline_manager.go +++ b/cli/azd/pkg/pipeline/pipeline_manager.go @@ -826,12 +826,6 @@ func (pm *PipelineManager) initialize(ctx context.Context, override string) erro pm.scmProvider = scmProvider pm.ciProvider = ciProvider - // pm.configOptions = &configurePipelineOptions{ - // projectVariables: slices.Clone(prjConfig.Pipeline.Variables), - // projectSecrets: slices.Clone(prjConfig.Pipeline.Secrets), - // provisioningProvider: &pm.infra.Options, - // } - return nil }