Deploy to App Service using Azure Pipelines
Azure DevOps Services | Azure DevOps Server 2020 | Azure DevOps Server 2019
Note
Starting June 1, 2024, all newly created App Service apps will have the option to generate a unique default hostname using the naming convention <app-name>-<random-hash>.<region>.azurewebsites.net
. Existing app names will remain unchanged.
Example: myapp-ds27dh7271aah175.westus-01.azurewebsites.net
For further details, refer to Unique Default Hostname for App Service Resource.
Use Azure Pipelines to automatically deploy your web app to Azure App Service on every successful build. Azure Pipelines lets you build, test, and deploy with continuous integration (CI) and continuous delivery (CD) using Azure DevOps.
YAML pipelines are defined using a YAML file in your repository. A step is the smallest building block of a pipeline and can be a script or task (prepackaged script). Learn about the key concepts and components that make up a pipeline.
You'll use the Azure Web App task (AzureWebApp
) to deploy to Azure App Service in your pipeline. For more complicated scenarios such as needing to use XML parameters in your deploy, you can use the Azure App Service deploy task (AzureRmWebAppDeployment).
- An Azure account with an active subscription. Create an account for free.
- An Azure DevOps organization. Create one for free.
- An ability to run pipelines on Microsoft-hosted agents. You can either purchase a parallel job or you can request a free tier.
- A working Azure App Service app with code hosted on GitHub or Azure Repos.
The code examples in this section assume you're deploying an ASP.NET web app. You can adapt the instructions for other frameworks.
Learn more about Azure Pipelines ecosystem support.
Sign in to your Azure DevOps organization and navigate to your project.
Go to Pipelines, and then select New Pipeline.
When prompted, select the location of your source code: either Azure Repos Git or GitHub.
You might be redirected to GitHub to sign in. If so, enter your GitHub credentials.
When the list of repositories appears, select your repository.
You might be redirected to GitHub to install the Azure Pipelines app. If so, select Approve & install.
When the Configure tab appears, select ASP.NET Core.
When your new pipeline appears, take a look at the YAML to see what it does. When you're ready, select Save and run.
Click the end of the YAML file, then select Show assistant.'
Use the Task assistant to add the Azure Web App task.
Alternatively, you can add the Azure App Service deploy (AzureRmWebAppDeployment) task.
Choose your Azure subscription. Make sure to Authorize your connection. The authorization creates the required service connection.
Select the App type, App name, and Runtime stack based on your App Service app. Your complete YAML should look similar to the following code.
variables: buildConfiguration: 'Release' steps: - task: DotNetCoreCLI@2 inputs: command: 'publish' publishWebProjects: true - task: AzureWebApp@1 inputs: azureSubscription: '<service-connection-name>' appType: 'webAppLinux' appName: '<app-name>' package: '$(System.DefaultWorkingDirectory)/**/*.zip'
- azureSubscription: Name of the authorized service connection to your Azure subscription.
- appName: Name of your existing app.
- package: File path to the package or a folder containing your app service contents. Wildcards are supported.
To deploy a .zip web package (for example, from an ASP.NET web app) to an Azure Web App, use the following snippet to deploy the build to an app.
variables:
buildConfiguration: 'Release'
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: true
- task: AzureWebApp@1
inputs:
azureSubscription: '<service-connection-name>'
appType: 'webAppLinux'
appName: '<app-name>'
package: '$(System.DefaultWorkingDirectory)/**/*.zip'
- azureSubscription: your Azure subscription.
- appType: your Web App type.
- appName: the name of your existing app service.
- package: the file path to the package or a folder containing your app service contents. Wildcards are supported.
By default, your deployment happens to the root application in the Azure Web App. You can deploy to a specific virtual application by using the VirtualApplication
property of the Azure App Service deploy (AzureRmWebAppDeployment
) task:
- task: AzureRmWebAppDeployment@4
inputs:
VirtualApplication: '<name of virtual application>'
- VirtualApplication: the name of the Virtual Application that's configured in the Azure portal. For more information, see Configure an App Service app in the Azure portal .
The following example shows how to deploy to a staging slot, and then swap to a production slot:
- task: AzureWebApp@1
inputs:
azureSubscription: '<service-connection-name>'
appType: webAppLinux
appName: '<app-name>'
deployToSlotOrASE: true
resourceGroupName: '<name of resource group>'
slotName: staging
package: '$(Build.ArtifactStagingDirectory)/**/*.zip'
- task: AzureAppServiceManage@0
inputs:
azureSubscription: '<service-connection-name>'
appType: webAppLinux
WebAppName: '<app-name>'
ResourceGroupName: '<name of resource group>'
SourceSlot: staging
SwapWithProduction: true
- azureSubscription: your Azure subscription.
- appType: (optional) Use
webAppLinux
to deploy to a Web App on Linux. - appName: the name of your existing app service.
- deployToSlotOrASE: Boolean. Deploy to an existing deployment slot or Azure App Service Environment.
- resourceGroupName: Name of the resource group. Required if
deployToSlotOrASE
is true. - slotName: Name of the slot, which defaults to
production
. Required ifdeployToSlotOrASE
is true. - package: the file path to the package or a folder containing your app service contents. Wildcards are supported.
- SourceSlot: Slot sent to production when
SwapWithProduction
is true. - SwapWithProduction: Boolean. Swap the traffic of source slot with production.
You can use jobs in your YAML file to set up a pipeline of deployments. By using jobs, you can control the order of deployment to multiple web apps.
jobs:
- job: buildandtest
pool:
vmImage: ubuntu-latest
steps:
# publish an artifact called drop
- task: PublishPipelineArtifact@1
inputs:
targetPath: '$(Build.ArtifactStagingDirectory)'
artifactName: drop
# deploy to Azure Web App staging
- task: AzureWebApp@1
inputs:
azureSubscription: '<service-connection-name>'
appType: <app type>
appName: '<staging-app-name>'
deployToSlotOrASE: true
resourceGroupName: <group-name>
slotName: 'staging'
package: '$(Build.ArtifactStagingDirectory)/**/*.zip'
- job: deploy
dependsOn: buildandtest
condition: succeeded()
pool:
vmImage: ubuntu-latest
steps:
# download the artifact drop from the previous job
- task: DownloadPipelineArtifact@2
inputs:
source: 'current'
artifact: 'drop'
path: '$(Pipeline.Workspace)'
- task: AzureWebApp@1
inputs:
azureSubscription: '<service-connection-name>'
appType: <app type>
appName: '<production-app-name>'
resourceGroupName: <group-name>
package: '$(Pipeline.Workspace)/**/*.zip'
For most language stacks, app settings and connection strings can be set as environment variables at runtime.
But there are other reasons you would want to make variable substitutions to your Web.config. In this example, your Web.config file contains a connection string named connectionString
. You can change its value before deploying to each web app. You can do this either by applying a Web.config transformation or by substituting variables in your Web.config file.
The following snippet shows an example of variable substitution by using the Azure App Service Deploy (AzureRmWebAppDeployment
) task:
jobs:
- job: test
variables:
connectionString: <test-stage connection string>
steps:
- task: AzureRmWebAppDeployment@4
inputs:
azureSubscription: '<Test stage Azure service connection>'
WebAppName: '<name of test stage web app>'
enableXmlVariableSubstitution: true
- job: prod
dependsOn: test
variables:
connectionString: <prod-stage connection string>
steps:
- task: AzureRmWebAppDeployment@4
inputs:
azureSubscription: '<Prod stage Azure service connection>'
WebAppName: '<name of prod stage web app>'
enableXmlVariableSubstitution: true
To do this in YAML, you can use one of the following techniques:
- Isolate the deployment steps into a separate job, and add a condition to that job.
- Add a condition to the step.
The following example shows how to use step conditions to deploy only builds that originate from the main branch:
- task: AzureWebApp@1
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
inputs:
azureSubscription: '<service-connection-name>'
appName: '<app-name>'
To learn more about conditions, see Specify conditions.
The Azure App Service deploy (AzureRmWebAppDeployment
) task can deploy to App Service using Web Deploy.
trigger:
- main
pool:
vmImage: windows-latest
variables:
buildConfiguration: 'Release'
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: true
arguments: '--configuration $(buildConfiguration)'
zipAfterPublish: true
- task: AzureRmWebAppDeployment@4
inputs:
ConnectionType: 'AzureRM'
azureSubscription: '<service-connection-name>'
appType: 'webApp'
WebAppName: '<app-name>'
packageForLinux: '$(System.DefaultWorkingDirectory)/**/*.zip'
enableCustomDeployment: true
DeploymentType: 'webDeploy'
The Azure Web App task (AzureWebApp
) is the simplest way to deploy to an Azure Web App. By default, your deployment happens to the root application in the Azure Web App.
The Azure App Service Deploy task (AzureRmWebAppDeployment
) can handle more custom scenarios, such as:
- Modify configuration settings inside web packages and XML parameters files.
- Deploy with Web Deploy, if you're used to the IIS deployment process.
- Deploy to virtual applications.
- Deploy to other app types, like Container apps, Function apps, WebJobs, or API and Mobile apps.
Note
File transforms and variable substitution are also supported by the separate File Transform task for use in Azure Pipelines. You can use the File Transform task to apply file transformations and variable substitutions on any configuration and parameters files.
In YAML pipelines, depending on your pipeline, there may be a mismatch between where your built web package is saved and where the deploy task is looking for it. For example, the AzureWebApp
task picks up the web package for deployment. For example, the AzureWebApp task looks in $(System.DefaultWorkingDirectory)/**/*.zip
. If the web package is deposited elsewhere, modify the value of package
.
This error occurs in the AzureRmWebAppDeployment task when you configure the task to deploy using Web Deploy, but your agent isn't running Windows. Verify that your YAML has something similar to the following code:
pool:
vmImage: windows-latest
For troubleshooting information on getting Microsoft Entra ID authentication to work with the AzureRmWebAppDeployment
task, see I can't Web Deploy to my Azure App Service using Microsoft Entra ID authentication from my Windows agent
- Customize your Azure DevOps pipeline.