In this blog you will learn how to extend and improve your Continuous Builds and Deployments using custom Azure DevOps Extensions! Learn how to create and publish an Azure DevOps Extension from scratch, and learn how to use custom tasks and scripts to extend and add new functionality to your pipelines!
By the end of this article, you will be able to setup a basic Azure DevOps extension yourself, containing a basic task that you can execute in your Build- and Release pipelines, and upload it to the Visual Studio Marketplace!
What is/are Azure Pipelines?
Azure Pipelines are the Continuous Integration & Deployment services offered by Azure as part of the Azure DevOps Services. Or, in more basic terminology, Azure Pipelines allows you to build, test, and deploy your projects to the platforms of your choosing. Whether it's Node.js, Python, Java, PHP, Ruby, C/C++, .NET, Android, and/or iOS apps, and whether you're into Linux, macOS, or Windows, Azure has you covered!
In the picture below, you can see the general Azure DevOps hosting and working scheme flow for pipelines.
Attachment 1. An overview of the Azure Services for Pipelines
Our focus for today will be to explain and setup the extension's File & Folder structure, and the tools required to turn the project we'll be setting into an extension to extend the Build, Test and/or Publish functionality in the Pipeline (CI) section of the Azure Services!
Creating your First Extension
Let's start off by creating a new folder to house our new extension! In this folder, we'll be creating a couple of key files that make up the anatomy of an Azure DevOps extension. These files are:
- The manifest file (vss-extension.json), the primary definition of our extension.
- The task manifest file(s) (task.json), the definitions of our tasks, which scripts to execute and which task input parameters should be displayed.
- The task script file(s) (.ps1/.js), the scripts that are executed as configured in the task.json.
- The task modules (for example, the VstsTaskSdk module)
- An icon for our extension! (.png)
The picture below showcases the folders and file structure of our demo extension.
Attachment 2. Stucturing your Azure DevOps Extension
Let's shortly explain the structure of the picture above.
Extension manifest file (vss-extension.json)
The vss-extension.json is the basis for your extension. It's describes the most important values that are used to define your extension, and what files the extension contains. This includes the extension's version, name, publisher, icon, tasks, etc.)
The Task Folder
In the extension we're setting up, we'll be splitting separate tasks into their own respective folder. The folder naming is up to you, but in this case we'll be using the name 'buildTask'. An extension can contain an infinite number of subtasks. The tasks are the part of the extension that are integrated into the pipeline, and that will execute a specific script. Each of our tasks will contain the following files:
- The task.json manifest, which describes the task, which input parameters it should have, which script to execute, the friendly name of the task, etc.
- The powershell.ps1 script, the script that will be executed when the task is run.
- The icon.png, a pretty image to make your task recognizable!
- The ps_modules folder, where we will store our modules that we use in our powershell.ps1 script! This can for example be the VstsTaskSdk that we can use to read/insert input parameters from Azure DevOps, into our script!
The extension icon
A pretty icon to make your extension recognizable, both for you and in the Marketplace if you decide to make your extension public!
The Extension Manifest File
Let's start by filling in our manifest file! In the snippet below you can see the vss-extension.json file, which I have filled in all the properties needed to structure the extension we're setting up! You can simply copy-paste the contents into your own vss-extension.json file, and replace the id, name, version, publisher, description, and the files/contributions to match the extension you wish to create! Or leave it as-is if you wish to follow me allong!
Creating your First Task
Let's head over to our first task! Before we can start developing the actual script that we want to execute in our pipelines, we will have to setup our task.json first! Like the extension manifest, you can copy-paste and change file I've published down below, or leave it as-is if you wish to follow me along!
Everything up to the Groups section defines the outside information of the task. This includes an Id (an unique Guid), the friendlyName and instanceNameFormat, the task's description, it's author, and the versioning you want this task to have! You can change these to whatever you like, just be sure to generate a new Guid to use as the task's ID.
Groups are used to, as the name would suggest, group input parameters. We will be defining several 'input types' as parameters that we can enter in our Azure DevOps pipelines, and keep them all sorted by using groups. This is mostly useful when you have several inputs with more than one key feature in your task, to make it more user friendly!
Under the Inputs section we define which parameters we can accept in our task. In this case we will be simply using a string input (single line). For more information on which input types are accepted, refer to this article on StackOverflow. A couple of important keys to set while defining your inputs are:
- name, to access the input value programmatically
- type, to define what type of input it should be
- label, the text that shows what the input type is used for
- required, a boolean whether the field has to be filled in or not.
- helpMarkdown, incase the label isn't enough of a descriptor allows you to fill in more information
- groupName, the name of the Group in which this input should be added to.
Under execution we define what our tasks should run when it is executed! In this case, we are defining that it should run our powershell.ps1 file using Powershell3, under the Windows operating system, in our current working directory!
Building your Extension
We've finished setting up our extension! Now all we need to do is actually turn it into a package, and upload it to the Visual Studio Marketplace!
To turn our project into a package that which we can upload, we will be using Node.Js!
Before we get started, we'll need to install the tool that builds the extension. Because VSS Web Extensions SDK require TFX, we'll need to install the CLI tool for it using the following command:
'npm install -g tfx-cli'
Once successfully installed, we can use it to turn our project into a package! Do this by running the followin command in our extension directory:
'npx tfx-cli extension create'
When it's completed, you see a message indicating your extension has been successfully packaged:
We're now ready to publish this extension!
Publishing your Extension
Let's head over to the Visual Studio Marketplace so that we can publish our extension!
First thing we need to do is create a publisher to which we can publish our extension! Click on "Create Publisher" on the left hand side, where we'll be able to enter our basic information like an unique name & id for our publisher, a logo, description, and our company name.
Important: The ID of the publisher has to match with the name of the publisher we entered in our extension's manifest file!
Now that we've created our publisher, we can upload our extension! Select the publisher we've just created on the left hand side, and then under the "+ New Extension" dropdown, select Azure DevOps. Here you will be able to upload the package file we've generated in the previous chapter!
🎉 Congratulations, you've successfully created & published your first Azure DevOps extensions! 🔥
The article shows the process of creating an extension for private usage – it doesn’t require validation from Microsoft. It allows you to quickly organize, set up, and use pipelines for your CI process in a seamless manner.
If you want to make the extension publicly available, you will need to contact Microsoft and go through the validation process.
If you have any further questions and or issues with the instructions in this article, please contact me using the information found here!
Sources used in this article:
Visual Studio Market Place, https://marketplace.visualstudio.com/
Vitalii Zaichenko on Coding Insight, https://codingsight.com/developing-azure-devops-extension/