When building software the most common scenario is that you have a team building the solution, application and/or service. You typically have front-end, back-end and full-stack developers, you have testers and designers, and more. However, working in a team is not always easy. Back in the days we could all have our software running locally and we just grabbed the latest version/commit and hacked away. For web applications the use of localhost
worked just fine for almost everyone. But with cloud based solutions where you have a strong connection to one or more cloud services, it becomes a little bit more complex - you might have connections to cloud services such as storage, databases, web service and more. In most cases these resources can be spun up by each developer or shared and then managed by a configuration/environment file.
But there are some services that cannot be shared and have strict requirements/dependencies on cloud services - Microsoft Teams Single-Sign-On Tabs and bots based on the Microsoft Bot Framework are two examples. These services requires that you use well-known publicly available domain names. When registering a bot you specify a FQDN for you bot web service, and for Microsoft Teams SSO Tab you register an Azure AD application with an APP ID URI that must contain your FQDN. You can’t have two or more developers running those public endpoints at the same time, hosting the application locally for debugging, and publishing your solution to a cloud service just to test it isn’t a feasible solution.
In this post I’m going to explain how I work with my teams when building cloud solutions, with focus on Microsoft Teams Apps development.
Sharing or not sharing resources?
The ideal solution is that each individual developer has a full copy of everything and works in isolation. They register their Azure AD apps, they have their own web apps hosted in the cloud (Azure for instance) and they have their own Microsoft 365 developer tenant. However, the reality is far from this and it’s not always an ideal solution. And in many cases - having the developers working in isolated environments causes issues further down the line; I’ve seen so many cases where the solution is just tested with one user, and of course an admin account.
So, if you should share resources what should you share then and what can’t you share. Let’s start with some features that we cannot share between developers when building solutions for Microsoft Teams:
Non shareable resources
- Bots: bots based on Microsoft Bot Framework are all registered in the Azure portal and they require a FQDN pointing at their messaging endpoint
- SSO Tabs: single-sign-on tabs requires you to have an Azure AD application with a hardcoded URL
- Teams manifest: the teams manifest contains hardcoded resources for the tabs, bots, connectors
- Connectors: Office 365 Connectors are registered in the Office 365 connector portal with hardcoded URLs
Shareable resources
There’s quite a few things you can (and should) share however, this list goes on but here are a few ones I do recommend. There is of course a lot of exceptions to this and scenarios where you actually do want to test things in isolation.
- Microsoft 365 Developer tenant: I think it is a very good practice to share the Microsoft 365 tenant for your project. I do however recommend that you use multiple accounts for your developers. By sharing the developer tenant you get more user interactions with multiple user profiles in your application and will detect many common mistakes up front.
- data stores: this can of course be debated, but if you share the same developer tenant and use multiple accounts, sharing common storage, caches, queues allows you to once again pick up quite a few mistakes and bugs early
- Azure Application Insights: There’s so many times I detected issues early by having my development team sharing Application Insights instance
With shared in this case I explicitly mean the local application used by the developers use the same back-end cloud services. I very seldom share access to the actual resource in Azure, that is I don’t hand out administrative permissions for the developers to fiddle with the Azure settings. If that is needed, then use dedicated resources.
How to share resources?
It’s not that easy sharing resources however and it requires some planning up-front, and it should contain some orchestration from you as the solution architect to make the onboarding of new developers easy - so make everything scripted and parametrized.
When I started to build the Microsoft Teams Apps generator - yo teams a few years back, one of the intentions I had was to make a great enterprise development solution, that supports scenarios exactly like this. The remainder of this post will focus on how to set up your Microsoft Teams development team using Yo Teams.
Prepare Microsoft Azure
Most resources when building Microsoft Teams apps requires you to have a cloud hosting solution, and even forces you to use parts of Microsoft Azure (bot registrations, Azure AD apps), so the first thing you need to do is to have an Azure subscription. Typically I create two or three resource groups:
- One resource group for the shared resources: data storage and other PaaS services needed. I typically host the published development environment here has well.
- One resource group for developer specific resource: this resource group contains all your unique bot registrations or other services that you need to be developer specific.
- (optional) One resource group for application insights: I think it makes sense to have a dedicated resource group for application insights, as it is easy to invite the devs to this resource group in case they want to work with the app insights data.
FQDN requirements for bots and SSO tabs, and Azure AD App registrations
The Bot messaging endpoints, connectors and SSO Tabs requires you to have a FQDN that proxies incoming requests to your local machine, so that you can debug easily and test without having to publish your solution to an Azure Web App (for instance). The most common way to do this is to use Ngrok, but I also recently published an alternative if you don’t want to pay for each developer or you can’t use Ngrok (see Setting up NGINX in Azure as an ngrok alternative). This allows you to have unique URLs for each developer.
I recommend that you set up a naming standard for your FQDN, such as project-dev-001
, and then assign each developer a number. You will follow this naming pattern for your bot registrations ( project-dev-001-bot
) and the SSO Tab Azure AD registrations ( project-dev-001-tab
).
With the help of Azure CLI you can do all this scripted and very easily just roll-on a new developer, or re-create a developer environment.
Development environment setup
Yo Teams supports having .env
files which allows you to specify local parameters for each developer. When Yo Teams packages the manifest and builds the solution it will pick up the parameters from the .env
file and replace them with the local properties. This way each development environment is unique. I typically create one .env
file for each developer - using the same naming standard as above ( project-dev-001.env
) and each developer just starts their Yo Teams project with gulp serve --env project-dev-001.env
).
When scaffolding a project using Yo Teams it by default creates parameters for your SSO Tabs, bots, connectors etc so it’s very easy for you to just copy the default generated file and replace with the id’s and secrets you got when you scripted your Azure resources.
The Teams manifest
There’s one thing you MUST do before sharing the .env
file with the developer. Assume that we do share the development tenant, if one developer uploaded their manifest it would make all requests for that app go to that developer. So you MUST HAVE multiple Teams apps - one for each developer. This is easily sorted out by generating a new Guid for the application id for each developer and modify the .env
file with this new Guid:
# Id of the Microsoft Teams application
APPLICATION_ID=b09c6bd0-3a09-11eb-888d-b5cbf3c9cf73
Now, each developer has their own instance of the Teams app. But, with the same name! This is easily fixed however by modifying the manifest.json
file to contain a replaceable parameter in the name and packageName section, as below, and just add a new parameter to the .env
file (DEV=001
).
"packageName": "{{PACKAGE_NAME}}{{DEV}}",
"name": {
"short": "Project - {{DEV}}",
"full": "Project - {{DEV}}"
}
In some cases I also make unique icons for the devs and just postfix the icons in the manifest:
"outline": "icon-outline-{{DEV}}.png"
. Creates a great dev experience and avoids common mistakes.
Bonus
If you follow these guidelines for your developers you will also gain some benefits when building your solutions for multiple environments (dev, stage, prod). If you follow my guide on how to deploy Yo Teams apps using Azure DevOps you can easily configure pipelines for all your environments based on the same principles. A full end-to-end enterprise ready dev/CI/CD solution!
Summary
Building solutions for Microsoft Teams, as a Team, does not have to be complex - but it requires some planning. There are of course alternatives to this and I do want feedback on what can be improved or changed in this process or how we can make Yo Teams even better for these scenarios. I hope this article helps you and your team in creating fantastic Microsoft Teams apps!