Specifying MSBuild version for Azure App Service build

364 Views Asked by At

I am trying to deploy two web apps from the same Git repo to two different Azure App Service apps. I am using the Deployment Console in each App Service app to build and deploy the apps. To select which app to deploy to which App Service app, I am specifying an application setting inside the Azure portal for each app, called PROJECT. which then points to the csproj for the app to build and deploy. This works fine!

However, my problem then lies in telling the build service to use the newest version of MSBuild. It defaults to v. 14, which does not work with the SDK style csproj files. I tried setting another application setting called MSBUILD_PATH to %MSBUILD_1670_DIR%\MSBuild.exe, but the deploy script Kudu generates only uses the MSBUILD_PATH for the build step, and not the NuGet restore step, so it still fails, with the output:

Command: "D:\home\site\deployments\tools\deploy.cmd"
Using custom deployment setting for MSBUILD_PATH custom value is '%MSBUILD_1670_DIR%\MSBuild.exe'.
Handling .NET Web Application deployment.
MSBuild auto-detection: using msbuild version '14.0.23107.0 built by: D14REL' from 'D:\Program Files (x86)\MSBuild\14.0\Bin'.
Invalid restore input. Missing required property 'OutputPath' for project type 'PackageReference'. Input files: D:\home\site\repository\ProReception.UnitTest\ProReception.UnitTest.csproj.
Failed exitCode=1, command=nuget restore "D:\home\site\repository\ProReception.sln"
An error has occurred during web site deployment.
Invalid restore input. Missing required property 'OutputPath' for project type 'PackageReference'. Input files: D:\home\site\repository\ProReception.UnitTest\ProReception.UnitTest.csproj.\r\nD:\Program Files (x86)\SiteExtensions\Kudu\98.40824.5897\bin\Scripts\starter.cmd "D:\home\site\deployments\tools\deploy.cmd"

The template for the build script is this one: https://github.com/projectkudu/KuduScript/blob/master/lib/templates/deploy.batch.aspnet.wap.template#L10 - and the NuGet restore command does not specify the -MSBuildPath.

So, the suggested fix is to add your own deploy.cmd script to your repo, but how do I do that without hardcoding the project to build? (since I have two projects).

To make this even more difficult: One of the web apps is an old ASP.NET MVC site running on .NET 4.7.1, and the other is a newer ASP.NET Core site running on .NET 6. So ideally they need different deploy scripts.

How can I use different deploy scripts for each app?

1

There are 1 best solutions below

0
Søren Pedersen On

OK, I came up with a temporary solution and created a deploy.cmd script that is able to deploy either app. It looks at the PROJECT environment variable, to determine which app to deploy.

Here is the complete script, in case it helps someone else:

@if "%SCM_TRACE_LEVEL%" NEQ "4" @echo off

:: ----------------------
:: KUDU Deployment Script
:: Version: 1.0.17
:: ----------------------

:: Prerequisites
:: -------------

:: Verify node.js installed
where node 2>nul >nul
IF %ERRORLEVEL% NEQ 0 (
  echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
  goto error
)

:: Setup
:: -----

setlocal enabledelayedexpansion

SET ARTIFACTS=%~dp0%..\artifacts

IF NOT DEFINED DEPLOYMENT_SOURCE (
  SET DEPLOYMENT_SOURCE=%~dp0%.
)

IF NOT DEFINED DEPLOYMENT_TARGET (
  SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
)

IF NOT DEFINED NEXT_MANIFEST_PATH (
  SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest

  IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
    SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
  )
)

IF NOT DEFINED KUDU_SYNC_CMD (
  :: Install kudu sync
  echo Installing Kudu Sync
  call npm install kudusync -g --silent
  IF !ERRORLEVEL! NEQ 0 goto error

  :: Locally just running "kuduSync" would also work
  SET KUDU_SYNC_CMD=%appdata%\npm\kuduSync.cmd
)
IF NOT DEFINED DEPLOYMENT_TEMP (
  SET DEPLOYMENT_TEMP=%temp%\___deployTemp%random%
  SET CLEAN_LOCAL_DEPLOYMENT_TEMP=true
)

IF DEFINED CLEAN_LOCAL_DEPLOYMENT_TEMP (
  IF EXIST "%DEPLOYMENT_TEMP%" rd /s /q "%DEPLOYMENT_TEMP%"
  mkdir "%DEPLOYMENT_TEMP%"
)

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

IF /I "%PROJECT%" EQU "ProReception/ProReception.csproj" (
  call :DeployMvc
  goto end
)

IF /I "%PROJECT%" EQU "ProReception.Api/ProReception.Api.csproj" (
  call :DeployApi
  goto end
)

echo Did not match any of the configured apps :( - please review the deploy.cmd script in the root of the repo to add '%PROJECT%' there.
goto error

:DeployMvc
echo Handling .NET Web Application deployment.

:: 1. Restore NuGet packages
IF /I "ProReception.sln" NEQ "" (
  call :ExecuteCmd nuget restore "%DEPLOYMENT_SOURCE%\ProReception.sln" -MSBuildPath "%MSBUILD_1670_DIR%"
  IF !ERRORLEVEL! NEQ 0 goto error
)

:: 2. Build to the temporary path
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
  call :ExecuteCmd "%MSBUILD_1670_DIR%\MSBuild.exe" "%DEPLOYMENT_SOURCE%\ProReception\ProReception.csproj" /nologo /verbosity:m /t:Build /t:pipelinePreDeployCopyAllFilesToOneFolder /p:_PackageTempDir="%DEPLOYMENT_TEMP%";AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release;UseSharedCompilation=false /p:SolutionDir="%DEPLOYMENT_SOURCE%\.\\" %SCM_BUILD_ARGS%
) ELSE (
  call :ExecuteCmd "%MSBUILD_1670_DIR%\MSBuild.exe" "%DEPLOYMENT_SOURCE%\ProReception\ProReception.csproj" /nologo /verbosity:m /t:Build /p:AutoParameterizationWebConfigConnectionStrings=false;Configuration=Release;UseSharedCompilation=false /p:SolutionDir="%DEPLOYMENT_SOURCE%\.\\" %SCM_BUILD_ARGS%
)

IF !ERRORLEVEL! NEQ 0 goto error

:: 3. KuduSync
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
  call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
  IF !ERRORLEVEL! NEQ 0 goto error
)

:DeployApi
echo Handling ASP.NET Core Web Application deployment.

:: 1. Restore, Build and publish
call :ExecuteCmd "%MSBUILD_1670_DIR%\MSBuild.exe" /restore "%DEPLOYMENT_SOURCE%\ProReception.Api\ProReception.Api.csproj" /p:DeployOnBuild=true /p:configuration=Release /p:publishurl="%DEPLOYMENT_TEMP%" %SCM_BUILD_ARGS%
IF !ERRORLEVEL! NEQ 0 goto error

:: 2. KuduSync
call :ExecuteCmd "%KUDU_SYNC_CMD%" -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: Execute command routine that will echo out when error
:ExecuteCmd
setlocal
set _CMD_=%*
call %_CMD_%
if "%ERRORLEVEL%" NEQ "0" echo Failed exitCode=%ERRORLEVEL%, command=%_CMD_%
exit /b %ERRORLEVEL%

:error
endlocal
echo An error has occurred during web site deployment.
call :exitSetErrorLevel
call :exitFromFunction 2>nul

:exitSetErrorLevel
exit /b 1

:exitFromFunction
()

:end
endlocal
echo Finished successfully.