Distribute Apps Faster with Visual Studio App Center and Azure Functions, Part I
As members of the Visual Studio App Center team, we’re driven to create an easy-to-use, web-based user experience, and our API-first mentality steers our product decisions. We’ve designed App Center to give you and your team ultimate flexibility and freedom: you pick and choose the components that best fit your needs, so you have more time to focus on building features your customers want, not managing day-to-day manual or redundant tasks.
In this post, I’ll share ways to set up a continuous release pipeline that redistributes your app to beta testers, without any manual work, based on crash and analytics data. With nothing more than Azure Functions to help drive an automation script and some basic App Center set up, you can automatically move releases between distribution groups.
I’ll expand on this topic in upcoming posts, covering automatic releases to app stores and getting urgent hotfixes to your customers with CodePush.
Defining a Scope
I started by outlining a clear goal to distribute, validate, and publish a release to different groups of testers without any manual steps other than merging a simple pull request. To keep in line with an average engineer’s availability, I wanted to write only few hundred lines of code and spend less than 3–4 hours getting things going. To satisfy these requirements, I knew I’d need some basic App Center setup, the right App Center APIs, a pre-built service framework, and a method to perform continuous releases.
Forget Builds and Focus on Commits
Implementation time: 5 minutes
The first step for setting up my automated release pipeline in App Center was to configure the Build service.
App Center gives you the ability to distribute builds you generate from changes in a git branch, so you can rapidly deliver updates to a group of developers or testers, without much time investment.
To do this for my project, I navigated to the Build service in App Center, selected my repository, and went directly into configuring my branch information.
Enabling Build this branch on every push and Distribute builds before selecting Collaborators, was all I needed to do to get any changes to my development branch automatically pushed to me and my team as new releases.
Collecting Data Points
Implementation time: 15 minutes
After delivering the latest app release to my team, I needed to gather their feedback on quality before distributing the release to a larger group.
To determine when a release would be redistributed, I focused on three metrics readily available through our public API: total installs, number of crashes, and sessions over one minute in length. To get this data, I simply integrated the latest App Center Analytics and Crash SDKs (available here) into my sample mobile project. To learn how to integrate the Crashes or Analytics SDKs into your app, check out App Center’s documentation.
Once I’d integrated the SDKs, I checked the Analytics and Crash services with in my App Center UI to verify data flowed into App Center every time I ran my application on my local device.
Pivoting to Automation
While the App Center portal allows me to manually investigate streams of information and decide when to redistribute a release, my goal was to create an automated way to react to changes in Crashes and Analytics without user intervention, potentially creating a store submission from an alpha release in the future without manual steps.
Check out the code covered in the next section and fork this repository, so you can follow along using the latest version of our favorite editor, Visual Studio Code (VS Code).
Developing with Azure Functions
Implementation time: 5 minutes
Azure Functions, part of the Azure serverless app platform, provides a fast and easy way to develop apps with event-driven compute and serverless architecture. The service also delivers great Continuous Integration support in minutes and frees the developer from any kind of system administrator responsibilities, saving a good amount of my already limited time budget. As an additional benefit, Azure Functions provided me and my team with a helpful template for the future, which we’ll be able to use when we need to run an action on a timer or RESTful endpoint without the overhead of creating a whole new service.
Before I could really get going, I had to make sure I was running the latest Azure Functions CLI on my system. To do this, I ran the snippet below in a VS Code terminal window.
npm install -g azure-functions-core-tools@core
It’s important that an Azure Function codebase is tied to the correct subscription before running, or you won’t be able to run or debug it locally on your system.
To ensure my project was configured for the right subscription, I navigated to the Azure portal, created a new Function called RereleaseTimer underneath my subscription, switched back to VS Code, and ran the command below.
func azure functionapp fetch-app-settings RereleaseTimer
Configuring the Success Metrics
Implementation time: 10 minutes
I decided to create a configuration file in the Azure Function project called config.json that would allow me to quickly add new apps as my needs grew in the future.
"source": "Alpha Testers",
"destination": "Beta Testers"
- The source and destination properties are reserved for the distribution groups you wish to move a release between.
- Installs are the total number of devices on the latest release.
- Sessions are the number of devices that have used the latest version for longer than a minute.
- Crashes represents the total number of crash events App Center has received.
- If at any point the latest release within a source group meets all its criteria, it will automatically be distributed to the destination.
The owner and app properties are required to query nearly every public App Center API, so, as a team, we’ve made locating these from the App Center portal easy: we always include them within the website address. To find the owner and app name for your project, navigate to any of the apps attached to your App Center account and look at the address bar.
Creating the Routine
Implementation time: 1 hour 30 minutes
The primary business logic that drives the Function is in the index.js file underneath the RereleaseTimer folder.
I’ve included a few helper methods that show how to query various App Center API’s using the API token, app, and owner name. In particular, the BuildUrl function will set up your request options, so you can start working with App Center API endpoints right away.
The current implementation checks the source group for its latest release before fetching information from the Crash and Analytics APIs. It will be released to a new distribution group after determining the release is stable based on the metrics I’d configured.
Testers in the destination group will get a new release notification, so the process can continue until you’ve produced a release-quality build. This is, of course, a very minimalistic distribution model, but it highlights one example of what you can accomplish with little effort.
In the future, I’ll expand on this model to analyze all versions that haven’t been distributed to a destination group, instead of solely the latest.
Performing a Test Run
Testing time: 1 hour
Testing Azure Functions in VS Code requires a host to run the trigger locally on a system. Executing
func host start –-debug vscode in the root directory of the project kicks things off, so you easily see the function processing on your local machine.
When I ran into issues figuring out why my releases weren’t automatically distributing, I set a breakpoint at the beginning of my Function in VS Code and used the Attach to Azure Function debug configuration already set up in the launch.json file to debug the code in real time.
After a few attempts, I was successfully fetching crash and analytics information for the latest release before deciding to redistribute.
Configuring Continuous Integration
Implementation time: 10 minutes
I’m under the strict belief that CI shouldn’t be more difficult to deploy than what it’s automating. One of the best parts about Azure Functions is the ability to attach a git repository to a Function and have it automatically update whenever you make changes to the codebase.
To set up Continuous Integration, all I needed to do was select the Platform features menu under my function in the Azure portal and click on Deployment options to link it to my local fork.
With so little time left in my self-designated time parameters, being able to configure this in under ten minutes was central to meeting my project completion deadline.
We’ve successfully distributed a release to a new group automatically based on analytics and crash data.
In my next blog, I’ll cover how to distribute releases between groups using a more robust workflow, including a preconfigured connection to an app store and a bit of additional Function code.
As we find new ways to make your experience the best ever, the App Center product and engineering group is not only excited to create solutions that work for you, but ones we can build on top of for ourselves.
Log in or sign up for App Center today, and share your ideas through the App Center in-app feedback chat.