I used to take both gravity and Continuous Deployment to Azure App Service for granted. This has wasted a lot of time executing manual tasks upon deployment. Sometimes you just need to execute several commands in addition to the default behavior. You probably don't really need to create a whole Azure DevOps(former VSTS) release pipeline for such a small job.

What is Kudu?

This is the backbone of Azure App Service. Kudu SCM is a hidden gem which is typically accessed via https://your-site-name.scm.azurewebsites.net(Multi-tenant environments) or https://your-site-name.scm.your-app-service-environment.p.azurewebsites.net(App Service Environment).

Custom Deployment script

I've used the built-in deployment from git for a long time now. You git push and then it takes care for your deployment. It will automatically decide what kind of site you are deploying and what should be done depending on it.
So for example, if you are deploying an ASP.NET MVC web app it will go ahead and MSBuild it into an artifacts folder, and then it will deploy only the files that changed to wwwroot. But that's what you get out of the box.

You may want to execute some custom tasks as part of the deployment and before flagging it as successful. For example, you may want to execute some tests or run database migration scripts. Custom deployment script is the thing that helped me fully automate the deployment of Ghost on Azure App Service.

How to write a custom deployment script?

You should better start with one of the default scripts and customize from there on:

  1. Install Node.js
  2. Install the KuduScript package:
    npm install kuduscript -g
  3. Go to the root of your repo
  4. Run kuduscript --help
    kuduscript --help
  5. Pick and choose whatever is appropriate for your solution

As you can see this tool support variety of platforms - ASP.NET, ASP.NET Core, Go, Node.js, Ruby, PHP, Python, Azure Function Apps, .NET console apps.
Let's create a custom deployment script for an ASP.NET MVC:

kuduscript -y --aspWAP Example.Web\Example.Web.csproj -s Example.sln

This thing will create the following files for you:

  • .deployment - a file pointing to which command to run for deployment
  • deploy.cmd - the actual deployment script

You can choose between Batch, Bash or PoSh by specifying the --scriptType argument.

The right place to insert your custom commands in deploy.cmd is somewhere between those lines:

:: Deployment
:: ----------


You also have some environment variables at your disposal:

  • DEPLOYMENT_SOURCE - The path for the root of your repository (In Azure).
  • DEPLOYMENT_TARGET - The wwwroot path (the deployment destination directory).
  • DEPLOYMENT_TEMP - Path to a temporary directory that will be removed after the deployment.
  • MSBUILD_PATH - Path to msbuild executable.

After including your own logic to the deployment script you can test it locally to make sure it runs as expected. You'll find the files published to a sub-directory called artifacts. Make sure to exclude it from being added to your repository.
And finally, add the generated files to your repository(.deployment and deploy.cmd) and push.

More info on customizing deployments: https://github.com/projectkudu/kudu/wiki/Customizing-deployments

Monitoring deployments

The first option is to use App Service > Deployment center

App Service > Deployment center

The other option is to use Kudu SCM itself where you can find more logs, https://your-site-name.scm.azurewebsites.net/ZipDeploy

Kudu SCM Deployments

See comparison between VSTS(Azure DevOps) and Kudu deployments: https://github.com/projectkudu/kudu/wiki/VSTS-vs-Kudu-deployments