{"id":34285,"date":"2017-07-17T05:57:00","date_gmt":"2017-07-17T05:57:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/devops\/?p=34285"},"modified":"2019-02-14T15:51:29","modified_gmt":"2019-02-14T23:51:29","slug":"fastest-path-new-team-services-extension","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/fastest-path-new-team-services-extension\/","title":{"rendered":"The fastest path to a new VSTS extension"},"content":{"rendered":"<p>Over the last few years we have introduced a number of ways to extend and integrate with Visual Studio Team Services (VSTS) and Team Foundation Server (TFS). For example, client libraries for <a href=\"https:\/\/www.visualstudio.com\/docs\/integrate\/get-started\/client-libraries\/dotnet\">.NET<\/a>\u00a0(which work with both .NET Framework and .NET Core apps)\u00a0and for\u00a0<a href=\"https:\/\/github.com\/Microsoft\/vsts-node-api\">Node.js<\/a>\u00a0and\u00a0an extensibility model that allows extension of our web experience.\u00a0The possibilities for developers wanting to integrate with or extend VSTS are almost endless.<\/p>\n<p>But with all of these great options, there is a challenge of knowing what pieces you need to get started and then assembling them in the right way. We have made a lot of improvements to our <a href=\"http:\/\/integrate.visualstudio.com\/\">integration docs<\/a>\u00a0and are planning another wave of improvements to our docs soon, but sometimes you need more than docs.<\/p>\n<p><strong>Sometimes you just need to start with code that you know is structured correctly and already does something real.<\/strong><\/p>\n<p>This post, which is the first in a series, covers a relatively new tool for jumpstarting development of a new extension.<\/p>\n<h2><strong>About the generator for VSTS extensions<\/strong><\/h2>\n<p>The Visual Studio ALM Rangers group recently released a <a href=\"http:\/\/yeoman.io\/\">Yeoman <\/a>generator that lays down all the files needed for a new VSTS extension. After you tell Yeoman which generator you want to use and answer a few questions, it <strong>lays down all the necessary files for you and structures them in the right way<\/strong>.<\/p>\n<p>Structuring an extension&#8217;s files can be tricky, especially when you throw in other technologies like TypeScript and NPM. With this generator you\u00a0get a new extension that is structured correctly\u00a0and contributes one of the following:<\/p>\n<ul>\n<li>A project-level <a href=\"https:\/\/www.visualstudio.com\/docs\/integrate\/extensions\/reference\/targets\/overview#hubs-and-hub-groups\">web hub<\/a> or action<\/li>\n<li>A <a href=\"https:\/\/www.visualstudio.com\/docs\/integrate\/extensions\/develop\/add-build-task\">task <\/a>that can be used in a build or release<\/li>\n<li>A <a href=\"https:\/\/www.visualstudio.com\/docs\/integrate\/extensions\/develop\/add-dashboard-widget\">widget <\/a>that can be added to a dashboard<\/li>\n<li>A service hooks consumer service that makes it easy for customers to send events to your service<\/li>\n<\/ul>\n<p>The generator takes the guess work out of correctly structuring a new extension. It also avoids that repetitive process of cobbling together the various files needed before you even write your first line of code.<\/p>\n<h2>Using the generator<\/h2>\n<p><strong>Install the pre-reqs:<\/strong><\/p>\n<ol>\n<li><a href=\"https:\/\/nodejs.org\/\">Install Node.js<\/a>. This is needed for Yeoman and the tools used to build and package your extension.<\/li>\n<li>Install Yeoman by running <code>npm install -g yo<\/code> from a command prompt<\/li>\n<li>Install the generator for VSTS extensions by running <code>npm install -g generator-team-services-extension<\/code><\/li>\n<\/ol>\n<p><strong>For each new extension you want to create:<\/strong><\/p>\n<ol>\n<li>Run <code>yo team-services-extension<\/code><\/li>\n<li>Select the type of extension you want to create:\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2017\/07\/yo-start-1024x667.png\" alt=\"\" width=\"840\" height=\"547\" class=\"alignnone size-large wp-image-34295\" \/><\/li>\n<li>Answer the questions when prompted\n<img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2017\/07\/yo-1-1024x287.png\" alt=\"\" width=\"840\" height=\"235\" class=\"alignnone size-large wp-image-34305\" \/><\/li>\n<\/ol>\n<p>After the generator completes, you will have a new folder populated with the necessary files for your new extension. For web-based extensions, the generator creates the following configuration files for you:<\/p>\n<ul>\n<li>TypeScript project (tsconfig.json)<\/li>\n<li>NPM package file (package.json). This pulls in dependencies like TypeScript and VSS Web Extension SDK and adds helpful scripts to build and package your new extension.<\/li>\n<li>Webpack configuration (webpack.config.js). Webpack analyzes your scripts and dependencies and packages just the parts into a single file.<\/li>\n<\/ul>\n<p>To try out the new extension, you need to publish it to the Visual Studio Marketplace. For the full steps, see <a href=\"https:\/\/www.visualstudio.com\/docs\/integrate\/extensions\/publish\/overview\">Package and publish extensions<\/a>. The abbreviated steps are:<\/p>\n<ol>\n<li>Publish your extension to the Marketplace. <strong>Note:<\/strong> You can do this from the command line by running <code>npm run gallery-publish -- --token xxxxx<\/code> where xxxxx is a personal access token.<\/li>\n<li>Share your extension with your VSTS account<\/li>\n<li>Install the extension to this account<\/li>\n<li>Navigate your web browser to your account<\/li>\n<\/ol>\n<p>In the example above, I created an extension that contributed a hub to the project-level Code hub group:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2017\/07\/yo-newhub-1024x452.png\" alt=\"\" width=\"840\" height=\"371\" class=\"alignnone size-large wp-image-34306\" \/><\/p>\n<p>To learn more about this tool, visit the <a href=\"https:\/\/github.com\/ALM-Rangers\/generator-team-services-extension\">ALM-Rangers\/generator-team-services-extension<\/a> repo on GitHub.<\/p>\n<p>Stay tuned for other posts in this series, including one on jumpstarting your .NET app\/service integration with <a href=\"https:\/\/github.com\/Microsoft\/vsts-dotnet-samples\">client library code samples<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Over the last few years we have introduced a number of ways to extend and integrate with Visual Studio Team Services (VSTS) and Team Foundation Server (TFS). For example, client libraries for .NET\u00a0(which work with both .NET Framework and .NET Core apps)\u00a0and for\u00a0Node.js\u00a0and\u00a0an extensibility model that allows extension of our web experience.\u00a0The possibilities for developers [&hellip;]<\/p>\n","protected":false},"author":144,"featured_media":45953,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-34285","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops"],"acf":[],"blog_post_summary":"<p>Over the last few years we have introduced a number of ways to extend and integrate with Visual Studio Team Services (VSTS) and Team Foundation Server (TFS). For example, client libraries for .NET\u00a0(which work with both .NET Framework and .NET Core apps)\u00a0and for\u00a0Node.js\u00a0and\u00a0an extensibility model that allows extension of our web experience.\u00a0The possibilities for developers [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/34285","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\/144"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=34285"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/34285\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/45953"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=34285"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=34285"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=34285"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}