{"id":2235,"date":"2017-12-28T04:33:23","date_gmt":"2017-12-27T20:33:23","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vsappcenter\/?p=2235"},"modified":"2019-02-16T15:30:35","modified_gmt":"2019-02-16T22:30:35","slug":"distribute-apps-faster-with-visual-studio-app-center-and-azure-functions-part-i","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/appcenter\/distribute-apps-faster-with-visual-studio-app-center-and-azure-functions-part-i\/","title":{"rendered":"Distribute Apps Faster with Visual Studio App Center and Azure Functions, Part I"},"content":{"rendered":"<p>As members of the Visual Studio App Center team, we\u2019re driven to create an easy-to-use, web-based user experience, and our API-first mentality steers our product decisions. We\u2019ve 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.  <\/p>\n<p>In this post, I&#8217;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.  <\/p>\n<p>I&#8217;ll expand on this topic in upcoming posts, covering automatic releases to app stores and getting urgent hotfixes to your customers with CodePush. <\/p>\n<h2>Defining a Scope<\/h2>\n<p>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\u2019s availability, I wanted to write only few hundred lines of code and spend less than 3&ndash;4 hours getting things going. To satisfy these requirements, I knew I\u2019d need some basic App Center setup, the right App Center APIs, a pre-built service framework, and a method to perform continuous releases. <\/p>\n<h2>Forget Builds and Focus on Commits<\/h2>\n<p><strong><em>Implementation time<\/em>: 5 minutes<\/strong><\/p>\n<p>The first step for setting up my automated release pipeline in App Center was to configure the Build service.  <\/p>\n<p>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.  <\/p>\n<p>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.<\/p>\n<p><img decoding=\"async\" src=\"\" alt=\"\" width=\"1024\" height=\"900\" class=\"aligncenter size-large wp-image-2245\" \/><\/p>\n<p>Enabling <em>Build this branch on every push<\/em> and <em>Distribute builds<\/em> 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.<\/p>\n<h2>Collecting Data Points<\/h2>\n<p><strong><em>Implementation time<\/em>: 15 minutes<\/strong><\/p>\n<p>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.  <\/p>\n<p>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 (<a href=\"https:\/\/docs.microsoft.com\/en-us\/appcenter\/sdk\/\" rel=\"noopener\" target=\"_blank\">available here<\/a>) into my sample mobile project. To learn how to integrate the Crashes or Analytics SDKs into your app, check out <a href=\"https:\/\/docs.microsoft.com\/en-us\/appcenter\/sdk\/\" rel=\"noopener\" target=\"_blank\">App Center&#8217;s documentation<\/a>.   <\/p>\n<p>Once I\u2019d 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. <\/p>\n<p><img decoding=\"async\" src=\"\" alt=\"\" width=\"1024\" height=\"715\" class=\"aligncenter size-large wp-image-2255\" \/><\/p>\n<p><img decoding=\"async\" src=\"\" alt=\"\" width=\"1024\" height=\"715\" class=\"aligncenter size-large wp-image-2256\" \/><\/p>\n<h3>Pivoting to Automation<\/h3>\n<p>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.  <\/p>\n<p>Check out the code covered in the next section and fork <a href=\"https:\/\/github.com\/pniko\/auto-distribution-function\" rel=\"noopener\" target=\"_blank\">this repository<\/a>, so you can follow along using the latest version of our favorite editor, <a href=\"https:\/\/code.visualstudio.com\/\" rel=\"noopener\" target=\"_blank\">Visual Studio Code (VS Code)<\/a>. <\/p>\n<h2>Developing with Azure Functions<\/h2>\n<p><strong><em>Implementation time<\/em>: 5 minutes <\/strong><\/p>\n<p><a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/azure-functions\/functions-reference-node\" rel=\"noopener\" target=\"_blank\">Azure Functions<\/a>, part of the <a href=\"https:\/\/azure.microsoft.com\/en-us\/overview\/serverless-computing\/\" rel=\"noopener\" target=\"_blank\">Azure serverless app platform<\/a>, 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\u2019ll 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.   <\/p>\n<p>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. <\/p>\n<p><code>npm install -g azure-functions-core-tools@core<\/code><\/p>\n<p>It\u2019s important that an Azure Function codebase is tied to the correct subscription before running, or you won&#8217;t be able to run or debug it locally on your system. <\/p>\n<p>To ensure my project was configured for the right subscription, I navigated to the <a href=\"https:\/\/portal.azure.com\/\" rel=\"noopener\" target=\"_blank\">Azure portal<\/a>, created a new Function called <em>RereleaseTimer<\/em> underneath my subscription, switched back to VS Code, and ran the command below. <\/p>\n<p><code>func azure functionapp fetch-app-settings RereleaseTimer<\/code><\/p>\n<h2>Configuring the Success Metrics<\/h2>\n<p><strong><em>Implementation time<\/em>: 10 minutes <\/strong><\/p>\n<p>I decided to create a configuration file in the Azure Function project called <strong>config.json<\/strong> that would allow me to quickly add new apps as my needs grew in the future.<\/p>\n<p><code>[{                                                                          \n<span style=\"padding-left: 20px\">\"owner\": \"Patricks-Fantastic-Org\",<\/span>\n<span style=\"padding-left: 20px\">\"app\": \"FirstApp\",<\/span>\n<span style=\"padding-left: 20px\">\"source\": \"Alpha Testers\",<\/span>\n<span style=\"padding-left: 20px\">\"installs\": 1,<\/span>\n<span style=\"padding-left: 20px\">\"sessions\": 1,<\/span>\n<span style=\"padding-left: 20px\">\"crashes\": 0,<\/span>\n<span style=\"padding-left: 20px\">\"destination\": \"Beta Testers\"<span>\n}]<\/code><\/p>\n<ul>\n<li>The <em>source<\/em> and <em>destination<\/em> properties are reserved for the distribution groups you wish to move a release between.  <\/li>\n<li><em>Installs<\/em> are the total number of devices on the latest release. <\/li>\n<li><em>Sessions<\/em> are the number of devices that have used the latest version for longer than a minute.<\/li>\n<li><em>Crashes<\/em> represents the total number of crash events App Center has received.  <\/li>\n<li>If at any point the latest release within a <em>source<\/em> group meets all its criteria, it will automatically be distributed to the <em>destination<\/em>.  <\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"\" alt=\"\" width=\"718\" height=\"238\" class=\"aligncenter size-full wp-image-2265\" \/><\/p>\n<p>The owner and app properties are required to query nearly every public App Center API, so, as a team, we\u2019ve 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.   <\/p>\n<h2>Creating the Routine<\/h2>\n<p><strong><em>Implementation time<\/em>: 1 hour 30 minutes <\/strong><\/p>\n<p>The primary business logic that drives the <em>Function<\/em> is in the <em>index.js<\/em> file underneath the <em>RereleaseTimer<\/em> folder. <\/p>\n<p>I\u2019ve included a few helper methods that show how to query various App Center API\u2019s using the API token, app, and owner name. In particular, the <em>BuildUrl<\/em> function will set up your request options, so you can start working with App Center API endpoints right away.  <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/mobile\/wp-content\/uploads\/sites\/3\/2017\/12\/4-buildurl.tif\" alt=\"\" class=\"aligncenter size-full wp-image-2275\" \/><\/p>\n<p>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\u2019d configured.  <\/p>\n<p>Testers in the destination group will get a new release notification, so the process can continue until you\u2019ve 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.  <\/p>\n<p>In the future, I&#8217;ll expand on this model to analyze all versions that haven&#8217;t been distributed to a destination group, instead of solely the latest. <\/p>\n<h2>Performing a Test Run<\/h2>\n<p><strong><em>Testing time<\/em>: 1 hour <\/strong><\/p>\n<p>Testing Azure Functions in VS Code requires a <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/azure-functions\/functions-run-local\" rel=\"noopener\" target=\"_blank\">host<\/a> to run the trigger locally on a system. Executing <code>func host start \u2013-debug vscode<\/code> in the root directory of the project kicks things off, so you easily see the function processing on your local machine.  <\/p>\n<p>When I ran into issues figuring out why my releases weren&#8217;t automatically distributing, I set a breakpoint at the beginning of my <em>Function<\/em> in VS Code and used the <em>Attach to Azure Function<\/em> debug configuration already set up in the <strong>launch.json<\/strong> file to debug the code in real time.  <\/p>\n<p>After a few attempts, I was successfully fetching crash and analytics information for the latest release before deciding to redistribute. <\/p>\n<p><img decoding=\"async\" src=\"\" alt=\"\" width=\"1024\" height=\"653\" class=\"aligncenter size-large wp-image-2285\" \/><\/p>\n<h2>Configuring Continuous Integration<\/h2>\n<p><strong><em>Implementation time<\/em>: 10 minutes <\/strong><\/p>\n<p>I\u2019m under the strict belief that CI shouldn&#8217;t be more difficult to deploy than what it\u2019s 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.<\/p>\n<p><img decoding=\"async\" src=\"\" alt=\"\" width=\"1024\" height=\"750\" class=\"aligncenter size-large wp-image-2295\" \/><\/p>\n<p>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 <em>Deployment options<\/em> to link it to my local fork.  <\/p>\n<p>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. <\/p>\n<h2>Conclusion<\/h2>\n<p>We\u2019ve successfully distributed a release to a new group automatically based on analytics and crash data.  <\/p>\n<p>In my next blog, I&#8217;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. <\/p>\n<p>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.   <\/p>\n<p><a href=\"https:\/\/appcenter.ms\/\">Log in or sign up<\/a> for App Center today, and share your ideas through the App Center in-app feedback chat.\n&nbsp;\n&nbsp;\n<a href=\"https:\/\/appcenter.ms\/signup\"><img decoding=\"async\" src=\"\" alt=\"\" width=\"150\" class=\"aligncenter size-medium wp-image-2305\" \/><\/a>\n&nbsp;\n&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>As members of the Visual Studio App Center team, we\u2019re driven to create an easy-to-use, web-based user experience, and our API-first mentality steers our product decisions. We\u2019ve 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 [&hellip;]<\/p>\n","protected":false},"author":46,"featured_media":38034,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[16],"tags":[],"class_list":["post-2235","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-mobiledev"],"acf":[],"blog_post_summary":"<p>As members of the Visual Studio App Center team, we\u2019re driven to create an easy-to-use, web-based user experience, and our API-first mentality steers our product decisions. We\u2019ve 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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/posts\/2235","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/users\/46"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/comments?post=2235"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/posts\/2235\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/media\/38034"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/media?parent=2235"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/categories?post=2235"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/appcenter\/wp-json\/wp\/v2\/tags?post=2235"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}