Azure DevOps Configuration required on new work item types (Resolved)

Copper Contributor

** Business Requirement ** 

Create a new iteration black log type 'Impediment'

 

DanielBotha1520_0-1716287224906.png

As part of the configuration, if a sprint board has column options other than (New | Active | Resolved | Closed), then a message of “Configuration required” will be displayed once the new work item type has been added to Azure DevOps.   

 

Sprint board with a custom column:

DanielBotha1520_1-1716287267085.png

Adding of the new Task type: 

DanielBotha1520_2-1716287297034.png

Sprint board with a custom column after work item type has been added:

DanielBotha1520_3-1716287321332.png

In most cases this can easily be resolved by going to ‘Column Options’ and clicking save to update the sprint board with the correct status.

 

DanielBotha1520_4-1716287348873.png

However, in our case we needed to do this across a big organization with a lot of boards, some with custom columns. As this is a disruptive action to users that would need to go to their sprint boards to update the new status. 

An automated method can be used through the API. Though the documentation is vague on what the json body requirement is the engineers from Microsoft was able to provide us with the required structure. 

 

Source: https://learn.microsoft.com/en-us/rest/api/azure/devops/work/taskboard-columns/update?view=azure-dev... 

 

[ 

  { 

    "mappings": [ 

      { 

        "workItemType": "Task", 

        "state": "New" 

      }, 

      { 

        "workItemType": "Bug", 

        "state": "New" 

      }, 

      { 

        "state": "New", 

        "workItemType": "Impediment" 

      } 

    ], 

    "order": 0, 

    "name": "New", 

    "id": "" 

  } 

]

 

I created the following PowerShell script to add the new work item states to sprint boards with custom added columns. 

 

 

# Define parameters for the script 

Param(  

[string]$organisation = "AzureDevOps-Organisation-Name",  

[string]$project = "AzureDevOps-Project-Name",  

[string]$user = "email address removed for privacy reasons", 

[string]$token = "Your-PAT" # Personal Access Token 

) 

 

# Convert username and token to Base64 for Basic Authentication 

$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $user,$token))) 

 

# Define headers for the API request 

$headers = @{Authorization=("Basic {0}" -f $base64AuthInfo)} 

 

# Define the URL for the Teams API 

$TeamUrl = "https://dev.azure.com/$($organisation)/_apis/projects/$project/teams?api-version=7.1-preview.3" 

 

# Send a GET request to the Teams API 

$TeamRequest = Invoke-RestMethod -Uri $TeamUrl -Method Get -ContentType "application/json" -Headers $headers 

 

# Loop through each team in the response 

foreach ($Team in $TeamRequest.value) { 

 

    # Define the URL for the Task Board Columns API for the current team 

    $TaskBoardUrl = "https://dev.azure.com/$($organisation)/$project/$($Team.id)/_apis/work/taskboardcolumns?api-version=7.1-preview.1" 

 

    # Send a GET request to the Task Board Columns API 

    $TaskBoardResult = Invoke-RestMethod -Uri $TaskBoardUrl -Method Get -ContentType "application/json" -Headers $headers 

 

    # Loop through each column in the response 

    foreach ($Column in $TaskBoardResult.columns) 

    { 

        # If the column name does not match 'New', 'Active', 'Resolved', or 'Closed' 

        if ($Column.name -notmatch 'New|Active|Resolved|Closed') 

        { 

            # Define an empty array for the columns 

            $columnsArray = @() 

 

            # Define valid states 

            $validStates = @("New", "Active", "Closed") 

 

            # Loop through each column in the response 

            $TaskBoardResult.columns | ForEach-Object { 

                # Create a new object for the column 

                $column = New-Object PSObject -Property @{ 

                    id = "" 

                    name = $_.name 

                    order = $_.order 

                    mappings = $_.mappings 

                } 

 

                # Filter the mappings for the column 

                $column.mappings = $column.mappings | Where-Object { $_.workItemType -ne "Impediment" -or ($_.workItemType -eq "Impediment" -and $_.state -eq $column.name) } 

 

                # If the column name is in the valid states 

                if ($column.name -in $validStates) { 

                    # Create a new mapping for the column 

                    $newMapping = New-Object PSObject -Property @{ 

                        state = $column.name 

                        workItemType = "Impediment" 

                    } 

 

                    # Add the new mapping to the column 

                    $column.mappings += $newMapping 

                }           

 

                # Add the column to the array 

                $columnsArray += $column 

            } 

 

            # Convert the array to JSON 

            $jsonBody = $columnsArray | ConvertTo-Json -Depth 10 

 

            # Define the URL for the Task Board Columns API for updating 

            $TaskBoardUrlUpdate = "https://dev.azure.com/$($organisation)/$project/$($Team.id)/_apis/work/taskboardcolumns?api-version=7.1-preview.1" 

 

            # Send a PUT request to the Task Board Columns API to update the columns 

            $ResultCall = Invoke-RestMethod -Uri $TaskBoardUrlUpdate -Method PUT -Body $jsonBody -ContentType "application/json" -Headers $headers 

 

            # Print the validation message and columns from the response 

            $ResultCall.validationMesssage 

            $ResultCall.columns 

        } 

    } 

} 

 

 

Result after running the script:

DanielBotha1520_5-1716287443756.png

 

 

0 Replies