1

I wrote some PowerShell functions to help me create user stories a bit faster, and this all works great, but now I am stuck figuring out how to create Tasks for a User Story/Work Item, and obviously having them be assigned to a specific Work Item.

I also can't find any documentation describing this. I almost imagine that I need use the uri "https://dev.azure.com/$($Organisation)/$Project/_apis/wit/workitems/`$Task?api-version=5.1" but I can't see how to associate it with a work item as part of this, or after.

Can anyone help or point me at some actual documentation for this, please?

Edit: While looking for something else, I stumbled across this, but sadly that errors out for me, so it might be deprecated by now...

Edit; Thanks for the help everyone. This now works for me This is my code in case it becomes useful for someone some day in the future:

#96116 is the parent work item, 96113 the child task
$ContentType = "application/json-patch+json"
$Token = System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($PersonalAccessToken)"))
$Header = @{Authorization = 'Basic ' + $Token;accept=$ContentType}
$uri = "https://dev.azure.com/$Organisation/$Project/_apis/wit/workitems/96113?api-version=6.1-preview.3"
$body= @'
[
  {
    "op": "add",
    "path": "/relations/-",
    "value": {
      "rel": "System.LinkTypes.Hierarchy-Reverse",
      "url": "https://dev.azure.com/$Organisation/$Project/_apis/wit/workitems/96113",
      "attributes": {
          "isLocked": false,
          "name": "Parent"
      }
    }
  }
]
'@
Invoke-RestMethod -Uri $uri -Method PATCH -Headers $Header -Body $Body -ContentType $contentType
Lars Panzerbjrn
  • 196
  • 3
  • 12
  • 1
    We have a project that does a lot with Work Items. Including adding relations. The trick is to create a batch update and add a patch operation to the create: https://github.com/tfsaggregator/aggregator-cli/tree/master/src/aggregator-ruleng. See: https://github.com/tfsaggregator/aggregator-cli/blob/master/src/aggregator-ruleng/WorkItemRelationWrapperCollection.cs https://github.com/tfsaggregator/aggregator-cli/blob/master/src/aggregator-ruleng/WorkItemWrapper.cs – jessehouwing Jan 18 '21 at 14:41
  • See also: https://github.com/redarrowlabs/vsts-restapi-samplecode/blob/master/VSTSRestApiSamples/WorkItemTracking/Batch.cs https://learn.microsoft.com/en-us/rest/api/vsts/wit/workitembatchupdate?view=vsts-rest-4.1 – jessehouwing Jan 18 '21 at 15:18
  • Thanks for your comments, but this appears to be in C#, which I don't really know well enough to figure out which parts are to do with tasks in Azure DevOps, but thanks for trying to help. – Lars Panzerbjrn Jan 18 '21 at 20:42
  • I extracted the main gist of it in an answer below and linked to the orphaned docs link. – jessehouwing Jan 19 '21 at 09:53
  • Hi @LarsPanzerbjrn, how are things going? Have you tried the suggestion in my answer? Is it helpful to you? Please have a try with it, and any progress, feel free to tell me. – Bright Ran-MSFT Jan 20 '21 at 07:07

3 Answers3

4

You can follow the steps below to create a new Task, and link a specified User Story as the Parent of this new Task:

  1. Use the endpoint "Work Items - Create" to create the new Task.

  2. Use the endpoint "Work Items - Update" to link the specified User Story as the Parent.

    • Request URI
      PATCH https://dev.azure.com/{organization}/{project}/_apis/wit/workitems/{id}?api-version=6.1-preview.3
      
    • Required Header
      Content-Type: application/json-patch+json
      
    • Request Body
      [
        {
          "op": "add",
          "path": "/relations/-",
          "value": {
            "rel": "System.LinkTypes.Hierarchy-Reverse",
            // This is the URL of the linked parent work item.
            "url": "https://dev.azure.com/{organization}/{project}/_apis/wit/workItems/{parent work item ID}",
            "attributes": {
                "isLocked": false,
                "name": "Parent"
            }
          }
        }
      ]
      

I have tested this method, it can work fine as expected.

Bright Ran-MSFT
  • 5,190
  • 1
  • 5
  • 12
2

As mentioned above, adding a relation can be done after creation with a separate PATCH request, but you can also combine multiple Work Item Tracking requests in a single call. You need to POST to the batch endpoint and send an array of JsonPatchDocuments:

PATCH https://dev.azure.com/{organization}/{project}/_apis/wit/$batch?api-version=2.2
"Content-Type": "application/json"
"Accept": "application/json"
"Authorization": "Basic {PAT}"

[
    {
         "method": "PATCH",
         // Replace $Task below with the WIT you want to create
         "uri": "/{Project}/_apis/wit/workitems/$Task?api-version=2.2",
         "headers": { "Content-Type": "application/json-patch+json" },
         "body": [
              { "op": "add", "path": "/fields/System.Title", "value": "Customer can sign in using their Microsoft Account" },

              // Indicates new work item instead of an update. Each new work item uses a unique negative number in the batch.
              { "op": "add", "path": "/id", "value": "-1" }, 

              {
                  "op": "add",
                  "path": "/relations/-",
                  "value": {
                      "rel": "System.LinkTypes.Hierarchy-Reverse",
                      "url": "https://dev.azure.com/{organization}/{project}_apis/wit/workitems/{work item id to link to}"
                  }
              }
          ]
     }
]

With this API you can also create a tree of work items in a single call. You use the negative IDs to link workitems together and they ge translated to their real work item ids as the batch is executed.

Docsr for the batch API are here:

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
0

It looks like Microsoft has documentation for creating, deleting, and updating work items.

Your guess was close. Here's the provided example:

Request

POST https://dev.azure.com/fabrikam/{project}/_apis/wit/workitems/${type}?api-version=6.1-preview.3

Body

[
  {
    "op": "add",
    "path": "/fields/System.Title",
    "from": null,
    "value": "Sample task"
  }
]

Response

{
  "id": 131489,
  "rev": 1,
  "fields": {
    "System.AreaPath": "CustomProcessPrj",
    "System.TeamProject": "CustomProcessPrj",
    "System.IterationPath": "CustomProcessPrj",
    "System.WorkItemType": "Task",
    "System.State": "New",
    "System.Reason": "New",
    "System.CreatedDate": "2017-10-06T01:04:51.57Z",
    "System.CreatedBy": {
      "displayName": "Jamal Hartnett",
      "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/d291b0c4-a05c-4ea6-8df1-4b41d5f39eff",
      "_links": {
        "avatar": {
          "href": "https://dev.azure.com/mseng/_apis/GraphProfile/MemberAvatars/aad.YTkzODFkODYtNTYxYS03ZDdiLWJjM2QtZDUzMjllMjM5OTAz"
        }
      },
      "id": "d291b0c4-a05c-4ea6-8df1-4b41d5f39eff",
      "uniqueName": "fabrikamfiber4@hotmail.com",
      "imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=d291b0c4-a05c-4ea6-8df1-4b41d5f39eff",
      "descriptor": "aad.YTkzODFkODYtNTYxYS03ZDdiLWJjM2QtZDUzMjllMjM5OTAz"
    },
    "System.ChangedDate": "2017-10-06T01:04:51.57Z",
    "System.ChangedBy": {
      "displayName": "Jamal Hartnett",
      "url": "https://vssps.dev.azure.com/fabrikam/_apis/Identities/d291b0c4-a05c-4ea6-8df1-4b41d5f39eff",
      "_links": {
        "avatar": {
          "href": "https://dev.azure.com/mseng/_apis/GraphProfile/MemberAvatars/aad.YTkzODFkODYtNTYxYS03ZDdiLWJjM2QtZDUzMjllMjM5OTAz"
        }
      },
      "id": "d291b0c4-a05c-4ea6-8df1-4b41d5f39eff",
      "uniqueName": "fabrikamfiber4@hotmail.com",
      "imageUrl": "https://dev.azure.com/fabrikam/_api/_common/identityImage?id=d291b0c4-a05c-4ea6-8df1-4b41d5f39eff",
      "descriptor": "aad.YTkzODFkODYtNTYxYS03ZDdiLWJjM2QtZDUzMjllMjM5OTAz"
    },
    "System.Title": "Sample task",
    "Microsoft.VSTS.Common.StateChangeDate": "2017-10-06T01:04:51.57Z",
    "Microsoft.VSTS.Common.Priority": 2
  },
  "_links": {
    "self": {
      "href": "https://dev.azure.com/fabrikam/_apis/wit/workItems/131489"
    },
    "workItemUpdates": {
      "href": "https://dev.azure.com/fabrikam/_apis/wit/workItems/131489/updates"
    },
    "workItemRevisions": {
      "href": "https://dev.azure.com/fabrikam/_apis/wit/workItems/131489/revisions"
    },
    "workItemHistory": {
      "href": "https://dev.azure.com/fabrikam/_apis/wit/workItems/131489/history"
    },
    "html": {
      "href": "https://dev.azure.com/fabrikam/web/wi.aspx?pcguid=20cda608-32f0-4e6e-9b7c-8def7b38d15a&id=131489"
    },
    "workItemType": {
      "href": "https://dev.azure.com/fabrikam/aaee31d9-14cf-48b9-a92b-3f1446c13f80/_apis/wit/workItemTypes/Task"
    },
    "fields": {
      "href": "https://dev.azure.com/fabrikam/_apis/wit/fields"
    }
  },
  "url": "https://dev.azure.com/fabrikam/_apis/wit/workItems/131489"
}
D M
  • 5,769
  • 4
  • 12
  • 27
  • Hi, thanks for the extensive answer. I don't see how that associate a task I create with a work item though(?)... Those pages you linked to were the ones I used when I originally wrote the module I linked to in my post. Using the code you put in your answer, would just create an orphaned task, which i then manual would have to associate with a work item, which defeats the purpose of what I want to do, I think... :-/ – Lars Panzerbjrn Jan 18 '21 at 21:11
  • My mistake, I see now that you are looking to associate a task, not create a new one. Unfortunately, I do not know how to link a task using the public API. – D M Jan 18 '21 at 21:21