functions/get-adoworkitemcommentlist.ps1
<#
.SYNOPSIS Retrieves comments for an Azure DevOps work item. .DESCRIPTION Retrieves a (pageable) list of comments for the specified work item. Supports server paging via -Top and -ContinuationToken or automatic full retrieval with -All. Can include deleted, expand rendered text or reactions, and control sort order. .PARAMETER Organization Azure DevOps organization name. .PARAMETER Project Project name or id. .PARAMETER Token Personal Access Token (PAT). .PARAMETER WorkItemId Target work item id. .PARAMETER Top Maximum number of comments to return in a single page ($top). .PARAMETER ContinuationToken Token returned from a previous page to continue listing. .PARAMETER IncludeDeleted Include deleted comments. .PARAMETER Expand Additional data options: none, reactions, renderedText, renderedTextOnly, all. .PARAMETER Order asc or desc. .PARAMETER All Retrieve and aggregate all pages (ignores provided -ContinuationToken; still honors -Top as page size if set). .PARAMETER Raw Return raw API payload objects instead of flattened comments. .PARAMETER ApiVersion API version (default 7.1-preview.4). .EXAMPLE Get-ADOWorkItemCommentList -Organization org -Project proj -Token $pat -WorkItemId 123 Retrieves the first page of comments for work item 123. .EXAMPLE Get-ADOWorkItemCommentList -Organization org -Project proj -Token $pat -WorkItemId 123 -Top 50 -All Retrieves all comments for work item 123 in pages of up to 50 comments. .EXAMPLE Get-ADOWorkItemCommentList -Organization org -Project proj -Token $pat -WorkItemId 123 -Expand renderedText -Order desc Retrieves all comments including rendered HTML, sorted descending by id. .NOTES Author: Oleksandr Nikolaiev (@onikolaiev) #> function Get-ADOWorkItemCommentList { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding(DefaultParameterSetName = 'Paged')] [OutputType([PSCustomObject[]])] param( [Parameter(Mandatory = $true)] [string]$Organization, [Parameter(Mandatory = $true)] [string]$Project, [Parameter(Mandatory = $true)] [string]$Token, [Parameter(Mandatory = $true)] [int]$WorkItemId, [Parameter(Mandatory = $false)] [int]$Top, [Parameter(Mandatory = $false, ParameterSetName = 'Paged')] [string]$ContinuationToken, [Parameter(Mandatory = $false)] [switch]$IncludeDeleted, [Parameter(Mandatory = $false)] [ValidateSet('none','reactions','renderedText','renderedTextOnly','all')] [string]$Expand = 'none', [Parameter(Mandatory = $false)] [ValidateSet('asc','desc')] [string]$Order = 'asc', [Parameter(Mandatory = $false)] [switch]$All, [Parameter(Mandatory = $false)] [switch]$Raw, [Parameter(Mandatory = $false)] [string]$ApiVersion = '7.1-preview.4' ) begin { Write-PSFMessage -Level Verbose -Message "Starting retrieval of comments for WorkItemId: $WorkItemId (Org: $Organization, Project: $Project)" Invoke-TimeSignal -Start $baseApiUri = "$Project/_apis/wit/workItems/$WorkItemId/comments" $aggregate = [PSCustomObject]@() # changed from [PSCustomObject]@() to a standard array $pageCount = 0 $effectiveContinuation = $ContinuationToken } process { if (Test-PSFFunctionInterrupt) { return } try { do { $query = @{} if ($Top) { $query['$top'] = $Top } if ($effectiveContinuation) { $query['continuationToken'] = $effectiveContinuation } if ($IncludeDeleted) { $query['includeDeleted'] = 'true' } if ($Expand -ne 'none') { $query['$expand'] = $Expand } if ($Order) { $query['order'] = $Order } $apiUri = $baseApiUri if ($query.Count -gt 0) { # Rewritten to avoid pipeline/-join binding issue $pairs = @() foreach ($kv in $query.GetEnumerator()) { $pairs += ("{0}={1}" -f $kv.Key, $kv.Value) } $apiUri += '?' + ($pairs -join '&') } Write-PSFMessage -Level Verbose -Message "Requesting comments page (page index: $pageCount) URI: $apiUri" $response = Invoke-ADOApiRequest -Organization $Organization ` -Token $Token ` -ApiUri $apiUri ` -Method "GET" ` -Headers @{'Content-Type'='application/json'} ` -ApiVersion $ApiVersion $payload = $response.Results $pageCount++ $currentComments = @() if ($payload -and $payload.comments) { $currentComments = $payload.comments } if ($Raw) { $aggregate += $payload } else { foreach ($c in $currentComments) { $aggregate += ($c | Select-PSFObject * -TypeName 'ADO.TOOLS.WorkItem.Comment') } } $effectiveContinuation = $payload.continuationToken $hasMore = [string]::IsNullOrWhiteSpace($effectiveContinuation) -eq $false if (-not $All) { $hasMore = $false } } while ($hasMore) if ($Raw) { Write-PSFMessage -Level Verbose -Message "Successfully retrieved $pageCount page(s) of comment payload(s)" return $aggregate | Select-PSFObject * -TypeName 'ADO.TOOLS.WorkItem.CommentList' } else { Write-PSFMessage -Level Verbose -Message "Successfully retrieved $($aggregate.Count) comment(s) across $pageCount page(s)" return $aggregate } } catch { Write-PSFMessage -Level Error -Message "Failed to retrieve comments for WorkItemId: $WorkItemId : $($_.ErrorDetails.Message)" -Exception $PSItem.Exception Stop-PSFFunction -Message "Stopping because of errors" [PSCustomObject]@() } } end { Write-PSFMessage -Level Verbose -Message "Completed retrieval of comments for WorkItemId: $WorkItemId" Invoke-TimeSignal -End } } |