{"id":52971,"date":"2019-01-25T16:00:18","date_gmt":"2019-01-25T16:00:18","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/devops\/?p=48435"},"modified":"2019-02-14T15:48:04","modified_gmt":"2019-02-14T23:48:04","slug":"top-5-open-source-features-in-azure-pipelines","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/top-5-open-source-features-in-azure-pipelines\/","title":{"rendered":"Top 5 Open Source Features in Azure Pipelines"},"content":{"rendered":"<p>When I became a Program Manager, I gave up writing software for a living. So I did what many programmers do when faced with such a dilemma: I started working on open source software in my spare time. One of the projects that I work on is called <strong><a href=\"https:\/\/libgit2.org\/\">libgit2<\/a><\/strong>.<\/p>\n<p>You might not have heard of libgit2; despite that, you\u2019ve almost certainly used it. libgit2 is the Git repository management library that powers many graphical Git clients, dozens of tools, and all the major Git hosting providers. Whether you host your code on GitHub, Azure Repos, or somewhere else, it\u2019s libgit2 that merges your pull requests.<\/p>\n<p>This is a big responsibility for a small open source project: keeping our code working and well-tested is critical to making sure that we keep your code working and well-tested. Bugs in <em>our<\/em> code would mean that <em>your<\/em> code doesn\u2019t get merged. Keeping our continuous integration setup efficient and operational is critical to keeping our development velocity high while maintaining confidence in our code.<\/p>\n<p>That\u2019s why libgit2 relies on <a href=\"https:\/\/azure.com\/pipelines\">Azure Pipelines<\/a> for our builds.<\/p>\n<p>Here\u2019s my five favorite things about Azure Pipelines for open source projects. Some of these are unique to Azure Pipelines, some are not, but all of them help me maintain my projects.<\/p>\n<h3>One Service, Every Platform<\/h3>\n<p>libgit2 tries to support many architectures and operating systems, but we have three &#8220;core&#8221; platforms that we want our master branch to always build on: Linux, Windows and macOS. This has always been a challenge for continuous integration build systems.<\/p>\n<p><img decoding=\"async\" style=\"padding: 8px 20px 10px 0\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2019\/01\/linuxmacwin1.png\" alt=\"\" width=\"270\" align=\"left\" \/><\/p>\n<p>The libgit2 project originally did its CI on some Jenkins servers that were donated by GitHub from their internal build farm. The build machine was called &#8220;janky&#8221; and it\u2019s hard to imagine a more appropriate name since we could only get a green checkmark on success or a red X on failure. Since this was an internal build server, open source contributors weren\u2019t authorized to get the full build logs.<\/p>\n<p>Eventually we moved over to Travis so that we could get more insight into build and test runs. This was a big step up, but it was Linux only. Inevitably someone would check in some code that worked great on Linux but called some function that didn\u2019t exist in Win32. So then we added AppVeyor to the mix for our Windows builds, and this also seemed like a big step up.<\/p>\n<p><img decoding=\"async\" style=\"padding: 0 0 20px 20px\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2019\/01\/libgit2platforms11.png\" alt=\"\" width=\"270\" align=\"right\" \/><\/p>\n<p>But it didn\u2019t take long before we realized that having two different systems meant doing more than three times as much work on our infrastructure trying to coordinate the configuration and communication between them. And we were paying two different bills, trying to get the fastest builds that we could afford on donations into our shoestring budget. Over time, our CI configuration became incredibly frustrating and not really what I wanted to be working on in my free time hacking on open source. So when we were finally given the option to standardize on a single build system in Azure Pipelines, we jumped at it.<\/p>\n<p>When we moved over to Azure Pipelines, we got a single source of truth for all our platforms. Linux, Windows and macOS, all hosted in the cloud, all offered in a single service. It simplified everything. There\u2019s one configuration. One output to look at. One set of artifacts produced. One bill at the end of the month. Well, actually, there\u2019s not, because&#8230;<\/p>\n<h3>Unlimited Build Minutes; 10 Parallel Pipelines; Zero charge<\/h3>\n<p>Azure Pipelines has a generous offer for open source projects: unlimited build minutes across 10 parallel build pipelines. All for free.<\/p>\n<p><img decoding=\"async\" style=\"padding: 8px 20px 10px 0\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2019\/01\/libgit2running1.png\" alt=\"\" width=\"270\" align=\"left\" \/><\/p>\n<p>Having 10 concurrent build pipelines is incredible for libgit2, since we want to build on so many different platforms. Although we only have those three \u201ccore\u201d targets that we want to target on every pull request build, there are actually small variances that we want to cover. For example, we want to target both x86 and amd64 architectures on Windows. We want to make sure that we build in gcc, clang, MSVC and mingw. And we want to build with both OpenSSL and mbedTLS.<\/p>\n<p>Ultimately that means that we run <strong>nine<\/strong> builds to validate every pull request. This is actually <em>more<\/em> validation builds than we used to run with our old Travis and AppVeyor, and thanks to all that parallelism it\u2019s much, much faster. We used to get just a few parallel builds running and long queue times, so when many contributors were working on their pull requests, tweaking and responding to feedback, it took an achingly long time to get validation builds done. And we were <em>paying<\/em> for that privilege.<\/p>\n<p>Now we get almost instant start times and all nine builds running in parallel. And it\u2019s free.<\/p>\n<h3>Scheduling Builds<\/h3>\n<p>If you were thinking that running nine builds on every pull request was a lot&#8230; I\u2019m afraid that I have to disagree with you. Those nine builds just cover those core platforms: several Linux builds, a handful of Windows builds, and one for macOS. And those give us a reasonably high confidence in the quality of pull requests and the current state of the master branch.<\/p>\n<p><img decoding=\"async\" style=\"padding: 10px 0 20px 20px\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2019\/01\/libgit2schedule1.png\" alt=\"\" width=\"350\" align=\"right\" \/><\/p>\n<p>But always, we want more. Otherwise you might forget that on ARM platforms, chars are signed by default, unlike most other processors. Or that SPARC is aggressive about enforcing alignment. There are too many crazy little variances in other platforms that are hard to remember, that only show up when you run a build and test pass. So build and test we must, or else we accidentally ship a release that fails on those platforms.<\/p>\n<p>But these platforms are sufficiently uncommon, and their idiosyncrasies mild enough that we don\u2019t need to build every single pull request; it\u2019s sufficient for us to build daily. So every night we queue up another fourteen builds, running on even more platforms, executing the long-running tests, and performing static code analysis.<\/p>\n<p>This setup gives us a good balance between getting a quick result when validating the core platforms all the time, but still making sure we are validating all the platforms daily.<\/p>\n<h3>Publishing Test Results<\/h3>\n<p>When contributors push up a pull request, they often want more than just a simple result telling them whether the build succeeded or failed. When tests fail, especially, it\u2019s good to get more insight into which ones passed and which didn\u2019t.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-47805\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2019\/01\/image1301.png\" alt=\"Tests Failed\" width=\"1100\" height=\"115\" \/><\/p>\n<p>If your test framework outputs a test results file, you can probably upload it to Azure Pipelines, where it can provide you a visualization of your tests. Azure Pipelines supports a bunch of formats: JUnit, NUnit (versions 2 and 3), Visual Studio Test (TRX), and xUnit 2. JUnit, in particular, is very commonly used across multiple build tools and languages.<\/p>\n<p>All you have to do is add an &#8220;upload test results&#8221; task to your pipeline. You can either do that with the visual designer, or <a href=\"https:\/\/github.com\/libgit2\/libgit2\/blob\/826d9a4de88b4b31b21b7fd7fde934b318b24341\/azure-pipelines\/bash.yml#L11-L17\">if you use YAML<\/a>:<\/p>\n<p><code><\/code><\/p>\n<pre>- task: PublishTestResults@2\n  displayName: Publish Test Results\n  condition: succeededOrFailed()\n  inputs:\n    testResultsFiles: 'results_*.xml'\n    searchFolder: '$(Build.BinariesDirectory)'\n    mergeTestResults: true<\/pre>\n<p>&nbsp;<\/p>\n<p>Now when you view a build, you can click on the Tests tab to see the test results. If there are any failures, you can click through to get the details.<\/p>\n<h3>Build Badges<\/h3>\n<p><img decoding=\"async\" style=\"padding: 12px 0 20px 20px\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2019\/01\/image1271.png\" alt=\"\" width=\"300\" align=\"right\" \/><\/p>\n<p>Publishing test results give contributors great visibility into the low-level, nitty-gritty details of the test passes. But users of the project and would-be new contributors want a much higher-level view of the project\u2019s health. They don\u2019t care if the ssh tests are being skipped, they usually care about a much more binary proposition: does it build? Yes or no?<\/p>\n<p>Build badges give a simple view of whether your build pipeline is running or not. And you can set up a different badge for each pipeline. If you have builds set up on maintenance branches, you can show each of them. If you\u2019re running a scheduled or nightly build, you can show a badge for that.<\/p>\n<p><img decoding=\"async\" style=\"padding: 0 0 20px 20px\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2019\/01\/libgit2createbadge1.gif\" alt=\"\" width=\"400\" align=\"right\" \/><\/p>\n<p>It\u2019s simple to add a build badge to your project\u2019s README. In your build pipeline in Azure Pipelines, just click the ellipses (&#8220;&#8230;&#8221;) menu, and select Status Badge. From there, you\u2019ll get the markdown that you can place directly in your README.<\/p>\n<p>Want to tweak it? You can change the label that gets displayed in the build badge. This is especially helpful if you have multiple builds and multiple badges. Just add <code>?label=MyLabel<\/code> to the end of the build badge URL.<\/p>\n<h3>Getting Started<\/h3>\n<p>These five helpful tips will help you use Azure Pipelines to maintain your project. If you\u2019re not using Azure Pipelines yet, it\u2019s easy \u2013 and free \u2013 for open source projects. To get started, just visit <a href=\"https:\/\/azure.com\/pipelines\">https:\/\/azure.com\/pipelines<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I became a Program Manager, I gave up writing software for a living. So I did what many programmers do when faced with such a dilemma: I started working on open source software in my spare time. One of the projects that I work on is called libgit2.<\/p>\n","protected":false},"author":233,"featured_media":52600,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[226],"tags":[],"class_list":["post-52971","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ci"],"acf":[],"blog_post_summary":"<p>When I became a Program Manager, I gave up writing software for a living. So I did what many programmers do when faced with such a dilemma: I started working on open source software in my spare time. One of the projects that I work on is called libgit2.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/52971","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/233"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=52971"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/52971\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/52600"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=52971"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=52971"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=52971"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}