azure-dev icon indicating copy to clipboard operation
azure-dev copied to clipboard

Prompting for parameters with aspire/azd

Open mip1983 opened this issue 1 year ago • 1 comments

azd version 1.7.0 (commit 49d6adc2efb178083f61822e6b4715258560803d)

Describe the issue

Having chatted about this on the aspire discussion area, @davidfowl asked me to raise this as an issue:

https://github.com/dotnet/aspire/discussions/2848#discussioncomment-8915919

I'm using preview 4 and trying to add a sql connection to an existing database.

I've added

var sqlConnection = builder.AddConnectionString("sql", "SQL_CONNECTION");

And then on my project:

var web = builder.AddProject<Projects.AspireTest>("aspire")
	.WithReference(sqlConnection)

This is fine running locally, reading the connection string from the AppHost secrets.

However, if you do an azd deploy, or run azd in your Azure DevOps pipeline, it asks for this connection string as a parameter. e.g. this in the prompt after 'azd deploy':

? Enter a value for the 'sql' infrastructure secured parameter:

If I provide this parameter, I think it essentially adds it to the main.paramaters.json, and then it's not so intuitive in terms of how to get this working as an environment variable so it can be built in a promptless CI/CI pipeline, the process doesn't tell you the name of this variable.

It is documented, but it would be good if during this prompt it could give you the option to save this parameter as an environment variable (and let you know the name of said variable) rather than it ending up in the json file.

Another potential option that might be nice to have is if aspire takes the 'environmentVariableName' param from AddConnectionString and outputs it to the manifest so that azd can use the same name for the environment variable input param (so it's named consistently and in a controllable/predictable way).

To Reproduce

Within an aspire project, declare a connection to an existing DB with the environmentVariableName param e.g.

var sqlConnection = builder.AddConnectionString("sql", "SQL_CONNECTION");

Expected behavior

I (wrongly) expected the project to require the environment variable name I'd given as input to populate the connection string value, wasn't clear how it worked until pointed at the docs

Environment Information on your environment: * .NET Aspire preview 4 * VS2022 17.10 Preview 2

mip1983 avatar Mar 26 '24 15:03 mip1983

If I provide this parameter, I think it essentially adds it to the main.paramaters.json, and then it's not so intuitive in terms of how to get this working as an environment variable so it can be built in a promptless CI/CI pipeline, the process doesn't tell you the name of this variable.

Your intuition is more or less correct here (in practice the value is saved into a different file, specific to the environment), but then end to end here isn't great yet.

It is documented, but it would be good if during this prompt it could give you the option to save this parameter as an environment variable (and let you know the name of said variable) rather than it ending up in the json file.

What you can do today is the following - in the infra\main.parameters.json you could do something like this:

    "sql": {
      "value": "${SQL_CONNECTION_STRING}"
    },

That would cause azd read the value of SQL_CONNECTION_STRING from an environment variable (you can set this in your pipeline configuration) and assign that to the parameter.

We need to think about this whole end to end a little more and make this less painful, but perhaps this information helps unblock your specific problem today.

ellismg avatar Mar 26 '24 17:03 ellismg

Hmm, I'm trying this and still running into problems in my CI/CI pipeline. The message I get is:

ERROR: failed deploying service 'ecodriver-analytics-api': failing invoking action 'deploy', failed executing template file: template: containerApp.tmpl.yaml:31:19: executing "containerApp.tmpl.yaml" at <securedParameter "ecoDriverDb">: error calling securedParameter: **parameter ecoDriverDb not found**

Which is confusing as the parameter is in my 'main.parameters.json':

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "ecoDriverDb": {
      "value": "${AZURE_ECO_DRIVER_DB}"
    },
    "environmentName": {
      "value": "${AZURE_ENV_NAME}"
    },
    "location": {
      "value": "${AZURE_LOCATION}"
    }
  }
}

That environment variable is set up in the variables group with the right name 'AZURE_ECO_DRIVER_DB' there in Azure Devops and is referenced in the build step:

- task: AzureCLI@2
  displayName: 'Deploy application to staging'
  inputs:
    azureSubscription: 'azDevServicePrincipalConnection'
    scriptType: 'bash'
    scriptLocation: 'inlineScript'
    inlineScript: 'azd deploy --no-prompt'
  env:
    AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
    AZURE_ENV_NAME: $(AZURE_ENV_NAME)
    AZURE_LOCATION: $(AZURE_LOCATION)
    AZURE_ECO_DRIVER_DB: $(AZURE_ECO_DRIVER_DB)

In the yaml file for the project it appears as:

      - name: connectionstrings--ecodriverdb
        value: '{{ securedParameter "ecoDriverDb" }}'

What am I missing, why is it not picking up the environment variable for this parameter?

mip1983 avatar Apr 11 '24 09:04 mip1983

@mip1983, the parameter mapping works only for the bicep template. It doesn't work for service yaml templates. For service's yaml template (in .Net Aspire world), secured parameters are persisted within the azd's environment config at .azure/env-name/config.json and never within the .azure/env-name/.env.

The expression: '{{ securedParameter "ecoDriverDb" }}' makes azd to look for the ecoDriverDb within the env's config.json.

Please try this:

  • Add AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) to the list of env: , like:
  env:
    AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
    AZURE_ENV_NAME: $(AZURE_ENV_NAME)
    AZURE_LOCATION: $(AZURE_LOCATION)
    AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG)
  • you can remove AZURE_ECO_DRIVER_DB env var, as it is ignored by azd

    • Run azd pipeline config. azd will create the AZD_INITIAL_ENVIRONMENT_CONFIG env var on your CI/CD pipeline with the content of env's config.json. Then, when your pipelien runs, azd will re-construct the env's config from that env var and the value for ecoDriverDb will be found.

vhvb1989 avatar Apr 15 '24 01:04 vhvb1989

I'm a bit lost there, I don't use azd pipeline config. I've set the build pipeline manually in Azure DevOps. I then push in variables for different environments using the 'Library' feature. I don't think I really want environment specific config on my local machine, particularly production values. e.g.

- ${{ if or(eq(parameters.provisionStage, true), eq(parameters.releaseStaging, true)) }}:
  - stage: 'DevEnvRelease'
    displayName: 'Development environment release'   
    jobs:
    - deployment: 'DevDeployment'
      displayName: 'Provision and/or Deploy dev'
      **variables:
        - group: 'AnalyticsDev'**
      environment: dev      
      strategy:
        runOnce:
          deploy:
            steps:
              - checkout: self

              - task: setup-azd@0 
                displayName: 'Setup AZD'

etc...

Is there a way to get azd to pick up this value that I'm trying to push in from the library?

mip1983 avatar Apr 15 '24 16:04 mip1983

@mip1983 , yes, if you are doing all manual, you will need to:

  • Push a variable AZD_INITIAL_ENVIRONMENT_CONFIG for each one of your environments. Set the value of the variable like:
{
  "infra": {
    "parameters": {
      "ecoDriverDb": "value-here"
    }
  }
}
  • Then reference the variable in the pipeline definition for running azd.

vhvb1989 avatar Apr 15 '24 17:04 vhvb1989

Im having this same issue and tried following your advice with no luck. same issue on the deployment.

@vhvb1989

When you say

Push a variable AZD_INITIAL_ENVIRONMENT_CONFIG for each one of your environments.

What exactly do you mean by this?

Im assuming you mean to add an env var (AZD_INITIAL_ENVIRONMENT_CONFIG) to each github environment here

image

and then set the value to the json of the config.json

I tried adding AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG) to the env in my github actions workflow and then running azd pipeline config but it didnt automatically add that env var to github

broline avatar Apr 20 '24 06:04 broline

What exactly do you mean by this?

I was referring to the Azure DevOps - library's variable group. Based on the commented user case:

I don't use azd pipeline config. I've set the build pipeline manually in Azure DevOps. I then push in variables for different environments using the 'Library' feature.

Within each variable group, there should be a variable AZD_INITIAL_ENVIRONMENT_CONFIG with the content of the infrastructure params. Then, the variable should be included in the pipeline definition (yaml)

vhvb1989 avatar Apr 20 '24 06:04 vhvb1989

I got this to work in github

Added AZD_INITIAL_ENVIRONMENT_CONFIG env var for my 'dev' envrionment with the json from the config.json of that environment from my local machine. Full azure-dev.yml looks like this

on:
  workflow_dispatch:
  push:
    # Run when commits are pushed to mainline branch (main or master)
    # Set this to the mainline branch you are using
    branches:
      - dev

permissions:
  id-token: write
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    environment: dev
    env:
      AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
      AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
      AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
      AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
      AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
      AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ vars. AZD_INITIAL_ENVIRONMENT_CONFIG }}
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Install azd
        uses: Azure/[email protected]

      - name: Install .NET Aspire workload
        run: dotnet workload install aspire

      - name: Log in with Azure (Federated Credentials)
        if: ${{ env.AZURE_CLIENT_ID != '' }}
        run: |
          azd auth login `
            --client-id "$Env:AZURE_CLIENT_ID" `
            --federated-credential-provider "github" `
            --tenant-id "$Env:AZURE_TENANT_ID"
        shell: pwsh

      - name: Log in with Azure (Client Credentials)
        if: ${{ env.AZURE_CREDENTIALS != '' }}
        run: |
          $info = $Env:AZURE_CREDENTIALS | ConvertFrom-Json -AsHashtable;
          Write-Host "::add-mask::$($info.clientSecret)"

          azd auth login `
            --client-id "$($info.clientId)" `
            --client-secret "$($info.clientSecret)" `
            --tenant-id "$($info.tenantId)"
        shell: pwsh

      - name: Provision Infrastructure
        run: azd provision -e dev --no-prompt

      - name: Deploy Application
        run: azd deploy -e dev --no-prompt

However, one interesting gotcha was that when i do azd pipeline config the client id that it stores in gitbub variables was wrong so i just had to update that in github with the correct one

Looks like it was using the value from AZURE_PIPELINE_CLIENT_ID in the .env file instead of MANAGED_IDENTITY_CLIENT_ID... despite AZD_PIPELINE_PROVIDER being set to 'github' Not sure why they are different though.

broline avatar Apr 20 '24 15:04 broline

I've not tried out adding 'AZD_INITIAL_ENVIRONMENT_CONFIG' to my library just yet, I imagine adding a multi-line json string to the library would work, just looks a little messy in what is otherwise key/value pairs.

What I've done at the moment is use 'azd infra synth'. I've left the connection string as an input in main.parameters and main.bicep. I just then added the connection string as an output variable at the end of the main.bicep file. I've then updated the tml.yaml file, replacing the parameter with something along these lines:

      - name: connectionstrings--sql
        value: '{{ .Env.SQL_CONNECTIONSTRING }}'    <-- Name of the output variable from main.bicep

Seen as this is working for now, and is nice and consistent with how all the other connection strings are set up, I might leave as is and hang on a little longer to see if a more user-friendly way of doing this emerges.

Maybe anything that's an input in main.parameters.json should be available as an output like I've done. Then it can be used easily by CI/CD and you don't have this separate and not so intuitive home for variables in the form of json against 'AZD_INITIAL_ENVIRONMENT_CONFIG'. If other connection strings are ending up in the .env file, this separate secure parameter concept seems a bit redundant and confusing.

mip1983 avatar Apr 29 '24 08:04 mip1983

@mip1983 Is this still working after AZD 1.9.0? I tried implementing your solution by editing the azd infra synth but my *.tmpl.yaml files are being ignored by azd deploy.

Bpflugrad avatar May 09 '24 22:05 Bpflugrad

@mip1983 , ideally, you should not set connections strings as output params and/or write them to .env files. Your workaround of updating the tml.yaml works, but you are relaxing security.

Consider using AZD_INITIAL_ENVIRONMENT_CONFIG. See this: https://github.com/Azure/azure-dev/issues/3850#issuecomment-2103915345

vhvb1989 avatar May 10 '24 06:05 vhvb1989

@mip1983 , ideally, you should not set connections strings as output params and/or write them to .env files. Your workaround of updating the tml.yaml works, but you are relaxing security.

Consider using AZD_INITIAL_ENVIRONMENT_CONFIG. See this: #3850 (comment)

I don't feel this is well addressed with this 'AZD_INITIAL_ENVIRONMENT_CONFIG' param. It doesn't suit the key-value nature of an Azure DevOps variable library, it's not intuitive or well documented (correct me if I've missed something there) and I think it's left a few users scratching heads from what I can tell. It's overly complex to simply add a connection string.

You've got all the other config including connection strings for blob storage and app insights etc. being put into .env files when using azd locally. Why is this bit of config not in the same place, and why is the json file secure and the env file not? It's not a file in source control, and I'm only using it locally during the setup phase to test things. It's not something that will get checked in and used as a real store for the wider dev team. The dev team will have this in secrets.json during local dev, and it'll be secured in Azure DevOps for deployment.

The connection strings for deployment in an Azure DevOps library are secured by permissions within Azure DevOps and can be backed by key vault, so this seems like a reasonable place to want to keep this config securely, having different libraries for different environments.

As such, I really think you should be able to easily pass variables like these connection strings from a library in Azure DevOps into azd in your CI/CI pipeline. It's a bit messy with one connection at the moment, but if you had multiple and you're cramming them all into this one 'AZD_INITIAL_ENVIRONMENT_CONFIG' variable in your library, it's just not very clean and doesn't seem like how it should be organized.

Originally I was trying to pass this variable in my pipeline via the 'env' section, I think this should be supported with it being on the user to secure Azure Devops libraries. If it could accept this input as a secure param, I wouldn't then need the work around outputting it in bicep.

Or better yet, if possible, the task should pick up matching variables from the variable group specified on the pipeline without having to manually pass them in on the task.

/unresolve

mip1983 avatar May 10 '24 07:05 mip1983

@mip1983 Is this still working after AZD 1.9.0? I tried implementing your solution by editing the azd infra synth but my *.tmpl.yaml files are being ignored by azd deploy.

Yes, this has stopped working for me since 1.9, I'm going to do some more playing around with it, but it seems like it's not picking up things in the yaml file, including my custom domain binding (#3875).

mip1983 avatar May 10 '24 08:05 mip1983

You've got all the other config including connection strings for blob storage and app insights etc. being put into .env files

There should be only host names, but not connection strings (including keys).

For any parameter that Aspire-manifest defines as secured() , azd can't just place the value for it in plain text in .env Even if it is not checked-in to the repo, it becomes a vulnerability (what if the repo is not github, or what if the .gitignore gets removed, etc). The security bar must be as high as possible when it comes to parameters set as secured.

In a world where azd would only be meant to run in CI/CD, it would be ok to directly use one secret for each parameter, which, in fact, works for mapping env to infra. But for deploy services, azd needs to know where to get the value from (.env , config, etc). Regardless of where azd is running (CI or local).

vhvb1989 avatar May 10 '24 08:05 vhvb1989

Ok, so because it could have credentials and is marked as secured() it get's treated with extra caution locally and you don't see the value in .env or config.json, makes sense.

What about allowing the user to explicitly specify as an argument that they want to accept secure params from the environment so this is something you can do deliberately just in a pipeline? i.e.

  - task: AzureCLI@2
    displayName: 'Deploy application to staging'
    inputs:
      azureSubscription: 'mySub'
      scriptType: 'bash'
      scriptLocation: 'inlineScript'
      inlineScript: 'azd deploy --no-prompt --secure-params-from-env'  <-- Extra arg
    env:
      AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
      AZURE_ENV_NAME: $(AZURE_ENV_NAME)
      AZURE_LOCATION: $(AZURE_LOCATION)
      AZURE_MY_SECURE_PARAM: $(Library_Variable)  <-- This is the parameter name you see in main.parameters.json, azd should give a clear message in the console output with the variable name if it's not been supplied rather than just panic.

mip1983 avatar May 10 '24 09:05 mip1983

@vhvb1989 @mip1983 can we mark this complete? anything pending here?

rajeshkamal5050 avatar Aug 13 '24 18:08 rajeshkamal5050

@rajeshkamal5050

Hi there, nothing has changed much on this front as far as I'm aware.

I'd say if the goal of Aspire is to simplify and remove the pain/complexity of building and deploying cloud native apps, then this aspect of supplying a connection string (secured parameter) in a CI/CD pipeline (including one that's not had the yaml generated via azd) is still too difficult to figure and clunky (in my opinion, but I think I've seen a few posts by others on GitHub on it). It isn't really covered in the documentation unless there's more detail elsewhere?

I still have 'AZD_INITIAL_ENVIRONMENT_CONFIG' with some JSON in the value field in Libraries in the Azure DevOps which is really for key/value pairs. I'd like to see a better way and clear documentation, perhaps like I've mentioned in my previous comment.

mip1983 avatar Aug 14 '24 09:08 mip1983

it's not intuitive or well documented (correct me if I've missed something there)

I can confirm that this issue/thread is the "Best" documentation that I have found for this field and I am still very much unclear how to use it for my own purposes.

Mike-E-angelo avatar Aug 31 '24 08:08 Mike-E-angelo

It would be great if this can be simplified, right now the cli command has everything mixed up and since we had to do a custom action file the cli tries to set the environment variables each time we want to update the secure arguments.

The current process is cumbersome as I have to pull the secrets to my local machine to then use the cli and manually paste it one by one before running azd pipeline config.

It would be great if azd/aspire supported using a keyvault to pull the secrets just like it's possible with bicep using the deployment parameters file. We could even use the same deploymentParameters.json file and would make it much more straightforward to setup.

gabynevada avatar Sep 26 '24 06:09 gabynevada

@vhvb1989 I was working on a pet project today and I ran into this issue when I wanted to start making use of GitHub Environments in my GitHub Actions. The problem with AZD_INITIAL_ENVIRONMENT_CONFIG is that you never know what should be in it - its a cliff from a user experience point of view.

I think this is an area that we need to look at overall in terms of:

  1. Making AZD_INITIAL_ENVIRONMENT_CONFIG unnecessary
  2. Making azd pipeline config GitHub Environment aware (so that user principals can support environment entity type credentials).

People should be able to define additional environments just by adding the environment in GitHub and setting the unique values for that environment (e.g. AZD_ENV_NAME).

In GitHub Actions its extra hard because there is literally no way to look at the existing value of AZD_INITIAL_ENVIRONMENT_CONFIG to reason over what might need to be tweaked.

azd pipeline config shouldn't necessarily have to create a new app registration either.

mitchdenny avatar Dec 22 '24 06:12 mitchdenny

I am having this same issue in Azure DevOps, and I tried the steps outline here to no avail:

  • create a pipeline variable called AZD_INITIAL_ENVIRONMENT_CONFIG
  • copy the contents of the .azure/<env_name>/config.json file into it
  • reference the variable in the YAML, like this:
  - task: AzureCLI@2
    displayName: Deploy Service Layer Core
    inputs:
      azureSubscription: azconnection
      scriptType: bash
      scriptLocation: inlineScript
      keepAzSessionActive: true
      inlineScript: |
        cd $(Build.SourcesDirectory)/ServiceLayer.AppHost;
        ls -la;
        azd deploy --no-prompt --environment $(AZURE_ENV_NAME);
    env:
      AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
      AZURE_ENV_NAME: $(AZURE_ENV_NAME)
      AZURE_LOCATION: $(AZURE_LOCATION)
      AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG)

However, I still get the same error when the pipeline runs azd deploy:

ERROR: failed deploying service 'account-service': failed executing template file: template: manifest template:27:19: executing "manifest template" at <securedParameter "CacheConnection">: error calling securedParameter: parameter CacheConnection not found

I added a step to echo out the contents of the environment variable, and all looks fine with that:

Image

All the great simplicity of running azd deploy locally from the command line seems to evaporate when trying to set up an Azure DevOps pipeline, which is a shame. If I'm doing something wrong with the above, please let me know, as I'm pretty frustrated currently :-)

Cheers,

Stu

Update:

I also tried creating the AZDO pipeline using azd pipeline config --provider azdo. It created the AZD_INITIAL_ENVIRONMENT_CONFIG variable for me, but I still get the same error on the azd deploy ...

essenbee2 avatar Jan 28 '25 10:01 essenbee2

This was solved for me - turns out I had run azd init in the AppHost folder. Running it in the root of the solution, then running azd pipeline config --provider azdo in that same folder fixed the problem.

essenbee2 avatar Feb 02 '25 13:02 essenbee2

Please correct me if i'm wrong, but after reading through this thread my understanding is that the only way to provide values to parameters defined in Aspire app model (be it builder.AddConnectionString or builder.AddParameter), in a prompt-less way, is via the AZD_INITIAL_ENVIRONMENT_CONFIG env variable? Which means the the expected flow looks like this:

  1. Run azd init locally
  2. Run azd provision locally, manually enter values for every defined parameter when prompted
  3. Copy contents of the .azure/{env-name}/config.json file over to AZD_INITIAL_ENVIRONMENT_CONFIG variable in the build pipeline
  4. Add the env section to your azd deploy --no-prompt build step like so:
env: 
    AZD_INITIAL_ENVIRONMENT_CONFIG: $(AZD_INITIAL_ENVIRONMENT_CONFIG)

The azd pipeline config can automate the step number 3, but won't help if you manage your CICD pipelines manually?

After reading all of this I'm somehow even more confused than I was before. The AZD_INITIAL_ENVIRONMENT_CONFIG is never mentioned anywhere in the docs, at least I couldn't find it. Most likely because it was supposed to 'just work' for people using azd pipeline config.

The .NET Aspire docs section about 'external parameters' never mentions anything about deployment either, it reads like you can provide parameter values in normal way via env variables, appsettings.*.json files, etc, which turns out only works when running apphost locally.

My assumption was that I would be able to manage all the parameters in my CICD (via variable groups, environment variables, supply them from azure key vault, etc), like I would normally do. And then the azd would pass them down the chain into the bicep files and eventually deploy the infrastructure. Right now it feels like you have to manually intervene somewhere in the middle of the flow for it to work properly.

ddizh avatar Mar 13 '25 15:03 ddizh

My assumption was that I would be able to manage all the parameters in my CICD (via variable groups, environment variables, supply them from azure key vault, etc), like I would normally do. And then the azd would pass them down the chain into the bicep files and eventually deploy the infrastructure. Right now it feels like you have to manually intervene somewhere in the middle of the flow for it to work properly.

This was our assumption as well and pretty much had to implement custom logic to bypass those limitations.

In bicep's case, we generate a complete parameter file ourselves to avoid azd reliance on config.json.

If we had to rely on config.json, we would just wrap a loop around all environment variables starting with a prefix and modify the json file directly like we already do with the parameter file.

In the end, this allows us to pass AZD_INITIAL_ENVIRONMENT_CONFIG as simply {"infra":{"parameters":{}}}. That reliance on AZD_INITIAL_ENVIRONMENT_CONFIG even sounds crazy to me, why would we want to pass a json object as a critical component of the tool through an environment variable. And why do we have to copy/paste a whole JSON object from some unversioned folder?

My initial expectation from azd for CI/CD was "You have a parameter storage_name to pass to bicep, you add an environment variable AZD_PARAM_storage_name to make the binding". Or allowing you to pass inline parameters with azd provision. Not relying on some magic env variable that is somewhat explained in a single issue on this repository.

In my opinion, there needs a major overall of the entire CI/CD process with azd because:

  1. It entirely relies on people using azd pipeline config with little documentation on how to setup everything manually
  2. azd pipeline config relies on permissions that a developer wouldn't normally have. Ie: User access administrator on the subscription
  3. You cannot provide the name or id of a service connection with everything already setup on ADO. Why should I have the UAA role on the subscription when my org requires to use an automated provisioning process that setups everything on Azure so that users with this specific role are limited?
  4. Separation of build, provisioning and deployment is not supported when using --with-package or azd provision unless you carry and artifact with your code on every stage/job
  5. A lot of little annoyances when you want to take an approach similar to what you would use with New-AzResourceGroupDeployment/az deployment group create

For CI/CD, I believe AZD has good value. For bicep deployments, you get a state comparison built-in to reduce job times and the way you can define applications in azure.yaml is very simple compared to the equivalent ADO tasks AzureFunction@2, AzureWebApp@2, ...

But when you get to configuring everything there are a lot of unecessary friction because you are supposed to do everything in one way and nothing else.

GABRIELNGBTUC avatar Mar 17 '25 09:03 GABRIELNGBTUC

My assumption was that I would be able to manage all the parameters in my CICD (via variable groups, environment variables, supply them from azure key vault, etc), like I would normally do. And then the azd would pass them down the chain into the bicep files and eventually deploy the infrastructure. Right now it feels like you have to manually intervene somewhere in the middle of the flow for it to work properly.

This was our assumption as well and pretty much had to implement custom logic to bypass those limitations.

In bicep's case, we generate a complete parameter file ourselves to avoid azd reliance on config.json.

If we had to rely on config.json, we would just wrap a loop around all environment variables starting with a prefix and modify the json file directly like we already do with the parameter file.

In the end, this allows us to pass AZD_INITIAL_ENVIRONMENT_CONFIG as simply {"infra":{"parameters":{}}}. That reliance on AZD_INITIAL_ENVIRONMENT_CONFIG even sounds crazy to me, why would we want to pass a json object as a critical component of the tool through an environment variable. And why do we have to copy/paste a whole JSON object from some unversioned folder?

My initial expectation from azd for CI/CD was "You have a parameter storage_name to pass to bicep, you add an environment variable AZD_PARAM_storage_name to make the binding". Or allowing you to pass inline parameters with azd provision. Not relying on some magic env variable that is somewhat explained in a single issue on this repository.

In my opinion, there needs a major overall of the entire CI/CD process with azd because:

  1. It entirely relies on people using azd pipeline config with little documentation on how to setup everything manually
  2. azd pipeline config relies on permissions that a developer wouldn't normally have. Ie: User access administrator on the subscription
  3. You cannot provide the name or id of a service connection with everything already setup on ADO. Why should I have the UAA role on the subscription when my org requires to use an automated provisioning process that setups everything on Azure so that users with this specific role are limited?
  4. Separation of build, provisioning and deployment is not supported when using --with-package or azd provision unless you carry and artifact with your code on every stage/job
  5. A lot of little annoyances when you want to take an approach similar to what you would use with New-AzResourceGroupDeployment/az deployment group create

For CI/CD, I believe AZD has good value. For bicep deployments, you get a state comparison built-in to reduce job times and the way you can define applications in azure.yaml is very simple compared to the equivalent ADO tasks AzureFunction@2, AzureWebApp@2, ...

But when you get to configuring everything there are a lot of unecessary friction because you are supposed to do everything in one way and nothing else.

We can totally relate to this. AZD is a wonderful tool, especially in conjunction with .NET Aspire. But the way it resolves parameters from within a CI/CD pipeline shouldn't be this much of a hassle.

Fazer01 avatar Apr 16 '25 06:04 Fazer01

This is fixed by https://github.com/Azure/azure-dev/pull/5143 https://github.com/Azure/azure-dev/pull/5190

Please use and try with AZD 1.16.0. Re-open if you still observe issues.

vhvb1989 avatar May 15 '25 00:05 vhvb1989

Thanks, that's a nice one to solve.

Link here for anyone following along: 9.3 CI/CD updates

mip1983 avatar May 21 '25 12:05 mip1983