Writing a ReleaseManagement extension for cloning an existing release definition
Code shared :- https://github.com/openalm/vsts-rm-extensions/tree/master/rd-export-import-clone-TFS2015U2
How to make Changes:-
Step1: Clone the repository using the link https://github.com/openalm/vsts-rm-extensions.git
Step2: Open a command prompt and go till folder 'rd-export-import-clone-TFS2015U2'
Step3: Run 'bower install' [ pre-requsite for running 'bower' can be referred https://github.com/Microsoft/vsts-extension-samples] which will download 1.95.2 version of VSS.SDK.js
Step4: Make your changes
Step5: Run 'tfx extension create' to generate .vsix package in the current directory. [Refer 'Try the extension in Visual Studio Team Services' section https://github.com/Microsoft/vsts-extension-samples]
Step6: Done!!!!
How to add 'Clone' as contextmenu item for ReleaseDefinition
[A generic how to add item in context menu is explained https://www.visualstudio.com/en-us/integrate/extensions/develop/add-action, below steps will explain similarly in context of ReleaseManagement]
Changes required in vss-extension.json [ Refer above shared code ]
Step1: Add below as "scopes" in vss-extension.json [Read more about ReleaseManagement scopes under 'Scopes' section in https://www.visualstudio.com/en-us/integrate/extensions/develop/manifest
"scopes": ["vso.release_execute"]
Step2: As we wanted to add one more item in the release definition context menu hence we will add one contribution (as below) in the vss-extension.json targeting "ms.vss-releaseManagement-web.release-definition-explorer-toolbar-menu" [ to learn more release management contribution point refer https://www.visualstudio.com/integrate/extensions/reference/targets/overview ]
{
"id": "importDefinitionToolbarMenu",
"type": "ms.vss-web.action",
"description": "Import definition(s) menu",
"targets": [
"ms.vss-releaseManagement-web.release-definition-explorer-toolbar-menu"
],
"properties": {
"title": "Import release definition",
"icon": "images/icon-import-16.png",
"group": "actions",
"uri": "main.html"
}
}
===========================
Note:- In case you are calling RM REST API from any contribution point outside RM hub then you may either of two approach :-
Approach1:- Add '"includes": [ "ms.vss-releaseManagement-web.release-service-data-external" ],' as well. Refer the link https://github.com/Microsoft/vss-web-extension-sdk/issues/35
This will cause RM account to be provisioned.
Approach2:- Add
"properties": {
"content": {
"contributionIds": ["ms.vss-releaseManagement-web.release-service-data-external"]
}
Approach2 is the recommended way and will work for VSTS and TFS2018 onwards.
===========================
Changes required in main.js [ Refer method cloneDefinitionContextMenu() in above shared code ]
Step1:- Create a rmClient using
var rmClient = VSS_Service.getCollectionClient(RM_WebApi.ReleaseHttpClient);
Step2: Make a getReleaseDefinition() call to get the definition object for the given id
rmClient.getReleaseDefinition(vsoContext.project.id,sourceItemContext.definition.id)
Step3: Update the definition name
definition.name = newDefinitionName;
Step4: Create a new definition using updated definition object in Step#3 above
rmClient.createReleaseDefinition(definition, vsoContext.project.id)
Step5: Refresh the UI to show the newly created definition
sourceItemContext.view.refresh();
Step6: Done!!!!
Complete code for quick reference :-
var cloneDefinitionContextMenu = (function () {
"use strict";
return {
execute: function (sourceItemContext) {
// Load VSTS controls and REST client
VSS.require(["VSS/Controls", "VSS/Service", "ReleaseManagement/Core/RestClient"],
function (Controls, VSS_Service, RM_WebApi) {
var newDefinitionName = prompt("New definition name:", sourceItemContext.definition.name + " - Copy");
if (newDefinitionName != null)
{
sourceItemContext.view.logMessage("Creating " + newDefinitionName + "...");
var vsoContext = VSS.getWebContext();
// Get a RM client to make REST calls
var rmClient = VSS_Service.getCollectionClient(RM_WebApi.ReleaseHttpClient);
rmClient.getReleaseDefinition(vsoContext.project.id,sourceItemContext.definition.id).then(function(definition){
definition.name = newDefinitionName;
rmClient.createReleaseDefinition(definition, vsoContext.project.id).then(() => {
sourceItemContext.view.refresh();
sourceItemContext.view.logMessage("Cloned \'"+ sourceItemContext.definition.name +"\' and created \'" + newDefinitionName + "\'");
}, function(error){
sourceItemContext.view.logError(error);
});
}, function(error){
sourceItemContext.view.logError(error);
});
}
});
}
}
}());