TFS 2017 Release Management:如何显示 Release 下任务的父 PBI

TFS 2017 Release Management: How to display parent PBI for Tasks under Release

有没有办法在TFS2017下的列表中显示Release下的Task Work项的父PBI?

下面的屏幕截图显示了与 Release-3 相关的两个任务。在这里,我希望能够显示它们每个的父 PBI。通过扩展它们或仅通过向父 PBI 显示带有 link 的附加列

感谢您的帮助

编辑: 我知道可以在 TFS 上创建查询。问题是我需要显示与特定版本相关的父工作项的信息,以便用户可以使用它们进行报告。我试图为此目的创建一个查询,但我找不到基于 Release 的过滤选项,所以我认为可能启用一些额外的列或者可能有一个扩展,但我不知道如何去做..

通过扩展实现的步骤:

  1. 获取指定版本以获取构建 ID
  2. 根据构建 ID 获取该构建的工作项
  3. 获取相关工作项

有简单的扩展代码可以获取特定版本的工作项,您可以参考:

HTML:

<!DOCTYPE html>
<html>
<head>
    <title>Custom widget</title>
    <meta charset="utf-8" />
    <script src="node_modules/vss-web-extension-sdk/lib/VSS.SDK.js"></script>
    <script type="text/javascript">
        VSS.init({
            explicitNotifyLoaded: true,
            usePlatformStyles:true
        });
        VSS.require(["TFS/Dashboards/WidgetHelpers", "TFS/TestManagement/RestClient", "TFS/WorkItemTracking/RestClient", "TFS/Build/RestClient", "VSS/Service", "VSS/Identities/Contracts", "VSS/Identities/RestClient", "VSS/Authentication/Services"], function (WidgetHelpers, TFS_Test_WebApi, TFS_Work_WebApi, TFS_Build_Client, VSS_Service, idContracts, idRest, VSS_Auth_Service) {
            WidgetHelpers.IncludeWidgetStyles();
            VSS.register("WidgetStarain", function () {

                 var authHeader = "none";
                var vstsAccount = "none";
                var projectName = "none";
                var releaseRestAPIPrex = "none"
                var getReleaseWorkItems= function (widgetSettings) {
                    var c = VSS.getWebContext();
                    vstsAccount = c.account.name;
                    projectName = c.project.name;
                    releaseRestAPIPrex="https://" + vstsAccount + ".vsrm.visualstudio.com/DefaultCollection/" + projectName + "/_apis/release"
                    VSS.getAccessToken().then(function (token) {

                        authHeader = VSS_Auth_Service.authTokenManager.getAuthorizationHeader(token);

                        $.ajax({
                            type: 'GET',
                            url: releaseRestAPIPrex+'/definitions?api-version=3.0-preview.1',
                            cache: false,
                            dataType: 'json',
                            beforeSend: function (xhr) {
                                xhr.setRequestHeader("Authorization", authHeader);
                            },
                        }).done(function (data) {
                            var v = data.value;
                            $("#releaseDefList").empty();
                            $("#releaseDefList").append('<option value="select">select</option>');
                            $.each(v, function (index, value) {
                                $("#releaseDefList").append('<option value="' + value.id + '">' + value.name + '</option>');
                            });
                        }).error(function (e) {
                            var s = "ss";
                        });

                    });

                };
                $("#releaseDefList").change(function () {
                    var str = "";
                    $("#releaseList").empty();
                    $("#releaseList").append('<option value="select">select</option>');
                    $("#releaseDefList option:selected").each(function () {

                        var releaseDefId = $(this).val();
                        if (releaseDefId != "select") {
                            $.ajax({
                                type: 'GET',
                                url: releaseRestAPIPrex+'/releases?definitionId=' + releaseDefId + '&api-version=3.0-preview.2',
                                cache: false,
                                dataType: 'json',
                                beforeSend: function (xhr) {
                                    xhr.setRequestHeader("Authorization", authHeader);
                                },
                            }).done(function (data) {
                                var v = data.value;

                                $.each(v, function (index, value) {
                                    $("#releaseList").append('<option value="' + value.id + '">' + value.name + '</option>');
                                });
                            }).error(function (e) {
                                var s = "ss";
                            });
                        }

                    });


                });
                $("#releaseList").change(function () {
                    var str = "";

                    $("#releaseList option:selected").each(function () {

                        var releaseId = $(this).val();
                        if (releaseId != "select") {
                            $.ajax({
                                type: 'GET',
                                url: releaseRestAPIPrex+'/release/releases/' + releaseId + '?api-version=3.0-preview.2',                                
                               cache: false,
                                dataType: 'json',
                                beforeSend: function (xhr) {
                                    xhr.setRequestHeader("Authorization", authHeader);
                                },
                            }).done(function (data) {
                                var artifacts = data.artifacts;
                                $.each(artifacts, function (index, value) {
                                    var buildId = value.definitionReference.version.id;

                                    TFS_Build_Client.getClient().getBuildWorkItemsRefs(projectName, buildId).then(function (workitemRefs) {
                                        var workItemIds = new Array();
                                        $.each(workitemRefs, function (index, value) {
                                            workItemIds.push(value.id);
                                        });
                                        var workitemString = "";
                                        TFS_Work_WebApi.getClient().getWorkItems(workItemIds,null,null,"All").then(function (workitems) {
                                            $.each(workitems, function (index, value) {
                                                workitemString += "ID: " + value.id + "; Title: " + value.fields["System.Title"];
                                            });
                                            $("#workitems").text(workitemString);
                                        });

                                    });
                                });

                            }).error(function (e) {
                                var s = "ss";
                            });
                        }

                    });


                });
                 return {
                    load: function (widgetSettings) {
                       getReleaseWorkItems(widgetSettings);
                        return WidgetHelpers.WidgetStatusHelper.Success();
                    }
                }
            });
            VSS.notifyLoadSucceeded();
        });
    </script>
</head>
<body>
    <div class="widget">
        <h2 class="title">widgets starain</h2>  
        <div class="token">none</div>

        <select id="releaseDefList">
            <option id="select">select</option>
        </select>
        <select id="releaseList">
            <option id="select">select</option>
        </select>
        <div id="workitems">
            none workitem
        </div>


    </div>
</body>
</html>

vss-extension.json:

{
  "manifestVersion": 1,
  "id": "sample-extension",
  "version": "0.5.34",
  "name": "My test extension",
  "description": "my test extension description",
  "publisher": "Starain",
  "targets": [
    {
      "id": "Microsoft.VisualStudio.Services"
    }
  ],
  "icons": {
    "default": "Images/logo.png"
  },
  "scopes": [
    "vso.work",
    "vso.build",
    "vso.build_execute",
    "vso.test",
    "vso.test_write",
    "vso.release"
  ],
  "contributions": [
        {
      "id": "WidgetStarain",
      "type": "ms.vss-dashboards-web.widget",
      "targets": [ "ms.vss-dashboards-web.widget-catalog", "Starain.sample-extension.WidgetStarainConfiguration" ],
      "properties": {
        "name": "widget starain",
        "description": "custom widget",
        "catelogIconUrl": "Images/iconProperty.png",
        "previewImageUrl": "Images/iconProperty.png",
        "uri": "WidgetStarain.html",
        "supportedSizes": [
          {
            "rowSpan": 1,
            "columnSpan": 2
          }
        ],
        "supportedScopes": [ "project_team" ]
      }
    } 
  ],
  "files": [
    {
      "path": "node_modules/vss-web-extension-sdk/lib",
      "addressable": true
    },
    {
      "path": "Images",
      "addressable": true
    },
    {
      "path": "Scripts",
      "addressable": true
    },
    {
      "path": "WidgetStarain.html",
      "addressable": true

    }
   ]
}