Τρίτη 10 Απριλίου 2018

How to publish a custom task in VSTS

Introduction

In this article we will describe how we can publish a task in VSTS (Visual Studio Team Services) and use it in our build and release definitions. The task can be private (available only in our project) or publicly distributed in VSTS Marketplace.
We have used the process described here
 https://docs.microsoft.com/en-gb/vsts/extend/develop/add-build-task?view=vsts


Goal

We will
  1. Create a powershell script which gets an argument and logs the host computer name. 
  2. Create a task in VSTS that uses this powershell script.
  3. Create a release definition which runs this task and shows on VSTS logging, script's output.
  4. Understand the underlying process.

1. Set up the environment

First of all create an account in VSTS https://www.visualstudio.com/team-services/

Create a publishing account from http://aka.ms/vsmarketplace-manage

 Get a text editor. https://code.visualstudio.com/


 Open powershell as administrator and run the next command
 npm i -g tfx-cli

 2. Create your project

Go to the folder where you keep your projects and create a project with the following structure 


Create empty files inside the folders. We will fill them later.

3. Create your powershell script

Create a simple script like below

param(
    [string]$psargument
)

#######################################################
# Returns computer name
#######################################################

Write-Host "GetComputerName.ps1 started on $env:computername with argument $psargument" -Fore Yellow

It gets one argument and writes computer name and the argument.
Save the script under folder buildAndReleaseTask, together with task.json.

4. Prepare the task.json file

Open task.json and copy paste the following code

{
    "id": "ABD573AF-2246-0FAB-13DC-ABDE3872EFCD",
    "name": "GetComputerName",
    "friendlyName": "Get Computer's Name",
    "description": "This is a simple powershell script which returns computer name",
    "helpMarkDown": "Version 1.0",
    "category": "Utility",
    "visibility": [
        "Build",
        "Release"
    ],
    "author": "Christos Giannoukos",
    "version": {
        "Major": 1,
        "Minor": 0,
        "Patch": 0
    },
    "instanceNameFormat": "Echo $(samplestring)",
    "groups": [
        {
            "name": "advanced",
            "displayName": "Advanced",
            "isExpanded": false
        }
    ],
    "inputs": [
        {
            "name": "psargument",
            "type": "string",
            "label": "PowerShell Argument",
            "defaultValue": "",
            "required": false,
            "helpMarkDown": "a simple argument"
        }
    ],
    "execution": {
        "PowerShell": {
            "target": "$(currentDirectory)\\GetComputerName.ps1",
            "argumentFormat":"",
            "workingDirectory": "$(currentDirectory)"
        }
    }
}


Study carefully this code as it describes the whole project.
First of all, give a proper ID. Follow the above format and change the hexadecimal digits as you like.
Else you are going to get id errors when uploading the extension (see section 7).
Another important section is inputs. Here you have to define the input parameters of your script.
Last, execution describes which script to run. $(currentDirectory) is the directory of the task.json file.
Target points to the file that must be executed.


5. Prepare the extension manifest file

 Open vss-extension.json and copy paste the next code. Change the ids and names


{
    "manifestVersion": 1,
    "id": "get-my-computer-name",
    "name": "GetMyComputerName",
    "version": "1.0.0",
    "publisher": "ChristosGiannoukos",
    "targets": [
        {
            "id": "Microsoft.VisualStudio.Services"
        }
    ],   
    "description": "Tools for building/releasing. Includes one build/release task.",
    "categories": [
        "Build and release"
    ],
    "icons": {
        "default": "images/extension-icon.png"       
    },
    "files": [
        {
            "path": "buildAndReleaseTask"
        }
    ],
    "contributions": [
        {
            "id": "GetComputerName",
            "type": "ms.vss-distributed-task.task",
            "targets": [
                "ms.vss-distributed-task.tasks"
            ],
            "properties": {
                "name": "buildAndReleaseTask"
            }
        }
    ]
}


Be careful for the publisher (5th setting). It must match your name in VS Publisher web page.

6. Packaging the extension

It is time to package the extension and upload it to VSTS
Open powershell, go to extension's directory and run

tfx extension create --manifest-globs vss-extension.json

After a while a *.vsix file will be created under extension's directory. vsix files are zip files which can be opened using tools like winzip or 7zip. Feel free to open it and understand which files it contains.32


7. Upload the extension

Go to your publishing account http://aka.ms/vsmarketplace-manage 
 In the web page you can see all existing published extensions and also your details.

Do you see the red triangle next to your name? This means that you are not registered to publish in VSTS MarketPlace. This extension can be used privately, only inside your VSTS accounts.

Click on New Extension->Visual Studio Team Services.

Select the vsix file and upload it.

Wait for some seconds until the file is verified.

 If you get an error

"Extension validation error
The task.json for contribution buildAndReleaseTask could not be deserialized.Error converting value "xxxxxxxx" to type 'System.Guid'. Path 'id', line 2, position 56."
means that your id has not the correct format. Fix it as described above. 

Another common error is

"Upload Error

Publisher ID 'Christos Giannoukos' provided in the extension manifest should match the publisher ID 'ChristosGiannoukos' under which you are trying to publish this extension."

this means that your name in VS publishing page does not match with the publisher in vss-extension.json


{
"manifestVersion": 1,
"id": "restart-biztalk-host",
"name": "Restart BizTalk Host Instance",
"version": "1.0.1",
"publisher": "ChristosGiannoukos",


change it and retry.

8. Share the extension

Click on the three dots at the right of the extension name and select Share/Unshare

Add the name of your Visual Studio account (without the .visualstudio.com) and press enter.



Go to your Visual Studio account, open the project and go to Manage extensions, top right, where the shopping bag is.


You can see all available extensions. Select the extension

In the next window, click on Get it free and finally install it in the VSTS account you want.

Done! Let's go now and create a simple release definition.

9. Create release definition

In VSTS, go to Releases.

Create an empty Release Definition



Open Environment 1 (or any name given)

In Agent phase select the Agent queue that corresponds to your machine. If you haven't installed an agent yet, click on the gear at the center of the blue menu and then Agent Queues.



click on the + of Agent Phase



By searching, you can find your extension. Add it and configure it. There is no need to write the path as VSTS will put it in the working folder. Fill only the arguments and any additional options.


Save release definition and add new release. Go to the log to see the results.


SUCCESS!!!!!

Understanding the process

When you add a new release, the agent which runs on your machine does among the others, two things:
  1. copies the extension to c:\agent\_work\_tasks\  (default path).
  2. Follows the instructions given inside the task.json file.
If you open the path, you can see your extension's name and id from task.json. Inside it, just under folder with version number, you can find the task.json and the powershell script.