Configure CI/CD with Azure Pipelines - Azure App Service (2024)

  • Article

Azure DevOps Services | Azure DevOps Server 2020 | Azure DevOps Server 2019

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).

Prerequisites

  • 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.
    • .NET: Create an ASP.NET Core web app in Azure
    • ASP.NET: Create an ASP.NET Framework web app in Azure
    • JavaScript: Create a Node.js web app in Azure App Service
    • Java: Create a Java app on Azure App Service
    • Python: Create a Python app in Azure App Service

1. Create a pipeline for your stack

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.

  • YAML
  • Classic
  1. Sign in to your Azure DevOps organization and navigate to your project.

  2. Go to Pipelines, and then select New Pipeline.

  3. 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.

  4. When the list of repositories appears, select your repository.

  5. You might be redirected to GitHub to install the Azure Pipelines app. If so, select Approve & install.

  6. When the Configure tab appears, select ASP.NET Core.

  7. When your new pipeline appears, take a look at the YAML to see what it does. When you're ready, select Save and run.

2. Add the deployment task

  • YAML
  • Classic
  1. Click the end of the YAML file, then select Show assistant.'

  2. Use the Task assistant to add the Azure Web App task.

    Configure CI/CD with Azure Pipelines - Azure App Service (1)

    Alternatively, you can add the Azure App Service deploy (AzureRmWebAppDeployment) task.

  3. Choose your Azure subscription. Make sure to Authorize your connection. The authorization creates the required service connection.

  4. 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:- script: dotnet build --configuration $(buildConfiguration) displayName: 'dotnet build $(buildConfiguration)'- 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.

Example: Deploy a .NET app

  • YAML
  • Classic

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:- script: dotnet build --configuration $(buildConfiguration) displayName: 'dotnet build $(buildConfiguration)'- 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.

Example: deploy to a virtual application

  • YAML
  • Classic

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.

Example: Deploy to a slot

  • YAML
  • Classic

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 if deployToSlotOrASE 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.

Example: Deploy to multiple web apps

  • YAML
  • Classic

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'

Example: Make variable substitutions

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.

  • YAML
  • Classic

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

Example: Deploy conditionally

  • YAML
  • Classic

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.

Example: deploy using Web Deploy

The Azure App Service deploy (AzureRmWebAppDeployment) task can deploy to App Service using Web Deploy.

  • YAML
  • Classic
trigger:- mainpool: vmImage: windows-latestvariables: buildConfiguration: 'Release'steps:- script: dotnet build --configuration $(buildConfiguration) displayName: 'dotnet build $(buildConfiguration)'- 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'

Frequently asked questions

What's the difference between the AzureWebApp and AzureRmWebAppDeployment tasks?

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.

I get the message "Invalid App Service package or folder path provided."

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.

I get the message "Publish using webdeploy options are supported only when using Windows agent."

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

Web Deploy doesn't work when I disable basic authentication

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

Next steps

  • Customize your Azure DevOps pipeline.
Configure CI/CD with Azure Pipelines - Azure App Service (2024)
Top Articles
Latest Posts
Article information

Author: Duncan Muller

Last Updated:

Views: 5679

Rating: 4.9 / 5 (79 voted)

Reviews: 86% of readers found this page helpful

Author information

Name: Duncan Muller

Birthday: 1997-01-13

Address: Apt. 505 914 Phillip Crossroad, O'Konborough, NV 62411

Phone: +8555305800947

Job: Construction Agent

Hobby: Shopping, Table tennis, Snowboarding, Rafting, Motor sports, Homebrewing, Taxidermy

Introduction: My name is Duncan Muller, I am a enchanting, good, gentle, modern, tasty, nice, elegant person who loves writing and wants to share my knowledge and understanding with you.