A powerful way to write and build Azure Functions is to use C# Script. This allows you to easily write function directly within the Azure Portal, or even using source control as simple .csx script files. You don’t need to pre-compile the function before deploying it to Azure and can easily edit and release changes. Authoring directly in the Azure Portal is simple and the code exists there, but setting up a Continuous Integration / Continuous Deployment (CI/CD) pipeline to deploy from source control isn’t as straight forward. This article will show you the simple steps necessary to setup a CI/CD pipeline using YAML within Azure DevOps to deploy your Azure Functions using the “Zip Deploy” method.

To get started writing the Azure Function, you can use the Azure Portal. This is a simple way to get started coding, testing and working on your Function in Development. However, when you need to push that code to Test, UAT, or Production environments, it’s best to use CI/CD automation using a tool like Azure DevOps.

First, you need to get your Azure Function App code into source control within an Azure DevOps Repo. You can download the contents of the Function App from the Azure Portal. You will need to place the files for the Function App in your Repository.

Below is an example of the files for a Function App that contains a single Function that you might have in your source control repository. Notice, the Function App files are placed in a subfolder named /src.

/src
- host.json
- /MyFunc
- - function.json
- - function.proj
- - run.csx

You can see the Function App contains the host.json file for the Function App, as well as a folder for a Function named MyFunc within the app.

To setup an Azure DevOps Pipeline used for CI/CD, you will make use of the following two tasks:

  1. ArchiveFiles@2 – This task will be used to zip up the Function App files into a .zip archive.
  2. AzureFunctionApp@1 – This task will be used to perform the Zip Deploy of the Function App’s .zip archive to the Azure Function App resource.

Below a sample YAML pipeline that can be used in Azure DevOps to perform the CI/CD deployment of this example Function App to Azure using the zipDeploy method. You’ll want to save this YAML to a file (for example deploy-pipeline.yaml) within the repository so it can be used by Azure DevOps.

trigger: none

stages:
- stage: deploy_function_app
  jobs:
    - deployment: FunctionAppDeployment
      displayName: 'Function App Deployment'
      strategy:
        runOnce:
          deploy:
            steps:
              - checkout: self
                clean: true

              - task: ArchiveFiles@2
                displayName: 'Create project zip'
                inputs:
                  rootFolderOrFile: '$(System.DefaultWorkingDirectory)/src'
                  includeRootFolder: false
                  archiveType: 'zip'
                  archiveFile: '$(Build.ArtifactStagingDirectory)/functionapp.zip'
                  replaceExistingArchive: true

              - task: PublishPipelineArtifact@1
                displayName: 'Publish zip artifact'
                inputs:
                  targetPath: '$(Build.ArtifactStagingDirectory)/functionapp.zip'
                  publishLocation: 'pipeline'
      
              - task: AzureFunctionApp@1
                displayName: 'Deploy Function App'
                inputs:
                  azureSubscription: <azure-subscription>
                  appType: 'functionapp'
                  resourceGroupName: '<azure-resource-group-name>'
                  appName: '<azure-function-app-name>'
                  package: '$(Build.ArtifactStagingDirectory)/functionapp.zip'
                  deploymentMethod: 'zipDeploy'

This this code example you’ll need to replace the <azure-subscription>, <azure-resource-group-name>, <azure-function-app-name> placeholders to be the values necessary to target your Azure Function App to deploy to.

Notice that this YAML example also includes the use of the PublishPipelineArtifact@1 task. This is so that the functionapp.zip archive that will be deployed to the Azure Function is also saved in the deployment history for the Azure DevOps Pipeline as an Artifact. This could be used to be consumed by another pipeline that uses that artifact, or simply as a means of being able to easily see and inspect the contents of the .zip archive that was deployed by the pipeline if troubleshooting is necessary.

NOTE: It’s worth noting that this exact same YAML Pipeline and zipDeploy method of deployment can be used for other Function Apps written in interpreted languages that don’t need pre-compilation. I’ve used this deployment pipeline method for Python-based Azure Function Apps too.

Happy scripting!

Microsoft MVP

Chris Pietschmann is a Microsoft MVP (Azure & IoT) and HashiCorp Ambassador (2021) with 20+ years of experience designing and building Cloud & Enterprise systems. He has worked with companies of all sizes from startups to Fortune 100. He is also a Microsoft Certified Azure Solutions Architect and developer, a Microsoft Certified Trainer (MCT), and Cloud Advocate. He has a passion for technology and sharing what he learns with others to help enable them to learn faster and be more productive.