{"id":7875,"date":"2017-04-14T19:51:00","date_gmt":"2017-04-14T19:51:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/premier_developer\/?p=7875"},"modified":"2019-03-05T15:16:52","modified_gmt":"2019-03-05T22:16:52","slug":"documentation-in-a-devops-world","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/premier-developer\/documentation-in-a-devops-world\/","title":{"rendered":"Documentation in a DevOps World"},"content":{"rendered":"<p>In this post, Application Development Manager, <strong>Chris Mason<\/strong> discusses the challenge of keeping documentation up to date in this fast moving DevOps world.\u00a0 In addition, he spotlights DocFX and writes a build task extension which integrates it into your build pipeline.<\/p>\n<hr \/>\n<h3>Overview<\/h3>\n<p>We talk a lot about DevOps today and it represents a major strategy and focus for our developer platforms with Visual Studio Team Services (VSTS) and Team Foundation Server (TFS). There are plenty of examples out there covering various aspects of application deployments in a DevOps world: deploying apps, database migrations, and coded infrastructure. However, one area that seems to escape coverage is&#8211; <strong><em>documentation<\/em><\/strong>.<\/p>\n<p>If we are deploying apps on a \u201ccloud cadence\u201d then we can expect new features to be rolling out to users every few weeks. When a user sees a new button, a new option, or a new color code in an app, they are going to want to know what it does. This means we need a rapid cadence to build and deploy new documentation so that when any new feature rolls out to the user, they can go and quickly find supporting information for it.<\/p>\n<p>This idea is not earthshattering or new. Dynamic documentation generation has been around for ages, for example, the old <a href=\"https:\/\/sandcastle.codeplex.com\/\">Sandcastle<\/a> project. While great for generating API level documentation for developers to look at, it is not necessarily the most user friendly result when done.<\/p>\n<h3>DocFx<\/h3>\n<p>Another option that is available today is the open-source option called <a href=\"http:\/\/dotnet.github.io\/docfx\/\">DocFx<\/a> which is developed and maintained by the .NET team. DocFx is the underlying technology behind the newly redesigned <a href=\"https:\/\/docs.microsoft.com\">docs.microsoft.com<\/a> which represents a clean, modern way we are presenting documentation on sites going forward. We have already migrated documentation for several products including Azure and .NET Core onto the new platform and more are actively in transition.<\/p>\n<p>DocFx is similar to other platforms like <a href=\"https:\/\/jekyllrb.com\/\">Jekyll<\/a> or <a href=\"https:\/\/readthedocs.com\/\">ReadTheDocs<\/a> where you write the content in Markdown, provide some high level template structure to your site, run the tool of choice and out comes a site with fully rendered html, CSS, and required JavaScript. In addition to supporting Markdown files, DocFx can also process Swagger json files, as well as managed code objects.<\/p>\n<h3>Introducing DocFx Build Task<\/h3>\n<p>DocFx gives us a lot of power to create great documentation for our product, but I wanted a way to be able to put that into a continuous integration \/ continuous delivery pipeline. My original approach to this problem was to create a build pipeline in VSTS that would download and install something like Chocolately, use Chocolately to grab the latest DocFx package, then run a command line build task that would invoke DocFx against our project. Unfortunately, that solution did not pan out as I had hoped and ended up being a bit messy overall.<\/p>\n<p>So, I wrote a <a href=\"https:\/\/www.visualstudio.com\/en-us\/docs\/integrate\/extensions\/develop\/add-build-task\">VSTS build task extension<\/a>! My extension is called <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=chrismason.vsts-docfxtasks\">DocFx Build Tasks<\/a> and it aims provide an easy way to integrate DocFx into your build pipeline so you can generate content that can later be pushed out through a release pipeline. The agent is in a first release, so try it out, give me feedback and let me know if you feel anything that is missing.<\/p>\n<h3>Example Walkthrough<\/h3>\n<p>We can now try this extension out and see what kind of workflow we might be able to get working. For my example project, I started with the <a href=\"https:\/\/github.com\/docascode\/docfx-seed\">DocFx seed project<\/a>. I created a new Git repository in VSTS and pushed this code base into there. No other changes were made to the seed project.<\/p>\n<h4>Install the Extension<\/h4>\n<p>Open the extension from the <a href=\"https:\/\/marketplace.visualstudio.com\/items?itemName=chrismason.vsts-docfxtasks\">VSTS Marketplace<\/a>. For VSTS click \u201cInstall\u201d for TFS click \u201cDownload\u201d<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35802\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/docfx.jpg\" alt=\"\" width=\"644\" height=\"225\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/docfx.jpg 644w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/docfx-300x105.jpg 300w\" sizes=\"(max-width: 644px) 100vw, 644px\" \/><\/p>\n<p>Follow the instructions to complete the installation of the extension (in my case, I am using VSTS and that is how I will refer to it from now on).<\/p>\n<h4>Configure Build<\/h4>\n<p>Navigate to the \u201cBuild\u201d hub within VSTS. Click \u201c+ New\u201d to create a new build.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image0041.png\"><img decoding=\"async\" style=\"padding-top: 0px; padding-left: 0px; padding-right: 0px; border-width: 0px;\" title=\"clip_image004\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image004_thumb1.png\" alt=\"clip_image004\" width=\"644\" height=\"91\" border=\"0\" \/><\/a><\/p>\n<p>You can select whichever template you would like as we are going to ultimately reconfigure it anyways.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35804\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/template.png\" alt=\"\" width=\"644\" height=\"253\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/template.png 644w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/template-300x118.png 300w\" sizes=\"(max-width: 644px) 100vw, 644px\" \/><\/p>\n<p>Assuming you pick \u201cVisual Studio\u201d, you end up with the following setup.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35805\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/template2.png\" alt=\"\" width=\"516\" height=\"484\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/template2.png 516w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/template2-300x281.png 300w\" sizes=\"(max-width: 516px) 100vw, 516px\" \/><\/p>\n<p>Remove every existing task within the setup. Click \u201c+ Add Task\u201d and add the following two tasks:<\/p>\n<p>\u00b7 Create DocFx Documentation<\/p>\n<p>\u00b7 Copy and Publish Build Artifacts<\/p>\n<p>Your pipeline should look like the following:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image010.png\"><img decoding=\"async\" style=\"padding-top: 0px; padding-left: 0px; padding-right: 0px; border-width: 0px;\" title=\"clip_image010\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image010_thumb.png\" alt=\"clip_image010\" width=\"644\" height=\"380\" border=\"0\" \/><\/a><\/p>\n<p>For the Create DocFx Documentation step, in most cases, you only need to provide a path to the docfx.json file in your source control.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image0121.png\"><img decoding=\"async\" style=\"padding-top: 0px; padding-left: 0px; padding-right: 0px; border-width: 0px;\" title=\"clip_image012\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image012_thumb1.png\" alt=\"clip_image012\" width=\"1028\" height=\"352\" border=\"0\" \/><\/a><\/p>\n<p>If you need to override how DocFx is invoked, you can specify those options as well. We are going to want to publish our generated content to a web site ultimately so we will need to configure the copy and publish build artifacts.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image0141.png\"><img decoding=\"async\" style=\"padding-top: 0px; padding-left: 0px; padding-right: 0px; border-width: 0px;\" title=\"clip_image014\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/31\/2019\/04\/clip_image014_thumb1.png\" alt=\"clip_image014\" width=\"1028\" height=\"531\" border=\"0\" \/><\/a><\/p>\n<p>Save and queue the build and your site should be generated within a few minutes and published as an artifact from our build.<\/p>\n<h4>Deploy to a Web App<\/h4>\n<p>In my example, I am using an Azure Web App to deploy my site\u2019s content to. I went to the Azure portal, created a new web app and then <a href=\"https:\/\/docs.microsoft.com\/en-us\/azure\/app-service-web\/app-service-deployment-credentials\">reset the credentials<\/a> to support ftp deployment.<\/p>\n<p>Back in VSTS, I navigate to the \u201cRelease\u201d hub and click the \u201c+\u201d to create a new release.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35806\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/releases.png\" alt=\"\" width=\"644\" height=\"306\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/releases.png 644w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/releases-300x143.png 300w\" sizes=\"(max-width: 644px) 100vw, 644px\" \/><\/p>\n<p>I started with an Empty release definition for this example.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35807\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/deploy.png\" alt=\"\" width=\"1028\" height=\"319\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/deploy.png 1028w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/deploy-300x93.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/deploy-768x238.png 768w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/deploy-1024x318.png 1024w\" sizes=\"(max-width: 1028px) 100vw, 1028px\" \/><\/p>\n<p>Click \u201cNext,\u201d select the name of the build definition you created in the previous step, you can choose if you want it to implement continuous deployment or not, and I left mine as the \u201cHosted\u201d build queue. Click \u201cCreate.\u201d<\/p>\n<p>In your new release definition, setup your environments. This can follow whatever flow makes sense for your requirements but an example flow could be something like Draft -&gt; QA -&gt; Live. Select an environment and add a single task:<\/p>\n<p>\u00b7 FTP Upload<\/p>\n<p>For Authentication Method, I used FTP Service Endpoint. This allows me to create a generic service endpoint based on the reset FTP credentials of the site I setup. Once I create that service endpoint, I can reference that within the task. Select the source folder to the artifacts folder you previously built. The remote directory for an Azure web app would be \/site\/wwwroot.<\/p>\n<p>A couple notes, in the Advanced section, you want to make sure you enable \u201cOverwrite\u201d as well as \u201cPreserve file paths.\u201d Without the second option, everything would be copied to a flat file format which would cause the site to not render correctly. The full release task is shown below:<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35808\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ftp.png\" alt=\"\" width=\"1028\" height=\"546\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ftp.png 1028w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ftp-300x159.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ftp-768x408.png 768w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/ftp-1024x544.png 1024w\" sizes=\"(max-width: 1028px) 100vw, 1028px\" \/><\/p>\n<p>Save and start a new release and in about a minute, you should have your newly generated CI\/CD DevOps friendly documentation site.<\/p>\n<p><img decoding=\"async\" class=\"alignnone size-full wp-image-35809\" src=\"http:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/seed.png\" alt=\"\" width=\"1028\" height=\"739\" srcset=\"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/seed.png 1028w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/seed-300x216.png 300w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/seed-768x552.png 768w, https:\/\/devblogs.microsoft.com\/premier-developer\/wp-content\/uploads\/sites\/31\/2017\/04\/seed-1024x736.png 1024w\" sizes=\"(max-width: 1028px) 100vw, 1028px\" \/><\/p>\n<p><i>We have seen in this example how we can now incorporate documentation writing as part of a DevOps mindset. Connecting written content to a continuous delivery pipeline provides an opportunity for end customers to ensure they are up to date on the latest and greatest details about your product. As far as the extension shown here is concerned, this is its first release and I would love to hear how it works for you or if there are any suggestions for improvement.<\/i><\/p>\n<hr \/>\n<p><strong><a href=\"https:\/\/devblogs.microsoft.com\/premier-developer\/welcome-to-premier-developer\/\">Premier Support for Developers<\/a><\/strong> provides strategic technology guidance, critical support coverage, and a range of essential services to help teams optimize development lifecycles and improve software quality.\u00a0 Contact your Application Development Manager (ADM) or <a href=\"https:\/\/blogs.msdn.microsoft.com\/premier_developer\/contact-us\/\">email us<\/a> to learn more about what we can do for you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post, Application Development Manager, Chris Mason discusses the challenge of keeping documentation up to date in this fast moving DevOps world.\u00a0 In addition, he spotlights DocFX and writes a build task extension which integrates it into your build pipeline. Overview We talk a lot about DevOps today and it represents a major strategy [&hellip;]<\/p>\n","protected":false},"author":582,"featured_media":37840,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[35,22],"tags":[21,205,3],"class_list":["post-7875","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-alm","category-devops","tag-devops","tag-documentation","tag-team"],"acf":[],"blog_post_summary":"<p>In this post, Application Development Manager, Chris Mason discusses the challenge of keeping documentation up to date in this fast moving DevOps world.\u00a0 In addition, he spotlights DocFX and writes a build task extension which integrates it into your build pipeline. Overview We talk a lot about DevOps today and it represents a major strategy [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/7875","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/users\/582"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/comments?post=7875"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/posts\/7875\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media\/37840"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/media?parent=7875"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/categories?post=7875"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/premier-developer\/wp-json\/wp\/v2\/tags?post=7875"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}