Can't set Board Swimlane Criteria in Azure DevOps Server 2022

326 views Asked by At

I'm using Azure DevOps Server 2022, am Team and Project Collection Administrator, and in Project > Board > Gear > Settings > Swimlanes, when adding a Swimlane, I don't see the Add Criteria option.

Bing Chat suggests confirming version (latest), permissions (aforementioned Admin role memberships), and browser version (Edge.latest on Win 11.latest).

What am I missing?

Additions, 2023.12.21: Script and output below. I now am wondering whether Work Areas are in play here. My environment currently has 3 Work Areas and the script uris are not parameterized by this quality. The Swimlanes are configured only on one of the boards. I can move the Work Item to a different Work Area where there are no swimlanes at all and the output doesn't differ. Could this be the source of my problem? How would I specify the target Work Area?

# update-Swimlane.ps1

param (
    [Parameter(Mandatory=$true)]
    [string]$id = $null
)

$server = "devops.huhs.harvard.edu" # The name or IP address of your Azure DevOps Server
$collection = "HUHS_IS"
$project = "TEMP-JIRA-MIGRATION"
$baseUri = "https://$server/$collection/$project/_apis/wit/wiql?api-version=7.0"
$pat = Get-Content .\rawpat.txt -Raw # Personal Access Token
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($pat)"))

$boardUri = "https://$server/$collection/$project/_apis/work/boards/Issues?api-version=7.0"
$responseGet = Invoke-RestMethod -Uri $boardUri -Method Get -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
$extensionFieldName = $responseGet.fields.rowField.referenceName

$uri = "https://$server/$collection/$project/_apis/wit/workitems/$($id)?api-version=7.0"
$result = Invoke-RestMethod -Uri $uri -Method GET -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
$SystemBoardLane = $result.fields.'System.BoardLane'
$KanbanRowLane = $result.fields.$extensionFieldName
$tags = $result.fields.'System.Tags' -split "\s*;\s*"
$state = $result.fields.'System.State'
$newBoardLane = 'CRM'
# Only update if change is needed (checks both System.BoardLane, not WEF_[guid]_KanbanRowLane)
if ($newBoardLane -and $newBoardLane -ne $SystemBoardLane) {
    echo "Before:" # from call above
    echo "  System.State:     $state"
    echo "  Tags:             $tags"
    echo "  System.BoardLane: $SystemBoardLane"
    echo "  KanbanRowLane:    $KanbanRowLane"
    echo ""
    echo "Changing $extensionFieldName to $newBoardLane"
    $body = @"
    [
        {
            "op": "add",
            "path": "/fields/$extensionFieldName",
            "from": null,
            "value": "$newBoardLane"
        }
    ]
"@
    $result = Invoke-RestMethod -Uri $uri -Method Patch -Body $body -ContentType "application/json-patch+json" -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
    # echo ""
    # echo "Change result:"
    # $result

    echo ""
    echo "Tweaking System.State"
    # select a new state from the other active ones that aren't the current one
    if ($state -ne 'Selected for Development') { $newState = 'Selected for Development'}
    if (-not $newState -and $state -ne 'On Hold') { $newState = 'On Hold'}
    if (-not $newState -and $state -ne 'Doing') { $newState = 'Doing'}
    echo "- change to $newState"
    $body = @"
[
{
    "op": "add",
    "path": "/fields/System.State",
    "value": "$newState"
}
]
"@ 
    $result = Invoke-RestMethod -Uri $uri -Method Patch -Body $body -ContentType "application/json-patch+json" -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
    # echo ""
    # echo "Tweak result:"
    # $result

    echo "- change back to $state"
    $body = @"
[
{
    "op": "add",
    "path": "/fields/System.State",
    "value": "$state"
}
]
"@ 
    $result = Invoke-RestMethod -Uri $uri -Method Patch -Body $body -ContentType "application/json-patch+json" -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
    # echo ""
    # echo "Tweak result:"
    # $result
    
    echo ""
    echo "After:"
    $result = Invoke-RestMethod -Uri $uri -Method GET -Headers @{Authorization = ("Basic {0}" -f $base64AuthInfo) }
    $SystemBoardLane = $result.fields.'System.BoardLane'
    $KanbanRowLane = $result.fields.$extensionFieldName
    $tags = $result.fields.'System.Tags' -split "\s*;\s*"    
    echo "  System.State:     $state"
    echo "  Tags:             $tags"
    echo "  System.BoardLane: $SystemBoardLane"
    echo "  KanbanRowLane:    $KanbanRowLane"
    echo "  Expected lane:    $newBoardLane"
}
else {
    echo "No change needed: $SystemBoardLae and $KanbanRowLane already $newBoardLane"
}
PS F:\DevTeam\Project_Management\Projects\Jira_to_DevOps_Migration> .\update-Swimlane.ps1 12770
Before:
  System.State:     Selected for Development
  Tags:             CRM
  System.BoardLane:
  KanbanRowLane:    CRM

Changing WEF_5DD75A5340614097AADDCAFDEA91A637_Kanban.Lane to CRM

Tweaking System.State
- change to On Hold
- change back to Selected for Development

After:
  System.State:     Selected for Development
  Tags:             CRM
  System.BoardLane:
  KanbanRowLane:    CRM
  Expected lane:    CRM
1

There are 1 answers

12
wade zhou - MSFT On

The Swinlane rule(Criteria option) is a new feature which announced in sprint 221(May 9 2023), it's only available with the New Boards Hubs preview.

enter image description here

Currently, there is no this new boards hub feature on ADO sever 2022(i installed latest version Azure DevOps Server 2022.1)

enter image description here

I'm afraid it's currently not supported yet on ADO server 2022.

Edit: add powershell scrip to change the swimlane for the work item.

After you grant the swimlane field value /WEF_39C0D7022xxx_Kanban.Lane:

# change the parameters to yours 
Param(
   [string]$token = "PAT",
   [string]$baseurl = "http://testVM/DefaultCollection",
   [string]$project = "project1",
   [string]$workitemid = "1"
)

#$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $User,$token)))
$base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":$($token)"))
$Header = @{Authorization = ("Basic {0}" -f $base64AuthInfo)}

$uri = "$baseurl/$project/_apis/wit/workitems/$workitemid"+ "?api-version=7.0"

Write-Host $uri


# use target swinlane name for value
$body = @"
[
  {
    `"op`": `"add`",
    `"path`": `"/fields/WEF_39C0D70225034E42BD9EC83B788459CB_Kanban.Lane`",
    `"from`": null,
    `"value`": `"swimlane 3`"
  }
]
"@

Invoke-RestMethod $uri -Method PATCH -Headers $header -ContentType "application/json-patch+json" -Body $body

enter image description here

Eidt: If you move work items across different state, and into target swimlane, you need to add state field change in request body as well.

For example, work item in New state, and would like to change to swimlane 3 in Active state.

enter image description here

Change the request body as below:

$body = @"
[
  {
    `"op`": `"add`",
    `"path`": `"/fields/WEF_39C0D70225034xxBD9EC83B778459CB_Kanban.Lane`",
    `"from`": null,
    `"value`": `"swimlane 3`"
  },
   {
    "op": "add",
    "path": "/fields/System.State",
    "value": "Active"
  }
]
"@

The System.BoardLane value will be automatically changed.

enter image description here