Public/Get-PSUADOWorkItemStates.ps1
|
function Get-PSUADOWorkItemStates { <# .SYNOPSIS Retrieves all available states for Azure DevOps work item types in a project. .DESCRIPTION This function connects to Azure DevOps and retrieves the complete list of available states for each work item type in the specified project. This is useful for understanding valid state transitions when creating or updating work items. .PARAMETER Project (Mandatory) The Azure DevOps project name where work item types are defined. .PARAMETER WorkItemType (Optional) Specific work item type to get states for (e.g., 'Bug', 'Task', 'User Story'). If not specified, returns states for all work item types in the project. .PARAMETER Organization (Optional) The Azure DevOps organization name under which the project resides. Default value is $env:ORGANIZATION. Set using: Set-PSUUserEnvironmentVariable -Name "ORGANIZATION" -Value "your_org_name" .PARAMETER PAT (Optional) Personal Access Token for Azure DevOps authentication. Default value is $env:PAT. Set using: Set-PSUUserEnvironmentVariable -Name "PAT" -Value "your_pat_token" .EXAMPLE Get-PSUADOWorkItemStates -Organization "myorg" -Project "MyProject" Retrieves states for all work item types in the "MyProject" project. .EXAMPLE Get-PSUADOWorkItemStates -Organization "myorg" -Project "MyProject" -WorkItemType "Bug" Retrieves only the states available for Bug work items. .EXAMPLE Get-PSUADOWorkItemStates -Project "MyProject" Uses environment variables for organization and PAT. .OUTPUTS [PSCustomObject[]] - Array of work item types with their available states .NOTES Author: Lakshmanachari Panuganti Date: October 16, 2025 .LINK https://github.com/lakshmanachari-panuganti/OMG.PSUtilities/tree/main/OMG.PSUtilities.AzureDevOps https://www.linkedin.com/in/lakshmanachari-panuganti/ https://www.powershellgallery.com/packages/OMG.PSUtilities.AzureDevOps https://learn.microsoft.com/en-us/rest/api/azure/devops #> [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$Project, [Parameter()] [string]$WorkItemType, [Parameter()] [ValidateNotNullOrEmpty()] [string]$Organization = $env:ORGANIZATION, [Parameter()] [ValidateNotNullOrEmpty()] [string]$PAT = $env:PAT ) begin { # Display parameters Write-Verbose "[$($MyInvocation.MyCommand.Name)] Parameters:" foreach ($param in $PSBoundParameters.GetEnumerator()) { if ($param.Key -eq 'PAT') { $maskedPAT = if ($param.Value -and $param.Value.Length -ge 3) { $param.Value.Substring(0, 3) + "********" } else { "***" } Write-Verbose " $($param.Key): $maskedPAT" } else { Write-Verbose " $($param.Key): $($param.Value)" } } # Validate Organization (required because ValidateNotNullOrEmpty doesn't check default values from environment variables) if (-not $Organization) { throw "The default value for the 'ORGANIZATION' environment variable is not set.`nSet it using: Set-PSUUserEnvironmentVariable -Name 'ORGANIZATION' -Value '<org>' or provide via -Organization parameter." } # Validate PAT (required because ValidateNotNullOrEmpty doesn't check default values from environment variables) if (-not $PAT) { throw "The default value for the 'PAT' environment variable is not set.`nSet it using: Set-PSUUserEnvironmentVariable -Name 'PAT' -Value '<pat>' or provide via -PAT parameter." } $headers = Get-PSUAdoAuthHeader -PAT $PAT } process { try { # Escape project name for URI $escapedProject = if ($Project -match '%[0-9A-Fa-f]{2}') { $Project } else { [uri]::EscapeDataString($Project) } $allWorkItemStates = @() if ($WorkItemType) { # Get states for specific work item type Write-Verbose "Retrieving states for work item type: $WorkItemType" $uri = "https://dev.azure.com/$Organization/$escapedProject/_apis/wit/workitemtypes/$WorkItemType/states?api-version=7.1-preview.1" $invokeParams = @{ Uri = $uri Headers = $headers Method = 'Get' ErrorAction = 'Stop' Verbose = $false } $response = Invoke-RestMethod @invokeParams $workItemStateInfo = [PSCustomObject]@{ WorkItemType = $WorkItemType States = $response.value.states | ForEach-Object { [PSCustomObject]@{ Name = $_.name Category = $_.category PSTypeName = 'PSU.ADO.WorkItemState' } } PSTypeName = 'PSU.ADO.WorkItemTypeStates' } $allWorkItemStates += $workItemStateInfo } else { # Get all work item types first, then get states for each Write-Verbose "Retrieving all work item types for project: $Project" $typesUri = "https://dev.azure.com/$Organization/$escapedProject/_apis/wit/workitemtypes?api-version=7.1-preview.1" $typesResponse = Invoke-RestMethod -Uri $typesUri -Headers $headers -Method Get -ErrorAction Stop foreach ($wit in $typesResponse.value) { Write-Verbose "Retrieving states for work item type: $($wit.name)" $statesUri = "https://dev.azure.com/$Organization/$escapedProject/_apis/wit/workitemtypes/$($wit.name)/states?api-version=7.1-preview.1" try { # Invoke states endpoint with splatting $invokeParams = @{ Uri = $statesUri Headers = $headers Method = 'Get' ErrorAction = 'Stop' Verbose = $false } $statesResponse = Invoke-RestMethod @invokeParams $workItemStateInfo = [PSCustomObject]@{ States = $statesResponse.value.states | ForEach-Object { [PSCustomObject]@{ Name = $_.name Category = $_.category PSTypeName = 'PSU.ADO.WorkItemState' } } PSTypeName = 'PSU.ADO.WorkItemTypeStates' } $allWorkItemStates += $workItemStateInfo } catch { Write-Warning "Failed to get states for work item type '$($wit.name)': $($_.Exception.Message)" } } } Write-Verbose "Retrieved states for $($allWorkItemStates.Count) work item type(s)" return $allWorkItemStates } catch { $PSCmdlet.ThrowTerminatingError($_) } } } |