UPDATE OCTOBER 2018

The Function pack utility is now deprecated in favour of a new utility called 'run from package'. Unfortunately 'run from package' does not yet support Linux, so you would have to use a windows host for your Azure functions app in Azure. I have not tried this, so cannot provide any guidance. Currently our VSTS function deployment is broken as i await feedback from Microsoft on the issue.

Original post....

As of June 2018 there is no official documentation on how to deploy an Azure Function written in Javascript via an automated deployment pipeline, such as Visual Studio Team Services. The steps in this article should work with any deployment service that can target Azure App Service, as the steps largely consist of package manager script calls.

To follow this article you will need the following

1) Create a function app in Azure

Head over to Azure and create a function app. It doesn't matter whether you use an App Service or Consumption plan.

2) Create a Javascript function app locally

See the official getting started article for up to date instructions if you don't already know how to do this. You should create a Javascript function with a HTTP trigger.

Alternatively, you can just clone my function app repository that i created while writing this article.

3) Configure the app deployment scripts

The VSTS build definition we will eventually create depends upon an npm script defined in package.json. The function CLI tools that created the app for you in step 2 doesn't currently create a package.json for you. Either use npm init or yarn init to create one in the function project root folder - Do not create this in the HTTP trigger function subfolder!
Why? a function app can have many functions, and typically share the package.json and dependencies. This is optimal to the function app, as all dependencies can be loaded once per function app.

Once you have a package.json, add the following script...

"scripts": {
    "pack": "funcpack pack ."
  }

The funcpack call relies on the Azure Functions Pack Why do we need this? it helps with performance, and they provide a good explanation of that on the repository homepage.

At this point you should push the source code of your function app to a remote repository that you can access from your VSTS account. Alternatively, you could use my function app repository that i put together when writing this article.

With the app now ready for deployment we can move onto the VSTS build definition.

4) Create the VSTS build definition

Create an empty build definition and hook the source up to your remote repository, or my function app repository. When selecting a build agent - if you are not using a hosted agent (which includes npm) then ensure your agent has this installed.

Now lets add the build tasks...

  1. Add an npm task which calls install. Self explanatory.
  2. Add a custom npm task which calls install -g azure-functions-pack
  3. Add a custom npm task which calls run pack
  4. Add a delete files task and specify node_modules as the folder. This may seem odd, but the pack script in step 3 combines the node_modules folder into a single script. See the explanation for more details
  5. Add a copy files task and specify $(Build.ArtifactStagingDirectory)/functions as the target folder
  6. Add an archive task with root folder set to $(Build.ArtifactStagingDirectory). Ensure the prepend root folder option remains unchecked. Set archive file to create to $(Build.ArtifactStagingDirectory)/Functions.zip
  7. Add a publish artifacts task with path to publish set to $(Build.ArtifactStagingDirectory)/Functions.zip and Artifact Name set to drop
  8. Add a Azure App Service Deploy task with App Type set to function and Package or folder set to $(Build.ArtifactStagingDirectory)/Functions.zip. Subscription must be set to your Azure account, if the drop down contains no entries then you need to connect your Azure subscription to VSTS via a Service Principal. Finally, select the function app in the App Service Name box, or type it in if nothing comes up (it can be sporadic!)

That's it. Now run the build, and you should end up with a successful deployment...

Successful Node Azure Function Deployment

Be aware that Azure functions V2 is very much in development, and is now being extended to support containers and kubernetes. How much of this article will still be relevant six months from now is anyones guess. It's great that Microsoft have taken a different approach with V2 and are now giving cross-platform development a priority. Consumption plans have always felt like the true 'serverless' way to me, but with support for Kubernetes just being announced it puts some interesting options on the table.