Setting the file. One moment.
03 List Open Threads · Copilot PR Autopilot · github/awesome-copilot · Skills Docs
ContentsBack to the top of the page 94.10
10 Cleanup
(opens in a new tab)
scripts/ 03-list-open-threads.ps1
PowerShell · 126 lines · 4 KB
15
16 . PARAMETER Owner
17 Optional; auto-resolved from `gh repo view`.
18
19 . PARAMETER Repo
20 Optional; auto-resolved from `gh repo view`.
21 . PARAMETER PrNumber The pull request number.
22
23 . EXAMPLE
24 pwsh 03-list-open-threads.ps1 -PrNumber 122
25
26 . PARAMETER MaxBodyLength
27 Cap the `Body` column at this many characters (default 500; pass 0 to
28 disable). Long Copilot comments otherwise dominate stdout and slow
29 triage; truncated bodies are suffixed with `…`.
30 #>
31 [ CmdletBinding ()]
32 param (
33 [ string ]$Owner ,
34 [ string ]$Repo ,
35
36 [ Parameter ( Mandatory = $true )]
37 [ int ]$PrNumber ,
38
39 [ ValidateRange ( 0 , 100000 )]
40 [ int ]$MaxBodyLength = 500
41 )
42
43 $ErrorActionPreference = 'Stop'
44 . " $PSScriptRoot /_lib.ps1"
45
46 $coords = Resolve-RepoCoords - Owner $Owner - Repo $Repo
47 $Owner = $coords.Owner
48 $Repo = $coords.Repo
49
50 $query = @'
51 query($owner: String!, $repo: String!, $pr: Int!, $after: String) {
52 repository(owner: $owner, name: $repo) {
53 pullRequest(number: $pr) {
54 reviewThreads(first: 100, after: $after) {
55 pageInfo {
56 endCursor
57 hasNextPage
58 }
59 nodes {
60 id
61 isResolved
62 comments(first: 1) {
63 nodes {
64 author { login }
65 body
66 path
67 line
68 createdAt
69 }
70 }
71 }
72 }
73 }
74 }
75 }
76 '@
77
78 $all = [ System.Collections.Generic.List [ object ]]::new()
79 $after = $null
80 do {
81 $ghArgs = @ ( '-f' , "query= $query " , '-f' , "owner= $Owner " , '-f' , "repo= $Repo " , '-F' , "pr= $PrNumber " )
82 if ($after) { $ghArgs = $ghArgs + @ ( '-f' , "after= $after " ) }
83
84 $data = Invoke-GhGraphQL - GhArgs $ghArgs - Context "list threads for $Owner / $Repo PR # $PrNumber "
85 $page = $data.data.repository.pullRequest.reviewThreads
86 foreach ($n in $page.nodes) { $all.Add($n) }
87 $after = $page.pageInfo.endCursor
88 } while ($page.pageInfo.hasNextPage)
89
90 $threads = $all.ToArray()
91
92 $open = $threads | Where-Object { -not $_ .isResolved }
93
94 $resultList = [ System.Collections.Generic.List [ object ]]::new()
95 foreach ($t in $open) {
96 $c = if ($t.comments -and $t.comments.nodes -and $t.comments.nodes.Count -gt 0 ) { $t.comments.nodes[ 0 ] } else { $null }
97 if ( -not $c) { continue } # malformed thread (no originating comment) — skip rather than crash
98 $body = ($c.body -replace " `r ? `n " , ' ' )
99 if ($MaxBodyLength -gt 0 -and $body.Length -gt $MaxBodyLength) {
100 $body = $body.Substring( 0 , $MaxBodyLength) + '…'
101 }
102 $path = if ( $null -ne $c.line) { " $( $c.path ) : $( $c.line ) " } else { $c.path }
103 $author = if ($c.author -and $c.author.login) { $c.author.login } else { '(deleted)' }
104 # Normalise createdAt via the shared helper so the format stays
105 # identical across 01/02/03 (Format-IsoUtcString in _lib.ps1).
106 $createdAt = Format-IsoUtcString $c.createdAt
107 $resultList.Add([ pscustomobject ] @ {
108 ThreadId = $t.id
109 Author = $author
110 Path = $path
111 CreatedAt = $createdAt
112 Body = $body
113 })
114 }
115 $result = $resultList.ToArray()
116
117 # Single-line JSON output (matches the contract used by 01/02/08/10).
118 # -Compress so callers can pipe to ConvertFrom-Json or jq directly without
119 # stripping PowerShell's default Format-List rendering / ANSI escapes.
120 [ pscustomobject ] @ {
121 PrNumber = $PrNumber
122 Owner = $Owner
123 Repo = $Repo
124 OpenThreadCount = $result.Count
125 Threads = $result
126 } | ConvertTo-Json - Depth 6 - Compress