Build and Deploy Azure Functions App from Build Server - azure

I have an Azure Functions App developed in Visual Studio using C# and Microsoft.NET.Sdk.Function.
I need to build and deploy this app from our Jenkins build server. What is the recommended approach? MSBuild? MSDeploy? Azure Functions CLI? FTP?
I can't use the Source Control or VSTS deployment.
Some sample scripts would be appreciated!

I was able to achieve the deployment in 2 steps. First, create a zip package using msbuild:
msbuild FunctionApp.sln /p:Configuration=Release /p:DeployOnBuild=true
/p:WebPublishMethod=Package /p:PackageAsSingleFile=true
/p:SkipInvalidConfigurations=true
/p:DesktopBuildPackageLocation="c:\output.zip" /p:DeployIisAppPath="Default Web Site"
Next, the package should be uploaded to azure blob storage (SAS tokens, etc)
And then, I utilized MSDeploy extension of Azure AppService that downloads the package and deploys it into your Azure Functions service:
{
"apiVersion": "2015-08-01",
"type": "Microsoft.Web/sites",
"name": "[variables('functionAppName')]",
"kind": "functionapp",
"dependsOn": [
...
],
"properties": {...},
"resources": [
{
"name": "MSDeploy",
"type": "extensions",
"location": "[resourceGroup().location]",
"apiVersion": "2015-08-01",
"dependsOn": [
"[concat('Microsoft.Web/sites/', variables('functionAppName'))]"
],
"tags": {
"displayName": "webDeploy"
},
"properties": {
"packageUri": "[concat(parameters('_artifactsLocation'), '/', parameters('webDeployPackageFolder'), '/', parameters('webDeployPackageFileName'), parameters('_artifactsLocationSasToken'))]",
"dbType": "None",
"connectionString": "",
"setParameters": {
"IIS Web Application Name": "[variables('functionAppName')]"
}
}
}
]
},
Make sure Azure Resource manager would be able to access the package!

That's an interesting solution! I explored the options a while back and for now just FTP and wait for the portable Functions CLI or use the CLI publish which zips up.

You can set up continuous deployment from the configuration of the functions app. At the end of the day, you want to "publish" your applications leveraging whatever tool you like on the build server, and then have those assets deployed as the function app.
To set up the deployment, navigate to your function app.
Click "Platform Features." You will see a section called "Code Deployment".
Click on "Deployment Options" and you will be prompted to set up the source. Here you can choose GitHub, local git, Dropbox, etc. Let's assume you're using local git.
Grab the git endpoint from the portal once you've configured it
Create a git repo on your build server, locally, or wherever you want to deploy from. Set up the endpoint from (3) as a remote. The git file structure should be the root of your published function.
Set up your build to push remote after publishing. Azure will detect the changes and automatically update the functions app.
This is similar for other options - for example, if you choose DropBox it will monitor the location and update once the files are changed/refreshed.
There is a full article on this capability here:
https://jlik.me/7b

msbuild is OK, please refer to the link here for more info
msbuild AzureFuncTest.sln /t:Rebuild /p:Configuration=Debug;PublishProfile=LocalDebug;DeployOnBuild=true;VisualStudioV
ersion=15.0

Related

Deploying custom software and configuration on Azure VMs

Context: looking to build out a test lab in Azure. The goal is to have VMs spun up from a CI/CD pipeline to run end2end automation tests. The VMs will need to be deployed based on a custom image. However, I don't want to maintain specific virtual machine images which have certain software installed in various flavors and permutations.
Furthermore, looking to have a self service and declarative solution where teams can specify in automation templates or scripts etc which software they need provisioned on the VM after it comes up, desired state.
Example: get me a VM based on image template X and install package A version 2.3, package B version 1.2 and and configure OS with setting X, Y and Z.
Software packages can come from various sources. MSIs, chocolatey, copy deploys etc.
There seems to be so many ways of doing it - seems like a jungle. Azure VM Apps? Powershell Desired State Configuration? Something else?
Cheers
Furthermore, looking to have a self service and declarative solution
where teams can specify in automation templates or scripts etc which
software they need provisioned on the VM after it comes up, desired
state. There seems to be so many ways of doing it - seems like a
jungle. Azure VM Apps? Powershell Desired State Configuration?
Something else?
There are 2 more ways you can accomplish this task.
You can make use of custom script extension in your pipeline and store the scripts with various packages or softwares in the storage account and use different scripts for installing different packages for different VM’s. Here, Your teams can just create a new script and store it in an Azure Storage account, And you can use any script with the package to deploy your VM.
Custom Script Extension:-
I created one Storage account and uploaded my custom script with package to install IIS server in Azure VM.
Now, While deploying your VM you can select this Custom Script in the Advanced tab like below:-
Select extension search for Custom Script Extension :-
You can browse the Storage account and pick your script to be installed in the VM. You can also install this script after VM deployment by going to VM > Left pane > VM + Extensions + application.
Script got deployed inside the VM and IIS server was installed successfully :-
As You want to automate this in your Azure DevOps pipeline, You can make use of ARM Template to install the Custom script extension in your VM pipeline. You can make use of TeamServicesagent property in ARM template to connect to your DevOps organization and deployment group in the ARM template and deploy the extension, Refer below :-
ARM Template :-
{
"name": "vmname",
"type": "Microsoft.Compute/virtualMachines",
"apiVersion": "2021-03-01",
"location": "[resourceGroup().location]",
"resources": [
{
"name": "[concat('vmname','/TeamServicesAgent')]",
"type": "Microsoft.Compute/virtualMachines/extensions",
"location": "[resourceGroup().location]",
"apiVersion": "2021-03-01",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines/','vmname')]"
],
"properties": {
"publisher": "Microsoft.VisualStudio.Services",
"type": "TeamServicesAgent",
"typeHandlerVersion": "1.0",
"autoUpgradeMinorVersion": true,
"settings": {
"VSTSAccountName": "AzureDevOpsorg",
"TeamProject": "Azuredevopsproject",
"DeploymentGroup": "Deploymentgroup",
"AgentName": "vmname"
},
"protectedSettings": {
"PATToken": "personal-access-token-azuredevops"
}
}
}
],
"dependsOn": [
"[resourceId('Microsoft.Storage/storageAccounts', toLower('vmstore8677676'))]"
],
"properties": {
"hardwareProfile": {
"vmSize": "Standard_D2s_v3"
},
"osProfile": {
"computerName": "vmname",
"adminUsername": "username",
"adminPassword": "Password"
},
"storageProfile": {
"imageReference": {
"publisher": "MicrosoftWindowsServer",
"offer": "WindowsServer",
"sku": "2019-Datacenter",
"version": "latest"
},
"osDisk": {
"name": "windowsVM1OSDisk",
"caching": "ReadWrite",
"createOption": "FromImage"
}
},
"networkProfile": {
"networkInterfaces": [
{
"id": "[resourceId('Microsoft.Network/networkInterfaces', 'app-interface')]"
}
]
},
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": true,
"storageUri": "[reference(resourceId('Microsoft.Storage/storageAccounts/', toLower('storaegeaccountname'))).primaryEndpoints.blob]"
}
}
}
},
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat('vmname', '/config-app')]",
"location": "[resourceGroup().location]",
"apiVersion": "2018-06-01",
"dependsOn": [
"[resourceId('Microsoft.Compute/virtualMachines/', 'vmname')]"
],
"properties": {
"publisher": "Microsoft.Compute",
"type": "CustomScriptExtension",
"typeHandlerVersion": "1.10",
"autoUpgradeMinorVersion": true,
"settings": {
"fileUris": [
"https://storageaccountname.blob.core.windows.net/installers/script.ps1?sp=r&st=2022-08-13T16:32:07Z&se=sas-token"
],
"commandToExecute": "powershell -ExecutionPolicy Unrestricted -File script.ps1"
}
}}
],
"outputs": {}
}
You need to generate SAS URL for the script file in your Azure storage account.
You can make use of Azure Dev-Test Labs and deploy a custom artifacts inside your Dev-test labs and different packages for different VM’s and copy the ARM Template and tasks of VM in the release pipeline of Azure DevOps.
Dev-Test Labs:-
I created one Azure Dev-Test Lab resource like below:-
Now, You can directly select from the bunch of pre-built images here:-
After selecting an Image create the VM > And Add Artifacts, Here you can add any desired package that needs to be installed in your VM
You can create multiple Dev-test labs according to your requirements and add additional packages as artifacts after the deployment of the VM.
You can click on apply artifacts and add additional or custom packages to your VM’s.
You can also automate this deployment via ARM template, Refer here :-
azure-docs/devtest-lab-use-resource-manager-template.md at main · MicrosoftDocs/azure-docs · GitHub
You can automate Azure Dev-Test lab deployment in Azure DevOps by following the steps given in this document:-
Integrate Azure DevTest Labs into Azure Pipelines - Azure DevTest Labs | Microsoft Learn
Apart from these methods, You can use chef and puppet to automate your deployments and packages.
Chef - Chef extension for Azure VMs - Azure Virtual Machines | Microsoft Learn
Puppet - Get Started on Azure With Puppet | Puppet by Perforce

Is it possible to deploy an Azure Web App based on a public git repo using only an ARM template?

I'm looking for a way to deploy an Azure Web App based on a public git repo containing a .NET, .NET Core, or Node service. However, I want to only use an ARM template to deploy the Web App.
So if I have a public repo that contains a .NET Core project (i.e., csproj and associated C# files), I want to deploy a Web App, using an ARM template, that will deploy from the repo. It seems like it's possible with the various options for continuous deployment, but I can't quite figure it out.
Yes it is, you need to define the sourcecontrol property of the webapp for that to happen, like in this example:
{
"apiVersion": "2015-08-01",
"name": "web",
"type": "sourcecontrols",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"RepoUrl": "[parameters('repoURL')]",
"branch": "[parameters('branch')]",
"IsManualIntegration": true
}
}

API to add properties to Azure Webapp Application settings

I have one web app running on a Azure appservice plan. The web app has a lot of settings defined in Application settings of the Web App. Now I want to replicate that web app with all its Application settings. I got the REST API to list down all the settings available for any web app (/api/settings). Although there is a POST call to add/update the settings , But it is not updating Application settings.
Is there any REST API to add/update the Application settings of Azure web app ?
Thanks,
Abhiram
Is there any REST API to add/update the Application settings of Azure web app ?
Yes, we could update the application setting with the following Update Application Settings REST API
Put https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resource group}/providers/Microsoft.Web/sites/{WebAppName}/config/appsettings?api-version=2016-08-01
Body
{
"id": "subscriptions/{subscriptionId}/resourceGroups/{resource group}/providers/Microsoft.Web/sites/{WebAppName}/config/appsettings",
"name": "appsettings",
"type": "Microsoft.Web/sites/config",
"location": "South Central US",
"tags": {
"hidden-related:/subscriptions/{subscriptionId}/resourceGroups/{groupName}/providers/Microsoft.Web/serverfarms/tomfreePlan": "empty"
},
"properties": {
"WEBSITE_NODE_DEFAULT_VERSION": "6.9.1",
"Test1": "testValue1" //Added value
}
}
Note: we could use the following List Application Settings REST API post way to list the appsetting body.
Post https://management.azure.com/subscriptions/{subscription}/resourceGroups/CXP-{resourceGroup}/providers/Microsoft.Web/sites/{WebAppName}/config/appsettings/list?api-version=2016-08-01
To my knowledge, there is not. But have you considered scripting your Web App settings with an ARM template? This is exactly the kind of thing that ARM templates are intended for.
An example of the properties section of a Web App's ARM template that lets you script appSettings and connectionStrings is listed below:
"properties": {
"name": "YourWebAppsName",
"serverFarmId": "[resourceId('Microsoft.Web/serverfarms', YourAppServicePlanName)]",
"siteConfig": {
"appSettings": [
{
"name": "someAppSettingKey",
"value": "someAppSettingValue"
},
{
"name": "someOtherAppSettingKey",
"value": "someOtherAppSettingValue"
}
],
"connectionStrings": [
{
"name": "defautlConnection",
"connectionString": "YourConnectionString",
"type": "2"
},
]
}
When you deploy an ARM template, Azure will ensure that the target resource's settings match what's specified in your template.
Visual Studio has a project type for developing and deploying these. It's the Azure Resource Group project type located under the Cloud node in the project templates.
As an added bonus, you can check these ARM templates into source control alongside your code.

Azure ARM templates deployment Github integration (with deploy keys)

I want to do ARM templates deployment for web app which has source code on Github. So far after quite some trial and error, I am able to use following format:
"apiVersion": "2015-08-01",
"name": "web",
"type": "sourcecontrols",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"RepoUrl": "https://github.com/user/repo.git",
"branch": "dev",
"IsManualIntegration": true
}
}
This is manual integration. It seems to work if I have previously used Github and authorised Azure. Isn't there any way to automatically setup and sync Github repo? Is there any way to use deploy keys?
Yes, it is possible, but not with ARM Template. Follow the steps here.
But if you've setup Github once on your subscription you can use this manual integration for all deployments in this subscription and it will work, so nothing to worry about.

Connect Azure Function App to VNet

How can I deploy my function app attached to a VNet using an arm template?
Right now my arm template deploys an AppServicePlan based function app just fine and sets the "vnetName" in the "site" resource "properties" section...but after the deploy the function app still shows as "not configured" for any VNet. I can then go into the portal and add to the desired VNet in a couple of clicks...but why doesn't it work via the arm template? Can someone please provide a sample arm template to do this?
Upon further review this is not possible via only ARM. Here are the instructions to connect a web app to a VNet: https://learn.microsoft.com/en-gb/azure/app-service-web/app-service-vnet-integration-powershell
Old Answer: Here is another post trying to achieve the same with Web Apps (Functions is built on Web Apps): https://stackoverflow.com/a/39518349/5915331
If I had to guess based on the powershell command, try adding a sub resource to the site of type config with name web, similar to the arm template for a github deployment: https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/app-service-web/app-service-web-arm-from-github-provision.md#web-app
There may be some magic happening under the hood, however.
{
"name": "[parameters('siteName')]",
"type": "Microsoft.Web/sites"
"location": ...,
"apiVersion": ...,
"properties": ...,
"resources": [
"name": "web",
"type": "config",
"apiVersion": "2015-08-01",
"dependsOn": [
"[resourceId('Microsoft.Web/Sites', parameters('siteName'))]"
],
"properties": {
"vnetName": "[parameters('vnetName')]"
},
]
}
I can do everything with ARM except create the VPN package - which is what makes the difference between just setting the resource properties and actually making the app connect to the VNET correctly.
Everything in this article (https://learn.microsoft.com/en-gb/azure/app-service-web/app-service-vnet-integration-powershell) can be easily converted from PowerShell to ARM except for Get-AzureRmVpnClientPackage
Hypothetically, if you are using a legacy VNET, you could get the VPN client package URL via ARM because the legacy VNET resource provider supports that operation (https://learn.microsoft.com/en-us/azure/active-directory/role-based-access-control-resource-provider-operations):
Microsoft.ClassicNetwork/virtualNetworks/gateways/listPackage/action
The ARM VNET provider does not seem to

Resources