Introduction to Azure Functions Pt. 5 - Automate the function deployment with a CI/CD pipeline
Tags: azure, serverless, dotnet, devops
Published: 2019-11-11 17:17:36

---
title: Introduction to Azure Functions Pt. 5 - Automate the function deployment with a CI/CD pipeline
published: true
description: 
tags: azure, serverless, dotnet, devops
series: Introduction to Azure Functions
---

## Introduction
In this post we will automate the deployment process of our Azure Function. We will setup a CI/CD process in Azure Devops that is run when we check into master. Next we will create a build pipeline that will build our entire solution and output an artifact for the function project. Finally we will create a release pipeline that will run automatically after the build succeeds and will take the build artifact and deploy it to our Function App. 

## Prerequisites
An Azure Devops account. Sign up for an account [here](https://azure.microsoft.com/en-us/services/devops/). I am using the free tier.

## Create an Azure Devops project
1. Login to the Azure Devops portal if you have not yet already.
2. Create a new Azure Devops project.
3. Under _Project Name_ name your project **Hello Azure**.
4. Click on _Create project_.


## Create a build pipeline
1. Login to the Azure Devops portal if you have not yet already.
2. Navigate to your **Hello Azure** project.
3. Click on _Pipelines_.
4. Click on _Builds_.
5. Click on _New pipeline_.
6. Under _Connect_ select the source control provider your code is hosted under. In my case GitHub.
    ![](https://i.imgur.com/ZmHOmAh.png)
    1. If you have not granted Azure Devops access to your GitHub account you will be redirected to a screen to grant access.
7. Under _Select_ select your repository. In my case `HelloAzure`.
    ![](https://i.imgur.com/OKakVt2.png)
    1. You will be redirected to a screen to grant Azure Devops access to your repository.
8. Under _Configure_ select **Starter Pipeline**
    ![](https://i.imgur.com/yc8SR1k.png)
9. Under _Review_ modify the contents of `azure-pipelines.yml` to be the following.
    ```yml
    trigger:
    - master
    
    pool:
      vmImage: 'ubuntu-latest'
    
    steps:
    - script: |
        dotnet restore
        dotnet build --configuration Release
    - task: DotNetCoreCLI@2
      inputs:
        command: publish
        arguments: '--configuration Release --output publish_output'
        projects: 'HelloAzure.Functions/HelloAzure_Functions.csproj'
        publishWebProjects: false
        modifyOutputPath: false
        zipAfterPublish: false
    - task: ArchiveFiles@2
      displayName: 'Archive files'
      inputs:
        rootFolderOrFile: "$(System.DefaultWorkingDirectory)/publish_output"
        includeRootFolder: false
        archiveFile: "$(System.DefaultWorkingDirectory)/build$(Build.BuildId).zip"
    - task: PublishBuildArtifacts@1
      inputs:
        PathtoPublish: "$(System.DefaultWorkingDirectory)/build$(Build.BuildId).zip"
        ArtifactName: "drop"

    ```
    1. `trigger` lets the pipeline know what can trigger it. In this case a checkin to `master`.
    2. `pool` is the environment we will run our build in.
    3. `steps` are the build steps.
        1. The first step runs two command line commands
            ```sh
            $ dotnet restore
            $ dotnet build --configuration Release
            ```
            1. The first command restores any nuget packages our solution depends on.
            2. The second command will build the entire solution in release configuration.
        2. The second step uses the dotnet core CLI to run a publish command on the project.
            1. We specify the configuration to be `Release` and the output of the publish to go into a directory named `publish_output`.
            2. We specify the `HelloAzure.Functions` project as the one to publish.
            3. We set `publishWebProjects` to `false` to prevent the dotnet cli from throwing an exception while it looks for web projects.
            4. We set `modifyOutputPath` to false in order to keep the output directory flat. This will be an important piece to publishing. 
            If `modifyOutputPath` is set to true we will get get a `publish_output` that looks like the following.
                ```
                .
                +-- publish_output/
                |   +-- HelloAzure.Functions/
                |       +-- ... published files
                
                ```
                We want an output that looks like the following.
                ```
                .
                +-- publish_output/
                |   +-- ... published files
                ```
            7. We will be running a separate step to archive the `publish_output` directory so we set `zipAfterPublishing` to `false`.
        3. The third step uses the `ArchiveFiles` task to turn `publish_output` into an archive that has the name of the build.
        4. The last step uses the `PublishBuildArtifacts` task to publish the build artifacts archive in a spot that our release pipeline can look for it.
10. Once you are happy with the `azure-pipeline.yml` file click on _Save and run_
    ![](https://i.imgur.com/9vVjka5.png)
11. In the _Save and run_ pane enter a commit message and choose a branch to commit the file to. In my case I just went with `master`.
    1. This will add the `azure-pipelines.yml` file to the root of your repo and commit the change.
12. The build will now attempt to run.
    1. If you get build failures verify that the branch you commited the `azure-pipelines-yml` file to is a branch that has your solution in it.

## Create a release pipeline
1. Login to the Azure Devops portal if you have not yet already.
2. Navigate to your **Hello Azure** project.
3. Click on _Pipelines_.
4. Click on _Releases_.
5. Click on _New pipeline_.
6. In the _Select a template_ pane select _Or start with an Empty job_.
    ![](https://i.imgur.com/gAOGtne.png)

### Adding a Stage
1. The _Stage_ pane will open after selecting _Or start with an Empty job_.
2. In the _Stage_ pane under _Stage name_ enter `Dev`.
    ![](https://i.imgur.com/gct6sde.png)
3. Close the _Stage_ pane.

### Adding an Artifact
1. Click on _Add an artifact_.
    ![](https://i.imgur.com/EQQKmfQ.png)
2. In the _Add an artifact_ pane ensure _Source type_ is set to **Build**.
3. Ensure _Project_ is set to **Hello Azure**.
4. Under _Source (build pipeline)_ select **HelloAzure**.
    ![](https://i.imgur.com/cRjhRCH.png)
5. Click on Add
    ![](https://i.imgur.com/meEiM5D.png)
6. Click on _Continuous deployment trigger_
    ![](https://i.imgur.com/8gLMVCH.png)
7. In the _Continuous deployment trigger_ pane toggle the switch for _Continuous deployment trigger_.
8. Under _Build branch filters_ select the branch you'd like to run on.
    ![](https://i.imgur.com/T3cV93k.png)
    

### Adding tasks to the Stage
1. Click on _1 job, 0 task_ under the _Dev_ Stage.
    ![](https://i.imgur.com/t1Mnn22.png)
2. In the _Tasks_ list click the _+_ icon on the _Agent job_ list item.
    ![](https://i.imgur.com/AjboFcj.png)
3. In the _Add tasks_ pane search for **Azure Functions**.
4. Click _Add_ on the **Azure Functions** task.
    ![](https://i.imgur.com/JxxLFHk.png)

### Configure the _Azure Function App Deploy_ task
1. In the configuration pane under _Azure subscription_ select your **Free Trial** subscription.
    ![](https://i.imgur.com/wxTTEBs.png)
    1. Click on Authorize
2. Under _App type_ select **Function App on Windows**
3. Under _App name_ select your Function App name.
    ![](https://i.imgur.com/8ZNnR4D.png)
4. Under _Package or folder_ ensure the value is set to `$(System.DefaultWorkingDirectory)/**/*.zip`.
5. Click on _Save_ in the menu-bar.
    ![](https://i.imgur.com/dCiyYJU.png)
6. Click on _Create release_ in the menu-bar.
    ![](https://i.imgur.com/vvRrUE2.png)
7. Follow the steps in the _Create release_ pane.
8. Navigate back to the pipeline details page and click on _Deploy_ under dev.
    ![](https://i.imgur.com/6LEXG7B.png)
9. Follow the steps in the _Deploy_ pane.
10. Your deployment will now be queued.



## Recap
In this post we setup a CI/CD process in Azure devops. We created a build pipeline that will automatically build our project. We then created a release pipeline that will take those build artifacts and automatically deploy them to our Function App.