Setting up a Build and Release Pipeline for Azure Bot Service using Azure DevOps

This post is something I wanted to do for a long time already. In my opinion, the topic of CI/CD can be very beneficial in terms of easier deployments and delivery of solutions. That is why I decided to run through the process of a creating a CI/CD pipeline for an Azure Bot Service based on Azure DevOps which I want to share with you with this post.

Preparation

First of all, we need to prepare a couple of things before we can actually start building our CI/CD pipeline:

Create Azure DevOps repository

First of all, we need to create an Azure DevOps repository where we actually store our code. So head over to your Azure DevOps environment, which will be something like https://{tenantName}.visualstudio.com and create a new repository.

01_stephan_bisser_devops_bot
01_stephan_bisser_devops_bot

Then we use the command line to clone the repo to our local disk and initialize the Git repo locally. To do that open your CMD of choice, navigate to a folder where you would like to store the source code and execute the command

git clone https://{tenantName}.visualstudio.com/{projectName/_git/{repoName}
02_stephan_bisser_devops_bot
02_stephan_bisser_devops_bot

After the Git repo is initialized locally, we can now create a new VS bot project in that folder which will allow us to commit and push the code we are building locally to Azure DevOps for further processing. This way, we can develop and test our solution locally and if we say the code shall be deployed to Azure, we can just commit and push and the pipeline will do the rest, as we will see later on.

03-1_stephan_bisser_devops_bot
03-1_stephan_bisser_devops_bot

Make sure to create the project in the root folder where you cloned your repo into.

03-2_stephan_bisser_devops_bot
03-2_stephan_bisser_devops_bot

After the solution has been created, we can give it a go and test it locally, to see if the solution is building correctly. So hit F5 in Visual Studio and open the .bot file which has been created with the Bot Framework Emulator and type in a message.

04_stephan_bisser_devops_bot
04_stephan_bisser_devops_bot

So now that we have our repo stuff ready, we can go on and develop the bot logic locally. If we then say we are ready for production we can commit and push the changes to our Azure DevOps repo with the following 3 commands:

git add .
git commit -a -m "First commit"
git push origin master
05_stephan_bisser_devops_bot
05_stephan_bisser_devops_bot

Now that the code has been committed and pushed we can check if the files have been created in Azure DevOps.

06_stephan_bisser_devops_bot
06_stephan_bisser_devops_bot

Create a Build Pipeline

After having our code in the Azure DevOps repo, we can set up our build pipeline to build that code in the repo automatically as well. So within your DevOps tenant navigate to pipelines and add a new Build pipeline. You’ll need to select a template or start with an empty job (I’d go with a template as it saves time). In our case, it makes sense to select the “Azure Web App for ASP.NET template as we are building a C# bot.

07-1_stephan_bisser_devops_bot
07-1_stephan_bisser_devops_bot

Now we would normally need to configure some settings for our build pipeline like the Azure Subscription we want to deploy the code to. But in our case we want to separate the build pipeline from the release pipeline to avoid any troubles afterward, so we delete the task “Azure App Service Deploy” from our task list completely.

07-2_stephan_bisser_devops_bot
07-2_stephan_bisser_devops_bot
07-3_stephan_bisser_devops_bot
07-3_stephan_bisser_devops_bot

After that, we can save and queue our pipeline to make it ready to build our code.

07-4_stephan_bisser_devops_bot
07-4_stephan_bisser_devops_bot

Create a Release Pipeline

Now that we have our build pipeline ready, we need to create a release pipeline as well in order to actually deploy our built code to an Azure App Service. To do that head over to “Pipelines” and create a new release pipeline. Similar to the build pipeline we will go for the “Azure App Service deployment” template there.

08-1_stephan_bisser_devops_bot
08-1_stephan_bisser_devops_bot

After creating, the pipeline will look pretty empty, but we will change that in a second.

08-2_stephan_bisser_devops_bot
08-2_stephan_bisser_devops_bot

First of all, we need to add an artifact to the pipeline, which actually the finished “product” from our build pipeline. So select your project, source (which is our build pipeline) and the version you want to add to the pipeline (in my case I will go for the latest version).

08-3_stephan_bisser_devops_bot
08-3_stephan_bisser_devops_bot

Now we added the artifact to the pipeline, we need to add some tasks to our stage for deploying the bot. But we will also create the necessary Azure resources within our pipeline in order to automate that task as well. So we need to add 2 tasks for executing Azure CLI commands to our stage before the task “Azure App Service Deploy” will be executed. Make sure to select your  Azure subscription and select “Inline script” as a script location. Then paste in the following command and hit save:

az group create --location {location} --name {resourceGroupName}
08-4_stephan_bisser_devops_bot
08-4_stephan_bisser_devops_bot

The second Azure CLI command will create an Azure App Service Plan and an App Service. So we do the same thing as with the first task but the command should look like this:

call az appservice plan create --name {appServicePlan} --resource-group {resourceGroupName} --sku FREE
call az webapp create --name {appServiceName} --resource-group {resourceGroupName} --plan {appServicePlan}
08-5_stephan_bisser_devops_bot
08-5_stephan_bisser_devops_bot

Then we need to configure the 3rd task where we need to select the Azure subscription again and insert our App Service name from the previous task.

08-6_stephan_bisser_devops_bot
08-6_stephan_bisser_devops_bot

Now the last thing to do here is to enable the continuous deployment trigger to make sure that the releases pipeline will run each time a new build is available.

08-7_stephan_bisser_devops_bot
08-7_stephan_bisser_devops_bot

Now that we have that we will save it and check it again. The pipeline should look something like this:

08-8_stephan_bisser_devops_bot
08-8_stephan_bisser_devops_bot

Trigger the first Build and Release

Now that everything is in place, we can head over to our project in VS and commit and push again to trigger the build pipeline.

09_stephan_bisser_devops_bot
09_stephan_bisser_devops_bot

After the commit and push happened we should soon see that there is a new build available in Azure DevOps and if everything is correctly configured the output should be successful.

10-1_stephan_bisser_devops_bot
10-1_stephan_bisser_devops_bot

Now that the build is available, the release pipeline should be triggered to create our resources in Azure and deploy the code to those resources.

10-2_stephan_bisser_devops_bot
10-2_stephan_bisser_devops_bot

After you see all green lights, open the Azure Portal and check if the resources have been created correctly.

11_stephan_bisser_devops_bot
11_stephan_bisser_devops_bot

Create a new Bot Channel Registration

By the time of writing, I still have not quite figured out how to automate that task as well. The problem we have is that we need to create a new bot channel registration, BUT we need to create App ID and App Secret ourselves as we need to secret in our .bot file later on. So going with the automated routine using the CLI is no option at the moment as there is no way to grab that secret currently (I hope that there will be a solution to that soon). So within our Azure Portal we go to the App Service which has been created and grab the URL.

12-1_stephan_bisser_devops_bot
12-1_stephan_bisser_devops_bot

Then we create a new service called “Bot Channel Registration” and select “Create App ID in the App Registration Portal”:

12-2_stephan_bisser_devops_bot.png
12-2_stephan_bisser_devops_bot.png

Now we generate a new app password (= appSecret)

12-3_stephan_bisser_devops_bot.png
12-3_stephan_bisser_devops_bot.png

And after pasting that in into the Azure Portal we can create the service

12-4_stephan_bisser_devops_bot.png
12-4_stephan_bisser_devops_bot.png

Now that the service has been created, we need to adapt our .bot file locally with that information. So we create a new endpoint there (make sure to append “/api/messages” to your App Service URL you copied before as an endpoint):

{
            "type": "endpoint",
            "appId": "{appID}",
            "appPassword": "{appSecret}",
            "endpoint": "https://{appServiceName}.azurewebsites.net/api/messages",
            "id": "{someRandomID}",
            "name": "production"
}
13-1_stephan_bisser_devops_bot
13-1_stephan_bisser_devops_bot

Update the pipeline

Now you might already know, that with the current configuration of our release pipeline, we have a problem. Because we have tasks to create a new App Service each time a new build is available. That won’t work, as we already have created those services in Azure. So we need to just update the code for that service instead of creating a new one. The simplest way to do that is to create a new stage in the release pipeline (NOTE: I am currently figuring out how to work with conditions in the Azure CLI task to check if the service has already been created and if so skip the task and go straight to the code deployment). So we are going to clone the stage we created earlier.

14-1_stephan_bisser_devops_bot
14-1_stephan_bisser_devops_bot

But this time we only will have one task, which is responsible for deploying the code there, instead of creating the Azure resources. Also make sure to add an App Setting to that task, which will deal with the locked files: MSDEPLOY_RENAME_LOCKED_FILES = 1

14-2_stephan_bisser_devops_bot
14-2_stephan_bisser_devops_bot

Now that we have that, we will trigger the pipeline again by committing changes to our repo via the command line.

14-3_stephan_bisser_devops_bot
14-3_stephan_bisser_devops_bot

And if everything has run successfully, we can go ahead and test the bot in the Azure Web Chat emulator to see if the changes have been applied to the bot’s code.

15_stephan_bisser_devops_bot.png
15_stephan_bisser_devops_bot.png

Now you can go ahead and implement your bot’s logic, add Cognitive Services like LUIS and QnAMaker to make your bot intelligent and whenever you are finished, just commit and push and your Azure resources will be updated by Azure DevOps automatically…

Summary

To sum up, the use of Azure DevOps as a CI/CD pipeline can help you in terms of developing locally, but building and deploying remotely. Thus, there are still some minor issues, like the problem, that we need to create the Azure Bot Channel Registration manually, due to the fact, that we cannot grab the App Password using the Azure CLI. But apart from that, we have a pretty cool way of integrating a CI/CD pipeline for building bots as well.

NOTE: I will look into the Azure CLI task for creating the Azure resources and update this post when I have found a good way of handling conditions in that task to overcome the fact that we need to create a second stage for all deployments apart from the first one. So stay tuned…

One Comment

  1. Pingback: Learn to Bot - Stephan Bisser

Leave a Reply

Your email address will not be published. Required fields are marked *