In this post we'll use Azure Functions as a gateway that recieves a payload from Octopus Deploy (after a deployment to production) and posts a notification to a Microsoft Teams channel.
The Azure Function code for this blogpost can be found at https://github.com/DavidDeSloovere/AzureFunction-OctopusToMicrosoftTeams
A few weeks ago Octopus Deploy released version 3.5 of the amazing deployment tool. In this version they introduced 'Subscriptions'. This feature allows you to subscribe to all kinds of events via email or webhook. Together with the release they also published a post, showcasing the use of 'Subscriptions' to send a notification of an Octopus Deploy event to a Slack channel via Zapier. Great idea, we usd Octopus Deploy at Natch, but... we don't use Slack, and I don't want to use Zapier. We did activate Microsoft teams recently, it comes for free with our Office 365 subscription and we are always looking to improve communication and workflow. So I got this idea:
Mission: post a message on a Microsoft Teams channel when Octopus Deploy has deployed an application in production, with Azure Functions in the middle
What is Azure Functions
With the announcement of Azure Functions going GA (General Availability) yesterday (2016-11-16), it seemed like the right time to write this blogpost. Azure Functions is Microsoft's implementation of the serverless computing model on top of Azure. Serverless computing has been the lastest evolution of the cloud. Amazon has had Lambda on AWS for two years already.
Azure Functions is a solution for easily running small pieces of code, or "functions," in the cloud.
We've come a long way. It started with buying physical hardware and running servers on them (been there, done that). Then came virtualization, renting resources, and running your VMs (IaaS). Evolving into platforms like Azure Website where you don't even own and maintain VMs anymore (PaaS). IaaS and Paas are still valid models, but you're paying for those resources 24/7 even if your application only runs a few hours a day or is only visited during office hours.
With serverless computing a lot of this changes. You only pay when your code is executed. You only maintain your code. The underlying infrastructure is taken care of for you by the hosting provider.
What is Microsoft Teams
In short, Microsofts answer to Slack. Released just a few weeks back (2016-11-02).
Microsoft Teams, the new chat-based workspace in Office 365
I believe Slack got a little bit scared, because they released this passive-aggresive 'Welcome Microsoft Teams' press release right after Microsofts announcement.
To set this all up, we have 3 parts:
- An Octopus Deploy Subscription that posts its payload to a webhook...
- An Azure function that receives the payload, extracts the data and posts a message
- A Microsoft Teams channel with an 'Incoming Webhook' connector
We'll start at the last step of the flow, because we need the webhook url for the Azure Function.
In the channel, add a connector of the type 'Incoming Webhook'.
All you need is a name (ie. Octopus Deploy) and you'll get a webhook url back under the outlook.office365.com domain. You might also want to upload the Octopus logo, because that will be displayed with the message. You'll need the webhook url in the next step, keep it in the clipboard.
In the Azure portal, add a new Function App. This App allows you to add multiple 'functions'. We'll only need one, and we'll use 'GenericWebhookCSharp' as the starting point. This template is configured to run on an incoming http request.
Under the Application Settings of the Funtion App, add a new 'app setting' named 'TeamsWebHookUrl' and paste the O365 webhook url as the value. This app setting will be available as an environment variable when we write our C# code. You don't need to hardcode this setting, so you don't need to put this in source control.
Copy the code from the github project (which I also set up as Continuous Integration source) or this gist.
Previously, without using a service like Zapier, I would have:
- created an ASP.NET MVC/WebApi project -> too much work (lazy developer = good developer)
- hosted it on a webserver (or azure) -> would run all the time (consume too much resources, expensive)
The code is very short and will be called a few times a day at most. Which is a great fit for an Azure Function.
Before we continue to the next step, copy the Function url from the Develop tab.
To activate a 'Subscription' you can either click around in Octopus Deploy until you stumble upon it or give up (yes, it's hidden very well). If you gave up, here iswhere you can find it: Configuration > Audit > Subscriptions (top right).
Create a new subscription. Give it a name, set filters and paste the Azure Function url in the 'Payload URL' field.
Now let's see if our setup works:
- Trigger an Octopus Deploy event that matches the filters of the subscription you have set up.
- In the Azure Portal, navigate to the monitor tab of your function, there is even a 'live event stream'
- Within a few seconds, your Microsoft Teams channel will receive the message that was sent by Octopus Deploy.
About writing the function
I started writing the code for the function in the Azure portal. The editor is pretty amazing, considering it's running in the browser. There a handy 'test' feature where you can quickly simulate a request to the function (which is more a webhook). This allows you to iterate quickly without leaving the browser. When the code was done (is code ever done?) I moved it to a github repo and set up the continuous integration option under the Function app settings. Now every commit in the master branch will automatically update the Azure function. So easy. I hadn't tried Azure functions before, nor had I used Octopus Deploy subscriptions or the Microsoft Teams webhook connector. Still I was able to get this all running in under 2 hours. Writing this blog post is actually more work.
Don't hesitate to leave a comment below or fork the github repo.