Configure a pipeline and push updates
In this article, you'll learn how to use the Azure Developer CLI (azd
) to push template changes through a CI/CD pipeline such as GitHub Actions or Azure DevOps. For this example you'll use the React Web App with Node.js API and MongoDB on Azure template, but you can apply the principles you learn in this article to any of the Azure Developer CLI templates.
Note
The azd pipeline config
command is still in beta. Read more about alpha and beta feature support on the feature versioning and release strategy page.
Prerequisites
azd
templates may or may not include a default GitHub Actions and/or Azure DevOps pipeline configuration file called azure-dev.yml
, which is required to setup CI/CD. This configuration file provisions your Azure resources and deploy your code to the main branch. You can find azure-dev.yml
:
- For GitHub Actions: in the
.github/workflows
directory. - For Azure DevOps: in the
.azdo/pipelines
directory.
You can use the configuration file as-is or modify it to suit your needs.
Note
Make sure your template has a pipeline definition (azure-dev.yaml
) before calling azd pipeline config
. azd
does not automatically create this file.
See Create a pipeline definition for azd below.
Use the azd pipeline config
command to configure a CI/CD pipeline, which handles the following tasks:
- Creates and configures a service principal for the app on the Azure subscription. Your user must have either
Owner
role orContributor + User Access Administrator
roles within the Azure subscription to allow azd to create and assign roles to the service principal. - Steps you through a workflow to create and configure a GitHub or Azure DevOps repository and commit your project code to it. You can also choose to use an existing repository.
- Creates a secure connection between Azure and your repository.
- Runs the GitHub action when you check in the workflow file.
For more granular control over this process, or if you user does not have the required roles, you can manually configure a pipeline.
Select your preferred pipeline provider to continue:
Authorize GitHub to deploy to Azure
To configure the workflow, you need to authorize a service principal to deploy to Azure on your behalf, from a GitHub action. azd
creates the service principal and a federated credential for it.
Run the following command to create the Azure service principal and configure the pipeline:
azd pipeline config
This command, optionally creates a GitHub repository and pushes code to the new repo.
Note
By default,
azd pipeline config
uses OpenID Connect (OIDC), called federated credentials. If you'd rather not use OIDC, runazd pipeline config --auth-type client-credentials
.OIDC/federated credentials are not supported for Terraform.
Supply the requested GitHub information.
When prompted about committing and pushing your local changes to start a new GitHub Actions run, specify
y
.In the terminal window, view the results of the
azd pipeline config
command. Theazd pipeline config
command will output the GitHub repository name for your project.Using your browser, open the GitHub repository for your project.
Select Actions to see the workflow running.
Make and push a code change
In the project's
/src/web/src/layout
directory, openheader.tsx
.Locate the line
<Text variant="xLarge">ToDo</Text>
.Change the literal
ToDo
tomyTodo
.Save the file.
Commit your change. Committing the change starts the GitHub Action pipeline to deploy the update.
Using your browser, open your project's GitHub repository to see both:
- Your commit
- The commit from GitHub Actions being set up.
Select Actions to see the test update reflected in the workflow.
Visit the web frontend URL to inspect the update.
azd
as a GitHub action
Add azd
as a GitHub action. This action will install azd
. To use it, you can add the following to .github\workflows\azure-dev.yml
:
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Install azd
uses: Azure/setup-azd@v0.1.0
Clean up resources
When you no longer need the Azure resources created in this article, run the following command:
azd down
Advanced features
You can extend the azd pipeline config
command for specific template scenarios or requirements, as described in the following sections.
Additional secrets or variables
By default, azd
sets variables and secrets for the pipeline. For example, the azd pipeline config
command creates the subscription id
, environment name
and the region
as pipeline variables whenever it executes. The pipeline definition then references those variables:
env:
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 }}
When the pipeline runs, azd
gets the values from the environment, which is mapped to the variables and secrets. Depending on the template, there might be settings which you can control using environment variables. For example, an environment variable named KEY_VAULT_NAME
could be set to define the name of a Key Vault resource within the template infrastructure. For such cases, the list of variables and secrets can be defined by the template, using the azure.yaml
. For example, consider the following azure.yaml
configuration:
pipeline:
variables:
- KEY_VAULT_NAME
- STORAGE_NAME
secrets:
- CONNECTION_STRING
With this configuration, azd
checks if any of the variables or secrets have a non-empty value in the environment. azd
then creates either a variable or a secret for the pipeline using the name of the key in the configuration as the name of the variable or secret, and the non-string value from the environment for the value.
The azure-dev.yaml
pipeline definition can then reference the variables or secrets:
- name: Provision Infrastructure
run: azd provision --no-prompt
env:
KEY_VAULT_NAME: ${{ variables.KEY_VAULT_NAME }}
STORAGE_NAME: ${{ variables.STORAGE_NAME }}
CONNECTION_STRING: ${{ secrets.CONNECTION_STRING }}
Note
You must run azd pipeline config
after updating the list of secrets or variables in azure.yaml
for azd to reset the pipeline values.
Infrastructure parameters
Consider the following bicep example:
@secure()
param BlobStorageConnection string
The parameter BlobStorageConnection
has no default value set, so azd
prompts the user to enter a value. However, there is no interactive prompt during CI/CD. azd
must request the value for the parameter when you run azd pipeline config
, save the value in the pipeline, and then fetch the value again when the pipeline runs.
azd
uses a pipeline secret called AZD_INITIAL_ENVIRONMENT_CONFIG
to automatically save and set the value of all the required parameters in the pipeline. You only need to reference this secret in your pipeline:
- name: Provision Infrastructure
run: azd provision --no-prompt
env:
AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }}
When the pipeline runs, azd
takes the values for the parameters from the secret, removing the need for an interactive prompt.
Note
You must re-run azd pipeline config
if you add a new parameter.
Create a pipeline definition
If your azd
template doesn't already have a CI/CD pipeline definition file, you can create one yourself. A CI/CD pipeline definition has typically 4 main sections:
- trigger
- permissions
- operating system or pool
- steps to be run
The following examples demonstrate how to create a definition file and related configurations for GitHub Actions and Azure Pipelines.
Running azd
in GitHub Actions requires the following configurations:
- Grant
id-token: write
andcontents: read
access scopes. - Install the azd action, unless you are using a docker image where
azd
is already installed.
You can use the following template as a starting point for your own pipeline definition:
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
- master
# Set this permission if you are using a Federated Credential.
permissions:
id-token: write
contents: read
jobs:
build:
runs-on: ubuntu-latest
# azd build-in variables.
# This variables are always set by `azd pipeline config`
# You can set them as global env (apply to all steps) or you can add them to individual steps' environment
env:
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 }}
## Define the additional variables or secrets that are required globally (provision and deploy)
# ADDITIONAL_VARIABLE_PLACEHOLDER: ${{ variables.ADDITIONAL_VARIABLE_PLACEHOLDER }}
# ADDITIONAL_SECRET_PLACEHOLDER: ${{ secrets.ADDITIONAL_SECRET_PLACEHOLDER }}
steps:
- name: Checkout
uses: actions/checkout@v4
# using the install-azd action
- name: Install azd
uses: Azure/setup-azd@v1.0.0
# # If you want to use azd-daily build, or install it from a PR, you can remove previous step and
# # use the next one:
# - name: Install azd - daily or from PR
# # Update this scrip based on the OS - pool of your pipeline. This example is for a linux pipeline installing daily build
# run: curl -fsSL https://aka.ms/install-azd.sh | bash -s -- --version daily
# shell: pwsh
# azd set up Federated Credential by default. You can remove this step if you are using Client Credentials
- 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
## If you set up your pipeline with Client Credentials, remove previous step and uncomment this one
# - 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
# env:
# AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }}
- name: Provision Infrastructure
run: azd provision --no-prompt
env:
# # uncomment this if you are using infrastructure parameters
# AZD_INITIAL_ENVIRONMENT_CONFIG: ${{ secrets.AZD_INITIAL_ENVIRONMENT_CONFIG }}
## Define the additional variables or secrets that are required only for provision
# ADDITIONAL_VARIABLE_PLACEHOLDER: ${{ variables.ADDITIONAL_VARIABLE_PLACEHOLDER }}
# ADDITIONAL_SECRET_PLACEHOLDER: ${{ secrets.ADDITIONAL_SECRET_PLACEHOLDER }}
- name: Deploy Application
run: azd deploy --no-prompt
env:
## Define the additional variables or secrets that are required only for deploy
# ADDITIONAL_VARIABLE_PLACEHOLDER: ${{ variables.ADDITIONAL_VARIABLE_PLACEHOLDER }}
# ADDITIONAL_SECRET_PLACEHOLDER: ${{ secrets.ADDITIONAL_SECRET_PLACEHOLDER }}