Deploying Logic Apps (Preview) using Azure DevOps and GitHub Actions
Single-tenant Logic Apps are now Generally Available! Refer to Microsoft’s Set up DevOps deployment for single-tenant Azure Logic Apps documentation for instructions on deploying them using Azure DevOps / Github.
Last September the Azure Logic Apps team has unveiled a new Logic Apps runtime which is built as an extension of Azure Functions runtime, this means you can now run Logic Apps everywhere you can run Function Apps including App Service Plans, Functions Premium plan, and locally on your device. Due to runtime changes the process for building and deploying Logic Apps changes from a fully ARM based approach to one almost identical to building and deploying a Function App.
You can the Logic Apps (Preview) documentation here: Overview: Azure Logic Apps Preview - Microsoft Docs.
⚠: As this runtime is preview it is not supported for Production workloads and includes some bugs and limitations. Make sure to familiarise yourself with known issues before getting started.
All templates used in this guide can be found at maciejporebski/function-based-logic-apps.
Developing
To get started with Logic Apps (Preview) download the Visual Studio Code extension Azure Logic Apps (Preview). The extension provides ability to scaffold projects and workflows. You’ll notice the generated project is very similar to a Functions App project.
Each workflow should be defined in a workflow.json
file placed in a folder which name will determine the workflow name. The workflow folders must be copied to the output directory. If you generate a new workflow using the “Create Workflow…” feature of Logic Apps (Preview) extension the directory will be added to the .csproj, however if you are creating workflows manually or decided to rename a workflow directory make sure to update your .csproj file:
<ItemGroup>
<None Update="CurrentTime\**\*.*">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Building
The build process is exactly the same as for a .NET Core Azure Functions project. You will want to restore nuget packages, build the project and publish it using the dotnet CLI.
dotnet restore
dotnet build
dotnet publish
Azure Pipelines
In Azure Pipelines use the DotNetCoreCLI
task to restore, build, and publish the package.
- task: DotNetCoreCLI@2
displayName: restore
inputs:
command: restore
projects: '**/*.csproj'
- task: DotNetCoreCLI@2
displayName: build
inputs:
projects: '**/*.csproj'
arguments: '--configuration Release'
- task: DotNetCoreCLI@2
displayName: publish
inputs:
command: publish
publishWebProjects: false
projects: '**/*.csproj'
arguments: '--configuration Release --output $(build.artifactstagingdirectory)'
zipAfterPublish: True
.azure-devops/azure-pipelines.yml
GitHub Actions
In GitHub actions use the actions/setup-dotnet
action to set up the SDK (currently the latest version supported by Azure Functions runtime is 3.1), then run the restore, build and publish commands.
- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v1.7.2
with:
dotnet-version: 3.1
- name: .NET Restore
run: dotnet restore $GITHUB_WORKSPACE/src/src.csproj
- name: .NET Build
run: dotnet build $GITHUB_WORKSPACE/src/src.csproj --configuration Release
- name: .NET Publish
run: dotnet publish $GITHUB_WORKSPACE/src/src.csproj --configuration Release --output $GITHUB_WORKSPACE/output
- uses: actions/upload-artifact@v2
with:
name: logic-app-package
path: output
.github/workflows/deploy-logic-app.yml
Building infrastructure
As previously mentioned Logic Apps (Preview) run on Azure Functions, this becomes obvious when deploying the Logic Apps (Preview) resource, which is a Microsoft.Web/sites
resource, with few minor differences compared to a Functions App Resource. The properties requiring Logic Apps (Preview) specific values are:
- kind
- properties.siteConfig.cors.allowedOrigins
- properties.siteConfig.appSettings
The required values are:
{
"type": "Microsoft.Web/sites",
"apiVersion": "2020-09-01",
"name": "[parameters('logicAppName')]",
"location": "[parameters('location')]",
"kind": "functionapp,workflowapp",
"properties": {
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', parameters('appServicePlanName'))]",
"siteConfig": {
"cors": {
"allowedOrigins": [
"https://afd.hosting.portal.azure.net",
"https://afd.hosting-ms.portal.azure.net",
"https://hosting.portal.azure.net",
"https://ms.hosting.portal.azure.net",
"https://ema.hosting.portal.azure.net"
]
},
"appSettings": [
{
"name": "APP_KIND",
"value": "workflowApp"
},
{
"name": "AzureFunctionsJobHost__extensionBundle__id",
"value": "Microsoft.Azure.Functions.ExtensionBundle.Workflows"
},
{
"name": "AzureFunctionsJobHost__extensionBundle__version",
"value": "[1.*, 2.0.0)"
},
{
"name": "AzureWebJobsStorage",
"value": "[concat('DefaultEndpointsProtocol=https;AccountName=', parameters('storageAccountName'), AccountKey=', listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName')'2019-06-01').keys[0].value)]"
},
{
"name": "FUNCTIONS_EXTENSION_VERSION",
"value": "~3"
},
{
"name": "FUNCTIONS_V2_COMPATIBILITY_MODE",
"value": "true"
},
{
"name": "FUNCTIONS_WORKER_RUNTIME",
"value": "dotnet"
}
]
}
},
"dependsOn": [...]
}
function-based-logic-apps/infrastructure/arm-template.json
Aside from the Logic Apps (Preview) resource you will need to deploy or reference an existing hosting App Service Plan and Storage Account. It is also a good idea to deploy an Application Insights resource to monitor your Logic App. All of these resources are deployed by the full template: arm-template.json
Deploying
The deployment process consists of two parts:
- deploying the infrastructure
- deploying the built package to the Logic Apps (Preview) resource
Azure Pipelines
In Azure Pipelines use the AzureResourceManagerTemplateDeployment
task to deploy the ARM template created in the ‘Building infrastructure’ section. Then use the ‘AzureRmWebAppDeployment’ task to deploy the built package to the Logic Apps (Preview) resource. Set the ‘appType’ property to ‘functionApp’ as currently Logic Apps (Preview) does not have a dedicated appType value.
- task : AzureResourceManagerTemplateDeployment@3
displayName: deploy_arm
inputs:
azureResourceManagerConnection: $(serviceConnection)
resourceGroupName: '$(resourceGroup)'
location: '$(location)'
csmFile: '$(pipeline.workspace)/drop/arm-template.json'
overrideParameters: '-logicAppName $(logicAppName) -storageAccountName $(storageAccountName) -appServicePlanName (appServicePlanName) -insightsName $(insightsName) -location $(location)'
- task: AzureRmWebAppDeployment@4
displayName: deploy_logic_app
inputs:
ConnectionType: 'AzureRM'
azureSubscription: $(serviceConnection)
appType: 'functionApp'
WebAppName: '$(logicAppName)'
packageForLinux: '$(pipeline.workspace)/drop/src.zip'
.azure-devops/azure-pipelines.yml
GitHub Actions
In GitHub Actions sign in to Azure by using the azure/login
action (you must configure service principal details in your repo secrets first), use the Azure/arm-deploy
action to deploy the infrastructure, then finally use the Azure/functions-action
action to deploy the package.
- uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Deploy Infrastructure
uses: Azure/arm-deploy@v1
with:
scope: resourcegroup
subscriptionId: ${{ secrets.SUBSCRIPTION_ID }}
resourceGroupName: ${{ env.RESOURCE_GROUP }}
template: infrastructure/arm-template.json
deploymentMode: Incremental
parameters: logicAppName=${{ env.LOGIC_APP_NAME }} storageAccountName=${{ env.STORAGE_ACCOUNT_NAME }} appServicePlanName=${{ env.ASP_NAME }} insightsName=${{ env.INSIGHTS_NAME }} location=${{ env.LOCATION }}
- name: Deploy Logic App
uses: Azure/functions-action@v1.3.1
with:
app-name: ${{ env.LOGIC_APP_NAME }}
package: logic-app-package
Comments