I am working with Azure and a C# based application. I have 2 App Services, a web app, and a function app. My web app use dotnet 9.0, and my function app uses dotnet 9.0 too. I selected a timer-trigger with an isolated worker, and have used the Consumption based plan. Additionally, my Web App has 4 deployment slots: development, uat, staging, production. My Function app has 2 deployment slots: development, production.
I split my Web App into 2 projects, a Web App and a Shared Library. My migrations, dbcontext, models, and the function to be referenced and run in the Azure Function, are all in the Shared Library. The 3rd project is my Azure function. All of these are stored in a single repo in Azure DevOps. When I run the below pipeline script, everything works perfectly and passes. However, it appears that the pipeline does not correctly build or deploy the Azure function.
When I load the Kudu console, I see that a zipped folder is uploaded to the ~/wwwroot dir. However, the name of this zipped folder is the webapp project zipped, and not the azure function project zipped. How can I fix this? My azure-pipelines.yml is below.
Edit 2: Updated .yml to the actual version being used.
trigger:
branches:
include:
- development-cs
- main
- uat
variables:
buildConfiguration: 'Release'
azureSubscription: 'RandomAzureConnection' # Name of your Azure Service Connection
appName: 'RandomWebApp' # Name of your Azure Web App
functionAppName: 'RandomFunctionApp' # Name of your Azure Function App
resourceGroupName: 'Random_ResourceGroup' # Name of your Resource Group
sqlServerName: 'randomsqlserver.database.windows.net' # Azure SQL Server FQDN
runtimeStack: 'DOTNETCORE|9.0'
ResourceGroupLocation: 'East US'
# Database names
devSqlDatabaseName: 'randomdevdb'
uatSqlDatabaseName: 'randomuatdb'
mainSqlDatabaseName: 'RandomMainDB'
# Deployment Slots for Web App
devSlotName: 'devSlot'
uatSlotName: 'uatSlot'
stagingSlotName: 'stagingSlot'
productionSlotName: 'productionSlot'
stages:
- stage: BuildAndDeploy
displayName: 'Build and Deploy Stage'
jobs:
- job: Build
displayName: 'Build Job'
pool:
vmImage: 'ubuntu-latest'
steps:
# Checkout code and set up environment
- checkout: self
fetchDepth: 0
persistCredentials: true
clean: true
- script: |
echo "Build Sources Directory: $(Build.SourcesDirectory)"
displayName: 'Print Build Sources Directory'
- script: |
echo '{ "sdk": { "version": "9.0.100" } }' > global.json
displayName: 'Create global.json'
- task: UseDotNet@2
displayName: 'Install .NET 9.0.100 SDK in Build Job'
inputs:
packageType: 'sdk'
version: '9.0.100'
- script: |
echo "Installing necessary tools..."
sudo apt-get update
sudo apt-get install -y azure-cli powershell
displayName: 'Install Azure CLI and PowerShell'
- script: |
echo "Installing dotnet-ef tool..."
dotnet tool install --global dotnet-ef --version 9.0.0-preview.6.24327.4
echo '##vso[task.prependpath]$HOME/.dotnet/tools'
displayName: 'Install dotnet-ef Tool in Build Job'
# Restore and Build all projects
- task: DotNetCoreCLI@2
displayName: 'Restore NuGet Packages'
inputs:
command: 'restore'
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'Build Projects'
inputs:
command: 'build'
projects: '**/*.csproj'
arguments: '--configuration $(buildConfiguration) --no-restore'
# Publish the Web App package
- task: DotNetCoreCLI@2
displayName: 'Publish Web App'
inputs:
command: 'publish'
projects: 'RandomApp/WebApp.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/web --no-restore'
# Publish the Function App package into its own folder
- task: DotNetCoreCLI@2
displayName: 'Publish Function App'
inputs:
command: 'publish'
projects: 'RandomApp/RandomFunctions.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/functions --no-restore'
# Archive the Function App folder into a zip file
- task: ArchiveFiles@2
displayName: 'Archive Function App Package'
inputs:
rootFolderOrFile: '$(Build.ArtifactStagingDirectory)/functions'
includeRootFolder: false
archiveFile: '$(Build.ArtifactStagingDirectory)/functionapp.zip'
replaceExistingArchive: true
# (Optional) Cleanup the unzipped Function App folder so only the zip remains
- script: |
echo "Cleaning up unzipped Function App folder..."
rm -rf "$(Build.ArtifactStagingDirectory)/functions"
displayName: 'Cleanup Function App Folder'
# (Optional) Generate EF Core migration SQL script
- script: |
echo "Generating EF Core migration script..."
dotnet ef migrations script --idempotent \
--project "RandomApp/RandomShared.csproj" \
--startup-project "RandomApp/WebApp.csproj" \
--output $(Build.ArtifactStagingDirectory)/migration.sql
displayName: 'Generate EF Core Migration Script'
# List files for debugging purposes
- script: |
echo "Listing contents of the Artifact Staging Directory:"
ls -la "$(Build.ArtifactStagingDirectory)"
displayName: 'List Artifact Files'
# Publish build artifacts (both the web folder and the Function App zip)
- task: PublishBuildArtifacts@1
displayName: 'Publish Build Artifacts'
inputs:
# Change the path to publish both the web folder and the functionapp.zip file
pathToPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'drop'
publishLocation: 'Container'
- job: Deploy
displayName: 'Deploy Job'
dependsOn: Build
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
fetchDepth: 0
persistCredentials: true
clean: true
- download: current
artifact: drop
# Install required tools in the Deploy Job
- task: UseDotNet@2
displayName: 'Install .NET 9.0.100 SDK in Deploy Job'
inputs:
packageType: 'sdk'
version: '9.0.100'
- script: |
echo "Installing Azure CLI..."
sudo apt-get update
sudo apt-get install -y azure-cli
displayName: 'Install Azure CLI'
- script: |
echo "Installing dotnet-ef tool..."
dotnet tool install --global dotnet-ef --version 9.0.0-preview.6.24327.4
echo '##vso[task.prependpath]$HOME/.dotnet/tools'
displayName: 'Install dotnet-ef Tool in Deploy Job'
- script: |
echo "Verifying dotnet-ef installation..."
dotnet ef --version
displayName: 'Verify dotnet-ef Installation in Deploy Job'
- script: |
echo "Testing connectivity to SQL Server..."
sudo apt-get install -y netcat
nc -zv $(sqlServerName) 1433
displayName: 'Test SQL Server Connectivity'
# Set slot and database variables based on branch
- script: |
branchName=$(Build.SourceBranchName)
if [ "$branchName" == "main" ]; then
echo "##vso[task.setvariable variable=slotName]$(stagingSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(mainSqlDatabaseName)"
echo "##vso[task.setvariable variable=functionSlot]''"
elif [ "$branchName" == "uat" ]; then
echo "##vso[task.setvariable variable=slotName]$(uatSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(uatSqlDatabaseName)"
echo "##vso[task.setvariable variable=functionSlot]none"
elif [ "$branchName" == "development-cs" ]; then
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
echo "##vso[task.setvariable variable=functionSlot]development"
else
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
echo "##vso[task.setvariable variable=functionSlot]development"
fi
echo "Branch: $branchName"
echo "Web App Slot Name: $(slotName)"
echo "SQL Server Name: $(sqlServerName)"
echo "SQL Database Name: $(sqlDatabaseName)"
echo "Function App Slot: $(functionSlot)"
displayName: 'Set Web App Slot, Function App Slot, and DB Based on Branch'
# Apply EF Core migrations for main and uat branches only
- script: |
echo "Applying EF Core Migrations using Service Principal..."
dotnet ef database update \
--project "RandomApp/RandomShared.csproj" \
--startup-project "RandomApp/WebApp.csproj" \
--connection "Server=tcp:$(sqlServerName),1433;Database=$(sqlDatabaseName);Authentication=Active Directory Service Principal;User ID=$(sqlClientId);Password=$(sqlClientSecret);Encrypt=True;TrustServerCertificate=False;MultipleActiveResultSets=True;Connection Timeout=30;"
displayName: 'Apply EF Core Migrations'
condition: or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], 'uat'))
# Deploy the Web App package to Azure App Service
- task: AzureWebApp@1
displayName: 'Deploy to Azure Web App'
inputs:
azureSubscription: '$(azureSubscription)'
appName: '$(appName)'
# Adjust the package path if your web app requires a zip package or folder.
package: '$(Pipeline.Workspace)/drop/web'
appType: 'webApp'
slotName: '$(slotName)'
# Update Web App settings using Azure CLI
- task: AzureCLI@2
displayName: 'Update Web App Settings'
inputs:
azureSubscription: '$(azureSubscription)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
echo "Updating Web App settings..."
az webapp config appsettings set \
--name "$(appName)" \
--resource-group "$(resourceGroupName)" \
--slot "$(slotName)" \
--settings ConnectionStrings__DefaultConnection="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" \
AzureAd__Instance="https://login.microsoftonline.com/" \
AzureAd__Domain="randomdomain.com" \
AzureAd__TenantId="$(tenantId)" \
AzureAd__ClientId="$(clientId)" \
AzureAd__ClientSecret="$(clientSecret)"
# Update Function App settings (only for main and development-cs branches)
- task: AzureCLI@2
displayName: 'Update Function App Settings'
condition: or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], 'development-cs'))
inputs:
azureSubscription: '$(azureSubscription)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
if [ "$(functionSlot)" = "development" ]; then
echo "Updating Function App settings for development slot (RandomFunctionApp/development)..."
az functionapp config appsettings set \
--name "$(functionAppName)" \
--resource-group "$(resourceGroupName)" \
--slot "development" \
--settings MyDbConnectionString="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
else
echo "Updating Function App settings for production Function App (RandomFunctionApp)..."
az functionapp config appsettings set \
--name "$(functionAppName)" \
--resource-group "$(resourceGroupName)" \
--settings MyDbConnectionString="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
fi
# Deploy the Function App package (only for main and development-cs branches)
- task: AzureFunctionApp@2
displayName: 'Deploy Function App to Azure'
condition: or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], 'development-cs'))
inputs:
connectedServiceNameARM: 'RandomAzureConnection'
appType: 'functionApp'
appName: '$(functionAppName)'
deployToSlotOrASE: true
resourceGroupName: '$(resourceGroupName)'
slotName: 'development'
package: '$(Pipeline.Workspace)/drop/functionapp.zip'
deploymentMethod: 'zipDeploy'
The script above is what I tried. Additionally, I attempted at using the Publish feature in VS Community which worked perfectly. No issues at all. It seems like the issues only occur when trying to use CI/CD with DevOps.
Edit 1: I also noticed that the web app would publish in the azure function app service, and my web app app service would no longer be published and display a page saying it is ready to be deployed to.
Edit 3: This is my current azure-pipelines.yml. The function app deploys perfectly, thank you. However, my web app no longer deploys. I tried referencing both zipped foldersin the published artifacts. I noticed that publishing them individually creates zipped folders and then publishing afterwards republishes all artifacts. Please see the code below:
trigger:
branches:
include:
- development-cs
- main
- uat
variables:
buildConfiguration: 'Release'
# Azure Service Connection
azureSubscription: 'AzureDevOpsConnection' # Name of your Azure Service Connection
# App Service Names
webAppName: 'EnvisionCRM' # Name of your Azure Web App
functionAppName: 'EnvisionCRM-Functions' # Name of your Azure Function App
resourceGroupName: 'EnvisionCRM_group' # Name of your Resource Group
# Example runtime settings - adjust as needed
runtimeStack: 'DOTNETCORE|9.0'
ResourceGroupLocation: 'East US'
# Database names
devSqlDatabaseName: 'eacdev'
uatSqlDatabaseName: 'eacuat'
mainSqlDatabaseName: 'Customer Database'
# Deployment Slots (for Web App only)
devSlotName: 'development'
uatSlotName: 'uat'
stagingSlotName: 'staging'
productionSlotName: 'production'
stages:
- stage: BuildAndDeploy
displayName: 'Build and Deploy Stage'
jobs:
# ------------------
# 1) BUILD JOB
# ------------------
- job: Build
displayName: 'Build Job'
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
fetchDepth: 0
persistCredentials: true
clean: true
- script: |
echo "Build Sources Directory: $(Build.SourcesDirectory)"
displayName: 'Print Build Sources Directory'
- script: |
echo '{ "sdk": { "version": "9.0.100" } }' > global.json
displayName: 'Create global.json'
- task: UseDotNet@2
displayName: 'Install .NET 9.0.100 SDK in Build Job'
inputs:
packageType: 'sdk'
version: '9.0.100'
- script: |
echo "Installing necessary tools..."
sudo apt-get update
sudo apt-get install -y azure-cli powershell zip
displayName: 'Install Azure CLI, PowerShell and Zip'
- script: |
echo "Installing dotnet-ef tool..."
dotnet tool install --global dotnet-ef --version 9.0.0-preview.6.24327.4
echo '##vso[task.prependpath]$HOME/.dotnet/tools'
displayName: 'Install dotnet-ef Tool in Build Job'
- task: DotNetCoreCLI@2
displayName: 'Restore NuGet Packages'
inputs:
command: 'restore'
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: 'Build Solution'
inputs:
command: 'build'
projects: '**/*.csproj'
arguments: '--configuration $(buildConfiguration) --no-restore'
# Clean output folders to avoid carry-over from previous builds
- script: |
echo "Cleaning output folders..."
rm -rf "$(Build.ArtifactStagingDirectory)/WebApp"
rm -rf "$(Build.ArtifactStagingDirectory)/Functions"
displayName: 'Clean Output Folders'
# Publish the WebApp project into its own folder
- task: DotNetCoreCLI@2
displayName: 'Publish EnvisionCRM.WebApp'
inputs:
command: 'publish'
publishWebProjects: false
projects: 'EnvisionCRM.WebApp/EnvisionCRM.WebApp.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/WebApp --no-restore'
# Publish the Functions project into its own folder
- task: DotNetCoreCLI@2
displayName: 'Publish EnvisionCRM.Functions'
inputs:
command: 'publish'
publishWebProjects: false
projects: 'EnvisionCRM.Functions/EnvisionCRM.Functions.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/Functions --no-restore'
# List contents for debugging
- script: |
echo "Listing WebApp folder contents:"
ls -R "$(Build.ArtifactStagingDirectory)/WebApp" || echo "WebApp folder is empty"
displayName: 'List WebApp Files'
- script: |
echo "Listing Functions folder contents:"
ls -R "$(Build.ArtifactStagingDirectory)/Functions" || echo "Functions folder is empty"
displayName: 'List Functions Files'
# Zip the published WebApp output from the artifact staging directory root
- script: |
rm -f "$(Build.ArtifactStagingDirectory)/EnvisionCRM.WebApp.zip"
echo "Zipping WebApp folder..."
cd "$(Build.ArtifactStagingDirectory)" && zip -r "EnvisionCRM.WebApp.zip" "WebApp"
displayName: 'Zip WebApp Files'
# Zip the published Functions output from the artifact staging directory root
- script: |
rm -f "$(Build.ArtifactStagingDirectory)/EnvisionCRM.Functions.zip"
echo "Zipping Functions folder..."
cd "$(Build.ArtifactStagingDirectory)" && zip -r "EnvisionCRM.Functions.zip" "Functions"
displayName: 'Zip Functions Files'
# (Optional) Generate EF Core migration SQL script for the WebApp
- script: |
echo "Generating EF Core migration script..."
dotnet ef migrations script --idempotent --project "EnvisionCRM.WebApp/EnvisionCRM.WebApp.csproj" --output "$(Build.ArtifactStagingDirectory)/migration.sql"
displayName: 'Generate EF Core Migration Script'
# Publish build artifacts (the zipped files and any other outputs)
- task: PublishBuildArtifacts@1
displayName: 'Publish Build Artifacts'
inputs:
pathToPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'drop'
publishLocation: 'Container'
# ------------------
# 2) DEPLOY JOB
# ------------------
- job: Deploy
displayName: 'Deploy Job'
dependsOn: Build
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
fetchDepth: 0
persistCredentials: true
clean: true
# Download the build artifacts
- download: current
artifact: drop
- task: UseDotNet@2
displayName: 'Install .NET 9.0.100 SDK in Deploy Job'
inputs:
packageType: 'sdk'
version: '9.0.100'
- script: |
echo "Installing Azure CLI..."
sudo apt-get update
sudo apt-get install -y azure-cli
displayName: 'Install Azure CLI'
- script: |
echo "Installing dotnet-ef tool..."
dotnet tool install --global dotnet-ef --version 9.0.0-preview.6.24327.4
echo '##vso[task.prependpath]$HOME/.dotnet/tools'
displayName: 'Install dotnet-ef Tool in Deploy Job'
- script: |
echo "Verifying dotnet-ef installation..."
dotnet ef --version
displayName: 'Verify dotnet-ef Installation in Deploy Job'
# Set slotName and sqlDatabaseName (used by the Web App only)
- script: |
branchName=$(Build.SourceBranchName)
if [ "$branchName" == "main" ]; then
echo "##vso[task.setvariable variable=slotName]$(stagingSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(mainSqlDatabaseName)"
elif [ "$branchName" == "uat" ]; then
echo "##vso[task.setvariable variable=slotName]$(uatSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(uatSqlDatabaseName)"
elif [ "$branchName" == "development-cs" ]; then
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
else
echo "##vso[task.setvariable variable=slotName]$(devSlotName)"
echo "##vso[task.setvariable variable=sqlDatabaseName]$(devSqlDatabaseName)"
fi
echo "Branch: $branchName"
echo "Slot Name: $(slotName)"
echo "SQL Server Name: $(sqlServerName)"
echo "SQL Database Name: $(sqlDatabaseName)"
displayName: 'Set DB and Slot Variables'
# (Optional) Apply EF Core migrations for the WebApp on main & uat branches
- script: |
echo "Applying EF Core Migrations using Service Principal..."
dotnet ef database update --connection "Server=tcp:$(sqlServerName),1433;Database=$(sqlDatabaseName);Authentication=Active Directory Service Principal;User ID=$(sqlClientId);Password=$(sqlClientSecret);Encrypt=True;TrustServerCertificate=False;MultipleActiveResultSets=True;Connection Timeout=30;"
displayName: 'Apply EF Core Migrations'
condition: or(eq(variables['Build.SourceBranchName'], 'main'), eq(variables['Build.SourceBranchName'], 'uat'))
# ---------------------------
# DEPLOY THE WEB APP
# ---------------------------
- task: AzureWebApp@1
displayName: 'Deploy to Azure Web App (EnvisionCRM)'
inputs:
azureSubscription: '$(azureSubscription)'
appName: '$(webAppName)'
deployToSlotOrASE: true
package: '$(Pipeline.Workspace)/drop/WebApp/EnvisionCRM.WebApp.zip'
appType: 'webApp'
slotName: '$(slotName)' # Use this only if your Web App uses deployment slots
- task: AzureCLI@2
displayName: 'Update Web App Settings'
inputs:
azureSubscription: '$(azureSubscription)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
echo "Updating App Service settings for Web App..."
az webapp config appsettings set \
--name "$(webAppName)" \
--resource-group "$(resourceGroupName)" \
--slot "$(slotName)" \
--settings \
ConnectionStrings__DefaultConnection="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" \
AzureAd__Instance="https://login.microsoftonline.com/" \
AzureAd__Domain="envisionafrica.co.za" \
AzureAd__TenantId="$(tenantId)" \
AzureAd__ClientId="$(clientId)" \
AzureAd__ClientSecret="$(clientSecret)"
# ---------------------------
# DEPLOY THE FUNCTION APP
# ---------------------------
- task: AzureWebApp@1
displayName: 'Deploy to Azure Function App (EnvisionCRM-Functions)'
inputs:
azureSubscription: '$(azureSubscription)'
appName: '$(functionAppName)'
package: '$(Pipeline.Workspace)/drop/Functions/EnvisionCRM.Functions.zip'
appType: 'functionApp'
slotName: '$(slotName)'
- task: AzureCLI@2
displayName: 'Update Function App Settings'
inputs:
azureSubscription: '$(azureSubscription)'
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: |
echo "Updating App Service settings for Function App..."
az functionapp config appsettings set \
--name "$(functionAppName)" \
--resource-group "$(resourceGroupName)" \
--settings \
ConnectionStrings__DefaultConnection="Server=tcp:$(sqlServerName),1433;Initial Catalog=$(sqlDatabaseName);Authentication=Active Directory Managed Identity;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;" \
AzureAd__Instance="https://login.microsoftonline.com/" \
AzureAd__Domain="envisionafrica.co.za" \
AzureAd__TenantId="$(tenantId)" \
AzureAd__ClientId="$(clientId)" \
AzureAd__ClientSecret="$(clientSecret)"
Refer to this doc: DotNetCoreCLI@2 - .NET Core v2 task
publishWebProjects - Publish web projects
boolean. Optional. Use when command = publish. Default value: true.
If this input is set to true, the projects property value is skipped, and the task tries to find the web projects in the repository and run the publish command on them.
When you use the dotnet publish task to build your project, you need to set the publishWebProjects
to false
. Then the projects
field value will work as expected. If the value is true, it will ignore the projects field and publish web projects in the repo. In your case, it will always build web projects.
To solve your issue, you need to set publishWebProjects to false in your Dotnet Publish Task.
For example:
# Publish the Web App package
- task: DotNetCoreCLI@2
displayName: 'Publish Web App'
inputs:
command: 'publish'
publishWebProjects: false
projects: 'RandomApp/WebApp.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/web --no-restore'
# Publish the Function App package into its own folder
- task: DotNetCoreCLI@2
displayName: 'Publish Function App'
inputs:
command: 'publish'
publishWebProjects: false
projects: 'RandomApp/RandomFunctions.csproj'
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/functions --no-restore'
In this case, the web app and function app projects will be output to the specified folders respectively.