Journey to an intelligent Azure Chat Bot - Part 2
In this blog series we build a versatile and useful chatbot based on azure, microsoft bot framework, nodejs, teams, chatgpt. Today - Deploy Chatbot to Azure with an automated CICD Pipeline
First, I have to mention: As of today, I have no clue yet how to build a chatbot with Microsoft Azure. None of the steps below I have done before - Research will be necessary.
That said - the following are the goals and also the features of the bot built in this blog series. Achieving those goals will certainly facilitate a lot of the daily business:
- Part 1 - Have an Azure Chatbot built in NodeJS
- Part 2 - Deploy the Bot to azure with an automated CICD pipeline
- Part 3 - Integrate the Bot in a Microsoft Teams Channel
- Part 4 - Test how to build multiple choice selections, user intent, dialog flows, prompts and answer validation. Support for Custom API Interactions.
- Part 5 - Test Azure Conversational Language Understanding (CLU)
Part-2 Content
Introduction
Today we are in part 2 of this blog series. In the first part of this blog series, we already have built our basic Microsoft Azure Chatbot in Node.js. Let's focus now on the deployment on Microsoft Azure Cloud. Our goal is to have an automatic CICD Pipeline in GitLab, that can install the bot on the Azure Cloud. So every time we change the code during the next steps in this blog series, we don't have to do manual deployment steps in order to deploy changes to the Microsoft Azure Cloud.
If you are following along - I also have the code for your review in a public GitHub Repository. I did not include the CICD Pipeline (.gitlab-ci.yaml) there though. You can see the pipeline in full down below.
Gitlab Repository
I have created a new empty repository in GitLab and uploaded the code we created in the last blog (part 1). Also, I have added a .gitignore file (standard for Node.js projects) in order to ignore the "node_modules" folder.
Then I have also added a ".gitlab-ci.yml" file in the project root, which is the CICD Pipeline that we are just about to implement.
Research, Prerequisites
First I did some research on how to deploy our new chatbot to Azure.
This is the official documentation on how to deploy the bot on azure. So let's try it manually according to this documentation and then have some thought about building a CICD pipeline just after.
It seems I need the azure-cli so let's install it on the mac
# https://learn.microsoft.com/en-us/cli/azure/install-azure-cli-macos
brew update && brew install azure-cli
Azure - Manual Bot Deployment
First, lets connect with azure using the "az login" command from the azure cli toolset.
# connect to azure
az login
# switch to correct subscription
az account set --subscription "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# create a ressource group for the bot
az group create --name "bot" --location "North Europe"
# create a service principal /
# app registration (make note of the app id)
az ad app create --display-name "bot" --sign-in-audience "AzureADMyOrg"
# create a secret for the app (paste app id)
az ad app credential reset --id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
Next step, according to the documentation, is to create an app service. So I edit the file parameters-for-template-BotApp-with-rg.json in the project and enter appId, appSecret, tenantId, appType=SingleTenant, appServiceName=testbot.
I end up using this command to create the app service. Later on, I might want to migrate this resource deployments mechanism to terraform, which I personally prefer. But as we already are provided with ARM Templates by Microsoft, let's stick to that right now.
Now we also need to create the bot ressource. I edit the file parameters-for-template-AzureBot-with-rg.json and fill the values azure BotId=testbot, appType=SingleTenant
Now we push our bot to azure to be hosted by the app service just created. As this is a JavaScript NodeJS project, I edit the .env file and fill again the necessary infos. The LUIS Info is missing - we dont need it right now.
MicrosoftAppType=SingleTenant
MicrosoftAppId=c*********
MicrosoftAppPassword=***********
MicrosoftAppTenantId=**********
LuisAppId=
LuisAPIKey=
LuisAPIHostName=
Now I start to actually deploy to Microsoft Azure Cloud.
# install dependencies
npm install
# web.config generate
az bot prepare-deploy --lang Javascript --code-dir "."
# zip the whole bot folder
...manual => testbot.zip
# deploy to azure
az webapp deployment source config-zip --resource-group "bot" --name "butschi84-testbot" --src "./testbot.zip"
In my new app service on Microsoft Azure I see the message "Pending" or "In Progress, building your application", which takes quite a while (20 minutes initially).
When opening the URL of the app service , I see that it is not working. Then I checked the Logs of the app service and found that it must be an issue with the Node.js version in the app service. So I started research on how to specify the Node.js Version as 18.12.1. In the configuration, I could specify the desired version.
Now it seems to be working, very good. In the bot service resource on Microsoft Azure, I also had to specify the web address of the app service under "configuration": https://butschi84-testbot.azurewebsites.net/api/messages
Now, when clicking on "Test in Web Chat" I see a familiar greeting card from my bot - "bujakasha".
CI/CD Pipeline
As this is successfully setup manually, we also want the deployment to work from an automated CI/CD Pipeline. In the app service, that we deployed, you could connect to a GitHub Repository, and it would just set up a pipeline automatically for you.
But that's not for me - I am more familiar with GitLab and prefer to use it for my projects. After trying to build a pipeline corresponding to the manual steps mentioned above, I came to a solution with 3 stages
- preparation
which generates the file web.config - build
which installs all npm dependencies and creates the bot.zip - deploy
which will deploy the bot to azure
I have added delegated permissions "Users.Read" to the Service Principal in Azure, so that the pipeline can connect to azure using this service principal. Also granted the service principal permissions to the subscription. Here is the full final pipeline (.gitlab-ci.yml) from the root of the bot project.
image: docker:latest
services:
- docker:dind
variables:
azure_app_id: ********-****-****-****-************
azure_tenant: ********-****-****-****-************
stages:
- prepare
- build
- deploy
# ###########################################
# bot prep
# ###########################################
prepare bot:
stage: prepare
image: mcr.microsoft.com/azure-cli
script:
- |-
# azure login
echo azure login service principal $azure_app_id ...
az login --service-principal -u $azure_app_id -p $azure_app_password --tenant $azure_tenant
# prepare deploy
echo preparing deployment...
rm web.config | true
az bot prepare-deploy --lang Javascript --code-dir "."
artifacts:
paths:
- web.config
only:
- main
# ###########################################
# bot build
# ###########################################
bot build:
image: node:18.12.1
stage: build
script:
- |-
echo building and zipping the bot
echo install npm dependency packages
npm install
echo install zip utility
apt update && apt install zip -y
echo create the bot zip
zip -r bot.zip ./*
artifacts:
paths:
- bot.zip
- web.config
only:
- main
# ###########################################
# bot deployment
# ###########################################
deploy:
stage: deploy
image: mcr.microsoft.com/azure-cli
script:
- |-
# azure login
echo azure login...
az login --service-principal -u $azure_app_id -p $azure_app_password --tenant $azure_tenant
# bot deployment
echo start bot deployment
az webapp deployment source config-zip --resource-group "bot" --name "butschi84-testbot" --src "./bot.zip"
artifacts:
paths:
- bot.zip
only:
- main
when: manual
When I commit new changes to the GitLab Repository, the pipeline now starts and deploys the chatbot automatically to the Microsoft Azure App Service.
That means, we have achieved the second goal: Deploy the Bot to azure with an automated CICD pipeline