Search code examples
azureazure-webjobsazure-deploymentazure-webjobs-continuous

How do I get Azure Kudu/Bitbucket deploy to deploy a .NET Core console app as a webjob?


Having read the advice here: https://learn.microsoft.com/en-gb/azure/app-service/webjobs-dotnet-deploy-vs#deploy-to-azure-app-service I don't feel significantly further towards a solution for deploying a .net core console app as a webjob via bitbucket/source control link because that article only talks about "how to deploy a .net core app using Visual Studio's Publish To Azure" and "how to set up a .Net standard app for deployment [via bit bucket/source control integration] Via Azure kudu" - my situation seems half way between these two?

How do I configure my solution, which contains a web app (deploys fine and works) and a console app (builds locally, isn't built on Azure) that I want to run as a web job?

Currently when I examine the build logs on Azure it looks like kudu doesn't even bother building the csproj even though the local build process seems to build it:

Command: "D:\home\site\deployments\tools\deploy.cmd"
Handling ASP.NET Core Web Application deployment.
  Restore completed in 803.97 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.DIExtension\ChatRoom.BL.DIExtension.csproj.
  Restore completed in 118.75 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.Interfaces\ChatRoom.BL.Interfaces.csproj.
  Restore completed in 111.72 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.Services\ChatRoom.BL.Services.csproj.
  Restore completed in 460.41 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.SignalR\ChatRoom.SignalR.csproj.
  Restore completed in 98.55 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.ViewModels\ChatRoom.BL.ViewModels.csproj.
  Restore completed in 137.75 ms for D:\home\site\repository\ChatRoom\ChatRoom.Cache\ChatRoom.Cache.csproj.
  Restore completed in 91.49 ms for D:\home\site\repository\ChatRoom\ChatRoom.Common\ChatRoom.Common.csproj.
  Restore completed in 126.71 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.DIExtension\ChatRoom.DL.DIExtension.csproj.
  Restore completed in 92.71 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.Entities\ChatRoom.DL.Entities.csproj.
  Restore completed in 97.46 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.Interfaces\ChatRoom.DL.Interfaces.csproj.
  Restore completed in 153.15 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.Repositories\ChatRoom.DL.Repositories.csproj.
  Restore completed in 109.98 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.UnitOfWork\ChatRoom.DL.UnitOfWork.csproj.
  Restore completed in 12.85 ms for D:\home\site\repository\ChatRoom\ChatRoom.Localization\ChatRoom.Localization.csproj.
  Restore completed in 76.23 ms for D:\home\site\repository\ChatRoom\ChatRoom.MessageBroker\ChatRoom.MessageBroker.csproj.
  Restore completed in 215.29 ms for D:\home\site\repository\ChatRoom\ChatRoom.Replication\ChatRoom.Replication.csproj.
  Restore completed in 189.31 ms for D:\home\site\repository\ChatRoom\ChatRoom.DrawingGenerator.Consumer\ChatRoom.DrawingGenerator.Consumer.csproj.
  Restore completed in 1.2 sec for D:\home\site\repository\ChatRoom\ChatRoom\ChatRoom.csproj.
  Restore completed in 592.52 ms for D:\home\site\repository\ChatRoom\ChatRoom\ChatRoom.csproj.
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Restore completed in 2.62 sec for D:\home\site\repository\ChatRoom\ChatRoom.BL.DIExtension\ChatRoom.BL.DIExtension.csproj.
  Restore completed in 195.02 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.Interfaces\ChatRoom.BL.Interfaces.csproj.
  Restore completed in 108.83 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.Services\ChatRoom.BL.Services.csproj.
  Restore completed in 359.89 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.SignalR\ChatRoom.SignalR.csproj.
  Restore completed in 97.73 ms for D:\home\site\repository\ChatRoom\ChatRoom.BL.ViewModels\ChatRoom.BL.ViewModels.csproj.
  Restore completed in 103.01 ms for D:\home\site\repository\ChatRoom\ChatRoom.Cache\ChatRoom.Cache.csproj.
  Restore completed in 83.57 ms for D:\home\site\repository\ChatRoom\ChatRoom.Common\ChatRoom.Common.csproj.
  Restore completed in 161.88 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.DIExtension\ChatRoom.DL.DIExtension.csproj.
  Restore completed in 91.2 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.Entities\ChatRoom.DL.Entities.csproj.
  Restore completed in 89.98 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.Interfaces\ChatRoom.DL.Interfaces.csproj.
  Restore completed in 108.06 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.Repositories\ChatRoom.DL.Repositories.csproj.
  Restore completed in 111.54 ms for D:\home\site\repository\ChatRoom\ChatRoom.DL.UnitOfWork\ChatRoom.DL.UnitOfWork.csproj.
  Restore completed in 7.71 ms for D:\home\site\repository\ChatRoom\ChatRoom.Localization\ChatRoom.Localization.csproj.
  Restore completed in 82.28 ms for D:\home\site\repository\ChatRoom\ChatRoom.MessageBroker\ChatRoom.MessageBroker.csproj.
  Restore completed in 178.2 ms for D:\home\site\repository\ChatRoom\ChatRoom.Replication\ChatRoom.Replication.csproj.
  Restore completed in 834.91 ms for D:\home\site\repository\ChatRoom\ChatRoom\ChatRoom.csproj.
  Restore completed in 328.17 ms for D:\home\site\repository\ChatRoom\ChatRoom\ChatRoom.csproj.
  ChatRoom.Cache -> D:\home\site\repository\ChatRoom\ChatRoom.Cache\bin\Release\netcoreapp2.2\ChatRoom.Cache.dll
  ChatRoom.Common -> D:\home\site\repository\ChatRoom\ChatRoom.Common\bin\Release\netcoreapp2.2\ChatRoom.Common.dll
  ChatRoom.DL.Entities -> D:\home\site\repository\ChatRoom\ChatRoom.DL.Entities\bin\Release\netcoreapp2.2\ChatRoom.DL.Entities.dll
  ChatRoom.MessageBroker -> D:\home\site\repository\ChatRoom\ChatRoom.MessageBroker\bin\Release\netcoreapp2.2\ChatRoom.MessageBroker.dll
  ChatRoom.BL.ViewModels -> D:\home\site\repository\ChatRoom\ChatRoom.BL.ViewModels\bin\Release\netcoreapp2.2\ChatRoom.BL.ViewModels.dll
  ChatRoom.BL.Interfaces -> D:\home\site\repository\ChatRoom\ChatRoom.BL.Interfaces\bin\Release\netcoreapp2.2\ChatRoom.BL.Interfaces.dll
  ChatRoom.DL.Interfaces -> D:\home\site\repository\ChatRoom\ChatRoom.DL.Interfaces\bin\Release\netcoreapp2.2\ChatRoom.DL.Interfaces.dll
  ChatRoom.DL.Repositories -> D:\home\site\repository\ChatRoom\ChatRoom.DL.Repositories\bin\Release\netcoreapp2.2\ChatRoom.DL.Repositories.dll
  ChatRoom.Localization -> D:\home\site\repository\ChatRoom\ChatRoom.Localization\bin\Release\netstandard2.0\ChatRoom.Localization.dll
  ChatRoom.Replication -> D:\home\site\repository\ChatRoom\ChatRoom.Replication\bin\Release\netcoreapp2.2\ChatRoom.Replication.dll
  ChatRoom.BL.Services -> D:\home\site\repository\ChatRoom\ChatRoom.BL.Services\bin\Release\netcoreapp2.2\ChatRoom.BL.Services.dll
  ChatRoom.BL.DIExtension -> D:\home\site\repository\ChatRoom\ChatRoom.BL.DIExtension\bin\Release\netcoreapp2.2\ChatRoom.BL.DIExtension.dll
  ChatRoom.SignalR -> D:\home\site\repository\ChatRoom\ChatRoom.BL.SignalR\bin\Release\netcoreapp2.2\ChatRoom.SignalR.dll
  ChatRoom.DL.UnitOfWork -> D:\home\site\repository\ChatRoom\ChatRoom.DL.UnitOfWork\bin\Release\netcoreapp2.2\ChatRoom.DL.UnitOfWork.dll
  ChatRoom.DL.DIExtension -> D:\home\site\repository\ChatRoom\ChatRoom.DL.DIExtension\bin\Release\netcoreapp2.2\ChatRoom.DL.DIExtension.dll
  ChatRoom -> D:\home\site\repository\ChatRoom\ChatRoom\bin\Release\netcoreapp2.2\ChatRoom.dll
  ChatRoom -> D:\local\Temp\8d74117af5751d5\
Creating app_offline.htm
KuduSync.NET from: 'D:\local\Temp\8d74117af5751d5' to: 'D:\home\site\wwwroot'
Copying file: 'ChatRoom.BL.DIExtension.dll'
Copying file: 'ChatRoom.BL.DIExtension.pdb'
Copying file: 'ChatRoom.BL.Interfaces.dll'
Copying file: 'ChatRoom.BL.Interfaces.pdb'
Copying file: 'ChatRoom.BL.Services.dll'
Copying file: 'ChatRoom.BL.Services.pdb'
Copying file: 'ChatRoom.BL.ViewModels.dll'
Copying file: 'ChatRoom.BL.ViewModels.pdb'
Copying file: 'ChatRoom.Cache.dll'
Copying file: 'ChatRoom.Cache.pdb'
Copying file: 'ChatRoom.Common.dll'
Copying file: 'ChatRoom.Common.pdb'
Copying file: 'ChatRoom.deps.json'
Copying file: 'ChatRoom.DL.DIExtension.dll'
Copying file: 'ChatRoom.DL.DIExtension.pdb'
Copying file: 'ChatRoom.DL.Entities.dll'
Copying file: 'ChatRoom.DL.Entities.pdb'
Copying file: 'ChatRoom.DL.Interfaces.dll'
Copying file: 'ChatRoom.DL.Interfaces.pdb'
Copying file: 'ChatRoom.DL.Repositories.dll'
Copying file: 'ChatRoom.DL.Repositories.pdb'
Copying file: 'ChatRoom.DL.UnitOfWork.dll'
Copying file: 'ChatRoom.DL.UnitOfWork.pdb'
Copying file: 'ChatRoom.dll'
Copying file: 'ChatRoom.Localization.dll'
Copying file: 'ChatRoom.Localization.pdb'
Copying file: 'ChatRoom.MessageBroker.dll'
Copying file: 'ChatRoom.MessageBroker.pdb'
Copying file: 'ChatRoom.pdb'
Copying file: 'ChatRoom.Replication.dll'
Copying file: 'ChatRoom.Replication.pdb'
Copying file: 'ChatRoom.runtimeconfig.json'
Copying file: 'ChatRoom.SignalR.dll'
Copying file: 'ChatRoom.SignalR.pdb'
Copying file: 'ar-AE\ChatRoom.Localization.resources.dll'
Copying file: 'de-DE\ChatRoom.Localization.resources.dll'
Copying file: 'ru-Ru\ChatRoom.Localization.resources.dll'
Deleting app_offline.htm
Finished successfully.

It clones the app that is to be the webjob and restore nuget packages for it:

    Restore completed in 189.31 ms for 
D:\home\site\repository\ChatRoom\ChatRoom.DrawingGenerator.Consumer\ChatRoom.DrawingGenerator.Consumer.csproj

But then it's never mentioned again and no binaries for this project are evident on the azure service..

I was hoping that I could configure them to output to the set of folders that are by-convention turned into web jobs


Solution

  • How do I configure my solution, which contains a web app (deploys fine and works) and a console app (builds locally, isn't built on Azure) that I want to run as a web job?

    I added a post build event to the project that Azure WAS building, of the form:

    dotnet publish "%25DEPLOYMENT_SOURCE%25\MySolutionName\MyWebJobProject\MyWebJobProject.csproj" --output "%25DEPLOYMENT_TEMP%25\app_data\jobs\continuous\mywebjob" --configuration Release
    

    The %25 are necessary-> they decode to % when the csproj XML is read meaning that %DEPLOYMENT_SOURCE% is passed to the command line. If you put %DEPLOYMENT_SOURCE% straight into the Post Build Event GUI in VS, the %DE will be decoded as 0xDE, whatever char that is, and you'll see errors in the log with a substitution character �

    • %DEPLOYMENT_SOURCE% is probably D:\home\site\repository. Files seem to build in this root, then publish as DLLs to the temp location:
    • %DEPLOYMENT_TEMP% is something like D:\local\temp\abcdef1234. After DLLs are moved here as a publish step, KuduSync.Net.exe runs and mirrors them back
    • KuduSync.Net.exe is essentially a mirroring tool; it deletes files and directories from your live site that were deployed last time but aren't deployed this time, and it adds new files deployed this time that weren't deployed last time. It doesn't touch files that haven't changed. In this way if your site creates its own files (i.e. not part of a deployment) then they won't be trashed
    • Once your webjob project is published to the %DEPLOYMENT_TEMP% location, in the app_data\jobs\continuous\somename subfolder, KuduSync will sync it back to the live site files hierarchy and it will appear inn the webjobs dashboard

    Which just leaves a couple of lines on how to get a dotnet console app to run as a webjob. The simplest route seems to be:

    • Add a file called run.bat to your project, set its Build Action to Content and Copy to Output Folder to Copy Always
    • Inside the file put dotnet NameOfYourCoreApp.dll

    Save the file with plain ASCII encoding, not UTF8, or the Byte Order Mark will form part of the first line of command and your app won't run


    Remember that webjobs can be different types of trigger; edit the word "continuous" appropriately

    Currently when I examine the build logs on Azure it looks like kudu doesn't even bother building the csproj

    If the csproj that azure IS building doesn't depend on it, then it wont build it. This doesn't matter, because the post build event on the project that IS building, builds the one that isn't building.