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

Journey to an intelligent Azure Chat Bot - Part 2
Photo by Ashutosh Dave / Unsplash

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-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.

Provision and publish a bot in Azure - Bot Service
Learn how to create Azure resources and publish your bot 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.

az deployment group create --resource-group bot --template-file /Users/roman/projects/testbot/deploymentTemplates/deployUseExistResourceGroup/template-BotApp-with-rg.json --parameters "/Users/roman/projects/testbot/deploymentTemplates/deployUseExistResourceGroup/parameters-for-template-BotApp-with-rg.json"

azure - create appservice resource using arm template

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

az deployment group create --resource-group bot --template-file /Users/roman/projects/testbot/deploymentTemplates/deployUseExistResourceGroup/template-AzureBot-with-rg.json --parameters "/Users/roman/projects/testbot/deploymentTemplates/deployUseExistResourceGroup/parameters-for-template-AzureBot-with-rg.json"

azure - create bot resource using arm template

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).

Image - Azure App Service Deployment in progess

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.

Image - Azure App Service specify Node.js 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".

Image - Chatbot deployed and working on Microsoft Azure Cloud

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