Tutorial: Deploy a .NET Aspire project using the Azure Developer CLI and GitHub Actions

The Azure Developer CLI (azd) enables you to deploy .NET Aspire projects using GitHub Actions by automatically configuring the required authentication and environment settings. This article walks you through the process of creating and deploying a .NET Aspire project on Azure Container Apps using azd and GitHub Actions. You learn the following concepts:

  • Explore how azd integration works with .NET Aspire projects and GitHub Actions
  • Create and configure a GitHub repository for a .NET Aspire project using azd
  • Add a GitHub Actions workflow file to your .NET Aspire solution
  • Monitor and explore GitHub Actions workflow executions and Azure deployments

Prerequisites

To work with .NET Aspire, you need the following installed locally:

For more information, see .NET Aspire setup and tooling, and .NET Aspire SDK.

You also need to have the Azure Developer CLI installed locally (version 1.5.1 or higher). Common install options include the following:

winget install microsoft.azd

Create a .NET Aspire solution

As a starting point, this article assumes that you've created a .NET Aspire solution from the .NET Aspire Starter Application template. For more information, see Quickstart: Build your first .NET Aspire app.

Initialize the template

  1. Open a new terminal window and cd into the AppHost project directory of your .NET Aspire solution.

  2. Execute the azd init command to initialize your project with azd, which will inspect the local directory structure and determine the type of app.

    azd init
    

    For more information on the azd init command, see azd init.

  3. Select Use code in the current directory when azd prompts you with two app initialization options.

    ? How do you want to initialize your app?  [Use arrows to move, type to filter]
    > Use code in the current directory
      Select a template
    
  4. After scanning the directory, azd prompts you to confirm that it found the correct .NET Aspire AppHost project. Select the Confirm and continue initializing my app option.

    Detected services:
    
      .NET (Aspire)
      Detected in: D:\source\repos\AspireSample\AspireSample.AppHost\AspireSample.AppHost.csproj
    
    azd will generate the files necessary to host your app on Azure using Azure Container Apps.
    
    ? Select an option  [Use arrows to move, type to filter]
    > Confirm and continue initializing my app
      Cancel and exit
    
  5. Enter an environment name, which is used to name provisioned resources in Azure and managing different environments such as dev and prod.

    Generating files to run your app on Azure:
    
      (✓) Done: Generating ./azure.yaml
      (✓) Done: Generating ./next-steps.md
    
    SUCCESS: Your app is ready for the cloud!
    You can provision and deploy your app to Azure by running the azd up command in this directory. For more information on configuring your app, see ./next-steps.md
    

azd generates a number of files and places them into the working directory. These files are:

  • azure.yaml: Describes the services of the app, such as .NET Aspire AppHost project, and maps them to Azure resources.
  • .azure/config.json: Configuration file that informs azd what the current active environment is.
  • .azure/aspireazddev/.env: Contains environment specific overrides.

Add the GitHub Actions workflow file

Although azd generated some essential template files for you, the project still needs a GitHub Actions workflow file to support provisioning and deployments using CI/CD.

  1. Create an empty .github folder at the root of your project. azd uses this directory by default to discover GitHub Actions workflow files.

    Tip

    If you're on macOS user and you're struggling to create a folder with a leading ., you can use the terminal to create the folder. Open the terminal and navigate to the root of your project. Run the following command to create the folder:

    mkdir .github
    
  2. Inside the new .github folder, create another folder called workflows (you'll end up with .github/workflows).

  3. Add a new GitHub Actions workflow file into the new folder named azure-dev.yml. The azd starter template provides a Sample GitHub Actions workflow file that you can copy into your project.

  4. Update the sample GitHub Actions workflow to include a step to install the .NET Aspire workload. This ensures the .NET Aspire tooling and commands are available to the job running your GitHub Actions. The completed workflow file should match the following:

    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:
          - main
    
    permissions:
      id-token: write
      contents: read
    
    jobs:
      build:
        runs-on: ubuntu-latest
        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_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
          AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
        steps:
          - name: Checkout
            uses: actions/checkout@v4
    
          - name: Install azd
            uses: Azure/setup-azd@v1.0.0
    
          - 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 --no-prompt
            # Required when 
            # env:
            #   AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }}
    
          # Required when provisioning and deploying are defined in separate jobs.
          # - name: Refresh azd env (pulls latest infrastructure provision)
          #  run: azd env refresh
          #  env:
          #    AZURE_LOCATION: ${{ env.AZURE_LOCATION }}
    
          - name: Deploy Application
            run: azd deploy --no-prompt
    

Additionally, you may notice that the provisioning and deployment steps are combined into a single job. If you prefer to separate these steps into different jobs, you can do so by creating two separate jobs in the workflow file. The provisioning job should run first, followed by the deployment job. The deployment job should include the AZD_INITIAL_ENVIRONMENT_CONFIG secret to ensure the deployment job has access to the environment configuration. You'd also need to uncomment the azd env refresh step in the deployment job to ensure the deployment job has access to the latest infrastructure provision.

Create the GitHub repository and pipeline

The Azure Developer CLI enables you to automatically create CI/CD pipelines with the correct configurations and permissions to provision and deploy resources to Azure. azd can also create a GitHub repository for your app if it doesn't exist already.

  1. Run the azd pipeline config command to configure your deployment pipeline and securely connect it to Azure:

    azd pipeline config
    
  2. Select the subscription to provision and deploy the app resources to.

  3. Select the Azure location to use for the resources.

  4. When prompted whether to create a new Git repository in the directory, enter y and press Enter.

    Note

    Creating a GitHub repository required you being logged into GitHub. There are a few selections that vary based on your preferences. After logging in, you will be prompted to create a new repository in the current directory.

  5. Select Create a new private GitHub repository to configure the git remote.

  6. Enter a name of your choice for the new GitHub repository or press enter to use the default name. azd creates a new repository in GitHub and configures it with the necessary secrets required to authenticate to Azure.

    A screenshot showing the pipeline configuration steps.

  7. Enter y to proceed when azd prompts you to commit and push your local changes to start the configured pipeline.

Explore the GitHub Actions workflow and deployment

  1. Navigate to your new GitHub repository using the link output by azd.

  2. Select the Actions tab to view the repository workflows. You should see the new workflow either running or already completed. Select the workflow to view the job steps and details in the logs of the run. For example, you can expand steps such as Install .NET Aspire Workload or Deploy application to see the details of the completed action.

    A screenshot showing the GitHub Action workflow steps.

  3. Select Deploy Application to expand the logs for that step. You should see two endpoint urls printed out for the apiservice and webfrontend. Select either of these links to open them in another browser tab and explore the deployed application.

    A screenshot showing the deployed app links.

Congratulations! You successfully deployed a .NET Aspire project using the Azure Developer CLI and GitHub Actions.

Configure the workflow file

Although azd generated some essential template files for you, the project still needs an Azure Pipelines workflow file to support provisioning and deployments using CI/CD.

  1. Create an empty .azdo folder at the root of your project. azd uses this directory by default to discover Azure Pipelines workflow files.

  2. Inside the new .azdo folder, create another folder called pipelines (you'll end up with .azdo/pipelines).

  3. Add a new Azure Pipelines workflow file into the new folder named azure-dev.yml. The azd starter template provides a Sample Azure Pipelines workflow file that you can copy into your project.

  4. Update the sample Azure Pipelines workflow to include a step to install the .NET Aspire workload. The completed workflow file should match the following:

trigger:
  - main
  - master

pool:
  vmImage: ubuntu-latest

steps:

  - task: Bash@3
    displayName: Install azd
    inputs:
      targetType: 'inline'
      script: |
        curl -fsSL https://aka.ms/install-azd.sh | bash

  # azd delegate auth to az to use service connection with AzureCLI@2
  - pwsh: |
      azd config set auth.useAzCliAuth "true"
    displayName: Configure `azd` to Use AZ CLI Authentication.

  - task: Bash@3
    displayName: Install .NET Aspire workload
    inputs:
      targetType: 'inline'
      script: |
        dotnet workload install aspire

  - task: AzureCLI@2
    displayName: Provision Infrastructure
    inputs:
      azureSubscription: azconnection
      scriptType: bash
      scriptLocation: inlineScript
      inlineScript: |
        azd provision --no-prompt
    env:
      AZURE_SUBSCRIPTION_ID: $(AZURE_SUBSCRIPTION_ID)
      AZURE_ENV_NAME: $(AZURE_ENV_NAME)
      AZURE_LOCATION: $(AZURE_LOCATION)

  - task: AzureCLI@2
    displayName: Deploy Application
    inputs:
      azureSubscription: azconnection
      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)

Create the Azure DevOps repository and pipeline

Important

As mentioned in the prerequisites, you'll need to create an Azure DevOps organization or select an existing organization to complete the steps ahead. You will also need to create a Personal Access Token (PAT) with the permissions listed in the prerequisites.

The Azure Developer CLI enables you to automatically create pipelines with the correct configurations and permissions to provision and deploy resources to Azure. azd can also create an Azure Pipelines repository for your app if it doesn't exist already.

  1. Run the azd pipeline config command to configure your deployment pipeline and securely connect it to Azure. Include the --provider azdo option to use Azure Pipelines instead of the default GitHub Actions configuration.

    azd pipeline config --provider azdo
    
  2. Select the subscription to provision and deploy the app resources to.

  3. Select the Azure location to use for the resources.

  4. Paste the Personal Access Token you created earlier.

  5. Enter the Azure DevOps Organization name you created or selected.

  6. When prompted to create a new repository in the current directory, enter y and press Enter.

  7. When prompted to configure the git remote, select Create a new Azure DevOps Project.

  8. Enter a unique name of your choice for the new repository, such as aspireazd. azd creates a new repository in Azure Repos and configures it with the necessary secrets required to authenticate to Azure.

    A screenshot showing the pipeline configuration steps.

  9. Enter y to proceed when azd prompts you to commit and push your local changes to start the configured pipeline.

Explore the pipeline and deployed app

  1. Navigate to your new Azure Pipeline using the status link output by azd.

    A screenshot showing the successful Azure Pipelines run.

  2. Select the completed pipeline run to view the summary.

    A screenshot showing the summary view of the Azure Pipelines run.

  3. Select the job link at the bottom of the view to navigate to the job details.

    A screenshot showing the detailed view of the Azure Pipelines run.

  4. The job details page shows the status of all the individual stages. Select Provision Infrastructure to view the logs for that stage, which detail all of the provisioning steps completed by azd. At the bottom of the logs take note of the final status message and link to the provisioned Azure resource group.

  5. Select the link at the bottom of the provisioning output logs to navigate to the new Azure resource group.

    A screenshot showing the deployed Azure resources.

    Note

    You can also navigate directly to your new resource group by searching for it in the Azure Portal. Your resource group name will be the environment name you provided to azd prefixed with rg-.

  6. Select the webfrontend container app, which hosts the public facing portion of your site.

  7. On the webfrontend details page, select the Application Url link to open your site in the browser.

Important

If you encounter a 403 Forbidden error when viewing your site in the browser, make sure the ingress settings are configured correctly. On the webfrontend app page in the Azure Portal, navigate to Ingress on the left navigation. Make sure Ingress traffic is set to Accepting traffic from anywhere and save your changes.

Congratulations! You successfully deployed a .NET Aspire project using the Azure Developer CLI and Azure Pipelines.

Clean up resources

Run the following Azure CLI command to delete the resource group when you no longer need the Azure resources you created. Deleting the resource group also deletes the resources contained inside of it.

az group delete --name <your-resource-group-name>

For more information, see Clean up resources in Azure.