hiiro 0.1.289 → 0.1.290
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/hiiro/git/pr.rb +5 -2
- data/lib/hiiro/pinned_pr_manager.rb +71 -44
- data/lib/hiiro/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 39db2e632092be3971a6cb08da3a0a4a4ad3accfc42c6978bccee29ebd9c185f
|
|
4
|
+
data.tar.gz: 02e163c3f894838a6e1ef31d96d2b9f3011bf0ff53e50eee71f4f8c4c8ff1fb4
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67bdae476921c82c1aaf61195768b1145b235756ba73687e28ea918dfe43ea8d907471d38d1084dfa2caf82921fe594145f9183073480adc8b140a6d6c998723
|
|
7
|
+
data.tar.gz: 9a824284df02e880db1bb13496610b1ae39c2cbdbbae9f09176640ff8bb6e50d3e9c1a56b84491ef6d5b6ff0742db0cb9f84fe5c3c2a67abc58b42d581279c8d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
```markdown
|
|
2
|
+
## v0.1.290 (2026-03-26)
|
|
3
|
+
|
|
4
|
+
### Fixed
|
|
5
|
+
- `h pr ls`/`h pr update`: revert `statusCheckRollup` contexts limit to 100 and add pagination to retrieve all checks beyond the first 100; GitHub's GraphQL API silently returns null when limit is exceeded, causing all checks to vanish
|
|
6
|
+
|
|
2
7
|
## v0.1.289 (2026-03-26)
|
|
3
8
|
|
|
4
9
|
### Fixed
|
|
5
10
|
- `h queue run`/`watch`: frontmatter `session_name` now directly controls which tmux session the task launches in; working directory seeded from that session's active pane when no tree is specified
|
|
6
11
|
- `h queue sadd`: now immediately launches a new tmux window in the target session after adding to queue, consistent with `hadd`/`vadd` behavior (previously just added to pending with no launch)
|
|
12
|
+
- `h pr ls`: revert `statusCheckRollup` contexts limit from 250 back to 100; GitHub's GraphQL API caps connections at 100 — exceeding it silently returns null for the entire field, causing all checks to vanish from the list
|
|
13
|
+
- `h pr update`: paginate beyond the first 100 checks for PRs that hit the limit; show `❓` status for PRs where pagination still couldn't retrieve all checks
|
|
7
14
|
|
|
8
15
|
## v0.1.288 (2026-03-26)
|
|
9
16
|
|
data/lib/hiiro/git/pr.rb
CHANGED
|
@@ -106,7 +106,8 @@ class Hiiro
|
|
|
106
106
|
|
|
107
107
|
# Summarizes raw statusCheckRollup contexts into { total, success, pending, failed, frozen }.
|
|
108
108
|
# frozen = number of failed contexts that are specifically the ISC code freeze check.
|
|
109
|
-
|
|
109
|
+
# truncated: true is added when pagination couldn't retrieve all checks.
|
|
110
|
+
def self.summarize_checks(rollup, truncated: false)
|
|
110
111
|
return nil unless rollup
|
|
111
112
|
|
|
112
113
|
contexts = rollup.is_a?(Array) ? rollup : []
|
|
@@ -126,7 +127,9 @@ class Hiiro
|
|
|
126
127
|
(FAILED_CONCLUSIONS.include?(c['conclusion']) || %w[FAILURE ERROR].include?(c['state']))
|
|
127
128
|
end
|
|
128
129
|
|
|
129
|
-
{ 'total' => total, 'success' => success, 'pending' => pending, 'failed' => failed, 'frozen' => frozen }
|
|
130
|
+
result = { 'total' => total, 'success' => success, 'pending' => pending, 'failed' => failed, 'frozen' => frozen }
|
|
131
|
+
result['truncated'] = true if truncated
|
|
132
|
+
result
|
|
130
133
|
end
|
|
131
134
|
|
|
132
135
|
# Summarizes raw review nodes into { approved, changes_requested, commented, reviewers }.
|
|
@@ -262,7 +262,7 @@ class Hiiro
|
|
|
262
262
|
pr.state = info['state']
|
|
263
263
|
pr.title = info['title']
|
|
264
264
|
pr.check_runs = rollup
|
|
265
|
-
pr.checks = Hiiro::Git::Pr.summarize_checks(rollup)
|
|
265
|
+
pr.checks = Hiiro::Git::Pr.summarize_checks(rollup, truncated: info['checksTruncated'])
|
|
266
266
|
pr.reviews = Hiiro::Git::Pr.summarize_reviews(info['reviews'])
|
|
267
267
|
pr.review_decision = info['reviewDecision']
|
|
268
268
|
pr.is_draft = info['isDraft']
|
|
@@ -317,6 +317,8 @@ class Hiiro
|
|
|
317
317
|
only_frozen ? " ❄️" : " ❌"
|
|
318
318
|
elsif has_pending
|
|
319
319
|
"⏳ "
|
|
320
|
+
elsif c['truncated']
|
|
321
|
+
" ❓"
|
|
320
322
|
else
|
|
321
323
|
" ✅"
|
|
322
324
|
end
|
|
@@ -494,44 +496,24 @@ class Hiiro
|
|
|
494
496
|
def fetch_batch_for_repo(owner, name, pr_numbers)
|
|
495
497
|
return {} if pr_numbers.empty?
|
|
496
498
|
|
|
499
|
+
context_fragment = <<~GRAPHQL.strip
|
|
500
|
+
__typename
|
|
501
|
+
... on CheckRun { __typename name conclusion status detailsUrl }
|
|
502
|
+
... on StatusContext { __typename context state targetUrl }
|
|
503
|
+
GRAPHQL
|
|
504
|
+
|
|
497
505
|
pr_queries = pr_numbers.map.with_index do |num, idx|
|
|
498
506
|
<<~GRAPHQL.strip
|
|
499
507
|
pr#{idx}: pullRequest(number: #{num}) {
|
|
500
|
-
number
|
|
501
|
-
title
|
|
502
|
-
url
|
|
503
|
-
headRefName
|
|
504
|
-
state
|
|
505
|
-
isDraft
|
|
506
|
-
mergeable
|
|
507
|
-
reviewDecision
|
|
508
|
+
number title url headRefName state isDraft mergeable reviewDecision
|
|
508
509
|
statusCheckRollup {
|
|
509
|
-
contexts(last:
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
name
|
|
514
|
-
conclusion
|
|
515
|
-
status
|
|
516
|
-
detailsUrl
|
|
517
|
-
}
|
|
518
|
-
... on StatusContext {
|
|
519
|
-
__typename
|
|
520
|
-
context
|
|
521
|
-
state
|
|
522
|
-
targetUrl
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
reviews(last: 50) {
|
|
528
|
-
nodes {
|
|
529
|
-
author {
|
|
530
|
-
login
|
|
531
|
-
}
|
|
532
|
-
state
|
|
510
|
+
contexts(last: 100) {
|
|
511
|
+
totalCount
|
|
512
|
+
pageInfo { hasPreviousPage startCursor }
|
|
513
|
+
nodes { #{context_fragment} }
|
|
533
514
|
}
|
|
534
515
|
}
|
|
516
|
+
reviews(last: 50) { nodes { author { login } state } }
|
|
535
517
|
}
|
|
536
518
|
GRAPHQL
|
|
537
519
|
end
|
|
@@ -557,18 +539,36 @@ class Hiiro
|
|
|
557
539
|
pr_data = repo_data["pr#{idx}"]
|
|
558
540
|
next unless pr_data
|
|
559
541
|
|
|
542
|
+
contexts_data = pr_data.dig('statusCheckRollup', 'contexts')
|
|
543
|
+
nodes = contexts_data&.[]('nodes') || []
|
|
544
|
+
total_count = contexts_data&.[]('totalCount').to_i
|
|
545
|
+
page_info = contexts_data&.[]('pageInfo') || {}
|
|
546
|
+
|
|
547
|
+
# Paginate backwards to collect all checks beyond the first 100
|
|
548
|
+
all_nodes = nodes.dup
|
|
549
|
+
cursor = page_info['startCursor']
|
|
550
|
+
while page_info['hasPreviousPage'] && cursor
|
|
551
|
+
extra_nodes, page_info = fetch_contexts_page(owner, name, num, cursor, context_fragment)
|
|
552
|
+
break unless extra_nodes
|
|
553
|
+
all_nodes = extra_nodes + all_nodes
|
|
554
|
+
cursor = page_info&.[]('startCursor')
|
|
555
|
+
end
|
|
556
|
+
|
|
557
|
+
truncated = total_count > 0 && all_nodes.length < total_count
|
|
558
|
+
|
|
560
559
|
pr_info_by_key[[num, repo_path]] = {
|
|
561
|
-
'number'
|
|
562
|
-
'title'
|
|
563
|
-
'url'
|
|
564
|
-
'headRefName'
|
|
565
|
-
'state'
|
|
566
|
-
'isDraft'
|
|
567
|
-
'mergeable'
|
|
568
|
-
'reviewDecision'
|
|
569
|
-
'statusCheckRollup'
|
|
570
|
-
'
|
|
571
|
-
'
|
|
560
|
+
'number' => pr_data['number'],
|
|
561
|
+
'title' => pr_data['title'],
|
|
562
|
+
'url' => pr_data['url'],
|
|
563
|
+
'headRefName' => pr_data['headRefName'],
|
|
564
|
+
'state' => pr_data['state'],
|
|
565
|
+
'isDraft' => pr_data['isDraft'],
|
|
566
|
+
'mergeable' => pr_data['mergeable'],
|
|
567
|
+
'reviewDecision' => pr_data['reviewDecision'],
|
|
568
|
+
'statusCheckRollup'=> all_nodes.any? ? all_nodes : nil,
|
|
569
|
+
'checksTruncated' => truncated,
|
|
570
|
+
'reviews' => pr_data.dig('reviews', 'nodes') || [],
|
|
571
|
+
'repo' => repo_path
|
|
572
572
|
}
|
|
573
573
|
end
|
|
574
574
|
|
|
@@ -577,6 +577,33 @@ class Hiiro
|
|
|
577
577
|
{}
|
|
578
578
|
end
|
|
579
579
|
|
|
580
|
+
def fetch_contexts_page(owner, name, pr_number, before_cursor, context_fragment)
|
|
581
|
+
query = <<~GRAPHQL
|
|
582
|
+
query {
|
|
583
|
+
repository(owner: "#{owner}", name: "#{name}") {
|
|
584
|
+
pullRequest(number: #{pr_number}) {
|
|
585
|
+
statusCheckRollup {
|
|
586
|
+
contexts(last: 100, before: "#{before_cursor}") {
|
|
587
|
+
pageInfo { hasPreviousPage startCursor }
|
|
588
|
+
nodes { #{context_fragment} }
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
GRAPHQL
|
|
595
|
+
|
|
596
|
+
result = `gh api graphql -f query='#{query.gsub("'", "'\\''")}' 2>/dev/null`
|
|
597
|
+
return [nil, nil] if result.empty?
|
|
598
|
+
|
|
599
|
+
contexts = JSON.parse(result).dig('data', 'repository', 'pullRequest', 'statusCheckRollup', 'contexts')
|
|
600
|
+
return [nil, nil] unless contexts
|
|
601
|
+
|
|
602
|
+
[contexts['nodes'] || [], contexts['pageInfo'] || {}]
|
|
603
|
+
rescue JSON::ParserError, StandardError
|
|
604
|
+
[nil, nil]
|
|
605
|
+
end
|
|
606
|
+
|
|
580
607
|
def check_run_emoji(conclusion, status)
|
|
581
608
|
return "⏳" if %w[QUEUED IN_PROGRESS PENDING REQUESTED WAITING].include?(status) && conclusion.nil?
|
|
582
609
|
case conclusion
|
data/lib/hiiro/version.rb
CHANGED