The Ops Community

Kithmini Indimagedara
Kithmini Indimagedara

Posted on

Using the Azure DevOps APIs, to copy a work item type-2🧡 πŸƒ

I covered the fundamentals of using the Azure DevOps APIs to duplicate a work item type in the previous article. I intend to talk about the further details in this article.

It can be created using the following steps:

The field must first be added to the work item type. You can add the group to the section as indicated in the code below once the field has been included in the work item type. Let's first define what the code is doing. We are looping through the groups for the specified section using the variable $grp as the control in the work item to copy from. The field is first added to the new work item type. The new group is then added to the section.The label in the group, which will serve as the label for the field, is the only thing that is not null, as you can see. We have a reference to the field we just added to the work item in the control (the control's id field) as well as the control's label.

As can be seen at the end of this code block, adding the group is therefore as simple as using the API.

# multi line text fields cannot be inside a group. they are their own group on the UI
if($grp.controls[0].controlType -eq "HtmlFieldControl")
{
    isMultiLine = $true
    # first add the field to the work item
    $addCtl = @{
       referenceName = $grp.controls[0].id
       order = "$null"
       readOnly = "$false"
       label = $grp.label.Trim()
       visible = "$true"

   # must encapsulate true false in quotes to register
   defaultValue = if($fld.type -eq "boolean")
                    {"$false"}
                    else {""}
   required = if($fld.type -eq "boolean")
                 {"$true"} 
                 else {"$false"} 
 $ctlJSON = ConvertTo-Json -InputObject $addCtl

 # add field to work item type
 # https://docs.microsoft.com/en-us/rest/api/azure/devops/processes/fields/add?view=azure-devops-rest-7.1
 # POST https://dev.azure.com/{organization}/_apis/work/processes/{processId}/workItemTypes/{witRefName}/fields?api-version=7.1-preview.2
 $field = $null
 $fieldURL = $userParams.HTTP_preFix + "://dev.azure.com/" + $userParams.VSTSMasterAcct + "/_apis/work/processes/" + $proc.typeId  + "/workitemTypes/" + $newWKItem.referenceName + "/fields?api-version=7.1-preview.2"
 $field = Invoke-RestMethod -Uri $fieldURL -Method Post -ContentType "application/json" -Headers $authorization -Body $ctlJSON
 Write-Host $field

# now add the Multi line field to the page in a group with no name 
$addGroup = @{
          Contribution = "$null"    
          height = "$null"
          id = "$null"
          inherited = "$null"
          isContribution = "$false"
          label = $grp.label.Trim()
          visible = "$true"
          order = "$null"
          overridden = "$null"
               controls = @( @{
                   contribution = "$null"
                   controlType = "$null"
                   height = "$null"
                   id = $grp.controls[0].id
                   inherited = "$null"
                   isContribution = "$false"
                   label = $grp.controls[0].label.Trim()
                   metadata = "$null"
                   order = "$null"
                   overridden = "$null"
                   visible = "$true"
                   watermark = "$null"
               })

    }
    $grpJSON = ConvertTo-Json -InputObject $addGroup
    # POST https://dev.azure.com/{organization}/_apis/work/processes/{processId}/workItemTypes/{witRefName}/layout/pages/{pageId}/sections/{sectionId}/groups?api-version=7.1-preview.1
    $groupURL = $userParams.HTTP_preFix + "://dev.azure.com/" + $userParams.VSTSMasterAcct + "/_apis/work/processes/" + $proc.typeId  + "/workitemtypes/" + $newWKItem.referenceName + "/layout/pages/" + $pgExists.id + "/sections/" + $newSection.id + "/groups?api-version=7.1-preview.1"   
    $group = Invoke-RestMethod -Uri $groupURL -Method Post -ContentType "application/json" -Headers $authorization -Body $grpJSON
    Write-Host "Multi line field " $group
    $newGrp = $group  
}

Enter fullscreen mode Exit fullscreen mode

Other controls exist that you must deal with. The custom control extension field comes first. This control has a multi-select feature and allows for the addition of selections. As with all other fields, you must add this type of field to the work item before adding it to the page. After that, you add the group it belongs to before adding the control to the group. It is displayed below. Keep in mind that the control must have a special Id. I employed the New-Guid PowerShell command. You must then include a reference name. The field you just created has this id. The field Name and values are then added once again in the contribution section.

 # add control to group. add the field to the control
         if($grpCtl.isContribution -eq $true)
         {
           $addCtl = @{
               # un documented when adding a contribution control it must have an ID. it has to be unique so i added a guid.
               id = New-Guid
               # un documented - if adding a contribution field must add reference name - this is the field in the control
               referenceName = $grpCtl.contribution.inputs.FieldName

              isContribution =  if($grpCtl.isContribution -eq $true){"$true"}else {"$false"}  
              height = "$null"
              label = $grpCtl.label.Trim()
              metadata = "$null"
              order = "$null"
              overridden = "$null"
              readOnly = if($grpCtl.readOnly -eq $true){"$true"}else {"$false"}   
              visible = if($grpCtl.visible -eq $true){"$true"}else {"$false"}   
              watermark = "$null"
                contribution = @{
                    contributionId = $grpCtl.contribution.contributionId
                    inputs = @{
                        FieldName =  $grpCtl.contribution.inputs.FieldName
                        Values = $grpCtl.contribution.inputs.Values
                    }
                }
          }
      }
Enter fullscreen mode Exit fullscreen mode

A Boolean field is the other field type to be cautious of. Here, the default value is essential and must be present. The default value won't be added to the page if you omit it. I got around this by always adding the default value and setting the field type to False if it was a Boolean field. I set it to a blank string if it wasn't Boolean, and that seems to work. Other custom control fields exist, and each one requires adjustment in order to add correctly. You can locate a URL field custom control in the code and see how I added it as well.

# url contribution control - need to set added to true so code will not try to add field or control again
    # url control has to be added as a control to the group, not like others that need field added first
    # adding url contribution field is not documented. found request by using fiddler
    if($grpCtl.contribution.contributionId -like "*url-field")
    {
      $addCtl = @{
        contributionId = $grpCtl.contribution.contributionId
        isContribution =  if($grpCtl.isContribution -eq $true){"$true"}else {"$false"}
        height = "$null"
        label = $grpCtl.label.Trim()
        metadata = "$null"
        order = "$null"
        overridden = "$null"
        controlType = "$null"
        readOnly = if($grpCtl.readOnly -eq $true){"$true"}else {"$false"}<br />
        visible = if($grpCtl.visible -eq $true){"$true"}else {"$false"}<br />
        watermark = "$null"
        contribution = @{
                     contributionId = $grpCtl.contribution.contributionId
                     inputs = @{
                              HideUrlIfEmptyField = $grpCtl.contribution.inputs.HideUrlIfEmptyField
                              Title = $grpCtl.contribution.inputs.Title
                              Url = $grpCtl.contribution.inputs.Url<br />
                              }
                     }
        }

        $ctlJSON = ConvertTo-Json -InputObject $addCtl
        # https://docs.microsoft.com/en-us/rest/api/azure/devops/processes/controls/create?view=azure-devops-rest-7.1
        # POST https://dev.azure.com/{organization}/_apis/work/processes/{processId}/workItemTypes/{witRefName}/layout/groups/{groupId}/controls?api-version=7.1-preview.1
        $controlURL = $userParams.HTTP_preFix + "://dev.azure.com/" + $userParams.VSTSMasterAcct + "/_apis/work/processes/" + $proc.typeId  + "/workitemtypes/" + $newWKItem.referenceName + "/layout/groups/" + $group.id + "/controls?api-version=7.1-preview.1"    
        $control = Invoke-RestMethod -Uri $controlURL -Method Post -ContentType "application/json" -Headers $authorization -Body $ctlJSON
        Write-Host $control
        $added = "$true"


       }
Enter fullscreen mode Exit fullscreen mode

I've demonstrated how to make a copy of an existing work item type using the same procedure. If you wish to add a new work item to another process as well, this ought to work.

I sincerely hope you will find this information to be useful.

Discussion (0)