CICD Pipeline for Serverless, release Azure Functions with VSTS.

While Serverless, Azure Functions, are just a few lines of code, they still require a release with all the principles a good pipeline. For example:

  • High quality by default.
  • Work in small batches.
  • Automate repetitive tasks.
  • Continuous improvement.
  • Everyone is responsible.
  • Transparency everywhere.

and some of the factors in the 12Factor methodology https://12factor.net/

Azure Function via Portal.

The implementation of an Azure Function can be written in the Azure portal (see: Create your first Azure Function). Not ideal for repeatability, automation, versioning, traceability, etc. (see list above and select more).

clip_image002

Backed-up with GIT

For more control the Azure Function can be connected to GitHub or VSTS (see screenshot). Better, but not ideal. When your release pipeline contains multiple environments, dev, test, staging and production you need the same number of branches in your Git repository, losing the ‘one codebase’ principle. There is also no control on the deployment other than a Pull to a specific branch. The config is decoupled from the release (App Function application settings), development is done local in files where only a Pull to a certain branch results in compilation and validation, all functions are deployed at once and more disadvantages … defiantly not optimal.

clip_image004

Visual Studio Tools

With the latest Visual Studio Azure Function Tools the development experience gets better. It is possible to build, run, validate, remote debug and deploy Azure Functions to Azure from a development environment. This also makes it possible to setup a more mature release pipeline for Azure Functions.

funproj

Within Visual Studio a solution can be created with multiple Azure Function projects (a funproj… J), which can contain multiple Functions. A Visual Studio Azure Function project is a deployable grouping, all functions in a funproj are deployed together. So, when a system requires that functions evolve separately than they need to be in separate funproj’s.

clip_image006

The deployment of a funproj works just the same as the deployment of an Azure WebApp. It simply is a Web Deploy which needs a Publish profile, downloadable from the Azure portal.

clip_image008

ARM and Application Settings.

only a comfortable way to deploy and run from a development environment isn’t enough to follow the principles of:

  • - One code base,
  • - configuration close to the environment,
  • - separate build and run stages,
  • - dev/prod parity

Dev/prod parity and destroy recreated can be reached via ARM definition files. The ARM definition for a single Azure Function App is not complex, the ‘special’ thing is the storage account the app needs, it won’t run without a proper configuration of this.

clip_image010

ARM can also be used for configuration and separate build/run stages. An Azure Function uses application settings the same way as Azure Web Apps, via the portal. Which is the best place to store all application settings, you can’t get any closer to the environment than that (the other place is the Azure KeyVault).

The integration points created in a function are registered in the application settings.

clip_image012

Also these settings can be used in the function itself via: WebConfigurationManager.AppSettings.Get("settingname");

In the ARM definition, this setting can be created via a resource setting in the Web App. Some settings will be overridden by the release process in a later deployment stage, mainly passwords. Most settings can be constructed out of parameters with variables and an environment setting (the preferred way).

clip_image014

VSTS Build and Release.

The Azure Function solution with multiple Azure Function projects and an ARM template is used to deploy to multiple environments, dev, test, staging and production. All artifacts are in one code base and a branching strategy takes care we are always in a deployable state.

clip_image016

A resource group per environment and a separation between dev/test and staging/production for security and separation of costs are the landing environment for the functions. The grouping of functions (per funproj) are deployed separately.

With all this in place, ARM, config, solution and projects, the build can be configured. Actually, not a real build, functions are compiled on the platform (you can deploy precompiled bits too). But the build step is mainly a copy activity.

VSTS Build, CI.

The build for ARM and Azure Functions is minimal, normally it would compile, get the depending packages, unit test, code quality etcetera, but for Functions all this can’t be done (yet?). For ARM we use some template validation tasks for naming conventions, security and other validations.

The publishing of the Function artifacts is only a copy action. A Function on Azure only exists of a Function.json and a run.csx (click the show files button in the Azure portal). This is also what the Visual Studio deployment does. It copies the artifacts to a temp folder, see C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\AzureFunctions\ Microsoft.AzureFunctions.Publishing.targets.

clip_image018

Something also the build definition needs to do, create build artifacts in a folder so the release can use them.

VSTS Release, CD.

The release contains two deployment activities (the test tasks are skipped for this post. Azure Functions is an integration solution, so a descend set of integration tests would be welcome).

The first activity is the ‘create or update Azure Resource Group’ with the parameters for the environment settings.

clip_image020

The second task is the deployment of the Azure Function. This task uses a small PowerShell script which reads the publish profile and uses MSDeploy.exe to deploy the function to Azure.

cmd.exe /C $("msdeploy.exe -source:IisApp='$wwwroot' -dest:IisApp='$websiteName',computerName='https://$publishURL/msdeploy.axd',userName='$userName',password='$password',authtype='Basic',includeAcls='False' -verb:sync -enableLink:contentLibExtension -enableRule:AppOffline -retryAttempts:2")

To use this MSDeploy in VSTS Release you can add an Azure PowerShell release step, which calls the PowerShell function with several parameters. To create a PowerShell script file which executes MSDeploy, look at: http://trycatchfail.com/blog/post/The-trials-and-tribulations-of-using-MSDeploy-with-PowerShell

For the deployment I’m using a little tweaked version of this script: Publishes a Windows Azure Web App from a Web Deploy Package using MSDeploy it accepts a publish settings file, which makes our live easier.

I’m using the same PowerShell for this: Build, publish and release DotNet Core 1.0.0 apps on Azure Websites with VSTS.

All this resulting in a mature release pipeline with all the capabilities which are available inside VSTS for traceability, transparency, testing and more.

Happy releasing in 2017.

clip_image022

Add comment