hiiro 0.1.159 → 0.1.161
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/bin/h-cpr +26 -0
- data/bin/h-pr +154 -27
- data/lib/hiiro/service_manager.rb +1 -1
- data/lib/hiiro/version.rb +1 -1
- metadata +10 -12
- /data/{scripts → script}/compare +0 -0
- /data/{scripts → script}/install +0 -0
- /data/{scripts → script}/publish +0 -0
- /data/{scripts → script}/sync +0 -0
- /data/{scripts → script}/test +0 -0
- /data/{scripts → script}/update +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bba280c058e3179fcf5430d57c5ad67725dfdd5787d05e256f6cefd5561b809d
|
|
4
|
+
data.tar.gz: 67315c92d268a4163193049a36b5d9e3e29fd70378efc9560a1d748d45216ed7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 652249cc95ecae99c1b4de0514117ee5c00a1911e00c85c4c236a15f9593493dadb92cd0e4c6311cd8d930f4fe40ca51fa790e0b03154a678795b3ada931c814
|
|
7
|
+
data.tar.gz: 030563f1521442ab306ff67e8bf454c7729ce711f35a02371d3b69da3d1c36e578cf3ad99b10b3f6dd3164c359cc6977511393a1e69a2a81d321d376e23a9fff
|
data/bin/h-cpr
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require "hiiro"
|
|
4
|
+
require "json"
|
|
5
|
+
|
|
6
|
+
Hiiro.load_env
|
|
7
|
+
|
|
8
|
+
output = `gh pr view --json number 2>/dev/null`.strip
|
|
9
|
+
if output.empty?
|
|
10
|
+
STDERR.puts "No PR found for current branch"
|
|
11
|
+
exit 1
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
pr_number = begin
|
|
15
|
+
JSON.parse(output)['number'].to_s
|
|
16
|
+
rescue JSON::ParserError
|
|
17
|
+
STDERR.puts "Could not parse PR info"
|
|
18
|
+
exit 1
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
if ARGV.empty?
|
|
22
|
+
exec('h', 'pr', 'view', pr_number)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
subcmd, *rest = ARGV
|
|
26
|
+
exec('h', 'pr', subcmd, pr_number, *rest)
|
data/bin/h-pr
CHANGED
|
@@ -268,6 +268,87 @@ class PinnedPRManager
|
|
|
268
268
|
end
|
|
269
269
|
|
|
270
270
|
|
|
271
|
+
def batch_fetch_pr_info(pr_numbers)
|
|
272
|
+
return {} if pr_numbers.empty?
|
|
273
|
+
|
|
274
|
+
# Build GraphQL query to fetch multiple PRs at once
|
|
275
|
+
pr_queries = pr_numbers.map.with_index do |num, idx|
|
|
276
|
+
<<~GRAPHQL.strip
|
|
277
|
+
pr#{idx}: pullRequest(number: #{num}) {
|
|
278
|
+
number
|
|
279
|
+
title
|
|
280
|
+
url
|
|
281
|
+
headRefName
|
|
282
|
+
state
|
|
283
|
+
isDraft
|
|
284
|
+
mergeable
|
|
285
|
+
reviewDecision
|
|
286
|
+
statusCheckRollup {
|
|
287
|
+
contexts(last: 100) {
|
|
288
|
+
nodes {
|
|
289
|
+
... on CheckRun {
|
|
290
|
+
conclusion
|
|
291
|
+
status
|
|
292
|
+
}
|
|
293
|
+
... on StatusContext {
|
|
294
|
+
state
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
reviews(last: 50) {
|
|
300
|
+
nodes {
|
|
301
|
+
author {
|
|
302
|
+
login
|
|
303
|
+
}
|
|
304
|
+
state
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
GRAPHQL
|
|
309
|
+
end
|
|
310
|
+
|
|
311
|
+
query = <<~GRAPHQL
|
|
312
|
+
query {
|
|
313
|
+
repository(owner: "instacart", name: "carrot") {
|
|
314
|
+
#{pr_queries.join("\n")}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
GRAPHQL
|
|
318
|
+
|
|
319
|
+
result = `gh api graphql -f query='#{query.gsub("'", "'\\''")}' 2>/dev/null`
|
|
320
|
+
return {} if result.empty?
|
|
321
|
+
|
|
322
|
+
data = JSON.parse(result)
|
|
323
|
+
repo_data = data.dig('data', 'repository')
|
|
324
|
+
return {} unless repo_data
|
|
325
|
+
|
|
326
|
+
# Convert GraphQL response to hash keyed by PR number
|
|
327
|
+
pr_info_by_number = {}
|
|
328
|
+
pr_numbers.each_with_index do |num, idx|
|
|
329
|
+
pr_data = repo_data["pr#{idx}"]
|
|
330
|
+
next unless pr_data
|
|
331
|
+
|
|
332
|
+
# Transform GraphQL response to match gh pr view format
|
|
333
|
+
pr_info_by_number[num] = {
|
|
334
|
+
'number' => pr_data['number'],
|
|
335
|
+
'title' => pr_data['title'],
|
|
336
|
+
'url' => pr_data['url'],
|
|
337
|
+
'headRefName' => pr_data['headRefName'],
|
|
338
|
+
'state' => pr_data['state'],
|
|
339
|
+
'isDraft' => pr_data['isDraft'],
|
|
340
|
+
'mergeable' => pr_data['mergeable'],
|
|
341
|
+
'reviewDecision' => pr_data['reviewDecision'],
|
|
342
|
+
'statusCheckRollup' => pr_data.dig('statusCheckRollup', 'contexts', 'nodes'),
|
|
343
|
+
'reviews' => pr_data.dig('reviews', 'nodes') || []
|
|
344
|
+
}
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
pr_info_by_number
|
|
348
|
+
rescue JSON::ParserError, StandardError
|
|
349
|
+
{}
|
|
350
|
+
end
|
|
351
|
+
|
|
271
352
|
def refresh_all_status(prs, force: false)
|
|
272
353
|
prs_to_refresh = prs.select { |pr| needs_refresh?(pr, force: force) }
|
|
273
354
|
|
|
@@ -276,7 +357,23 @@ class PinnedPRManager
|
|
|
276
357
|
return prs
|
|
277
358
|
end
|
|
278
359
|
|
|
279
|
-
prs_to_refresh.
|
|
360
|
+
pr_numbers = prs_to_refresh.map { |pr| pr['number'] }
|
|
361
|
+
infos = batch_fetch_pr_info(pr_numbers)
|
|
362
|
+
|
|
363
|
+
prs_to_refresh.each do |pr|
|
|
364
|
+
info = infos[pr['number']]
|
|
365
|
+
next unless info
|
|
366
|
+
|
|
367
|
+
pr['state'] = info['state']
|
|
368
|
+
pr['title'] = info['title']
|
|
369
|
+
pr['checks'] = summarize_checks(info['statusCheckRollup'])
|
|
370
|
+
pr['reviews'] = summarize_reviews(info['reviews'])
|
|
371
|
+
pr['review_decision'] = info['reviewDecision']
|
|
372
|
+
pr['is_draft'] = info['isDraft']
|
|
373
|
+
pr['mergeable'] = info['mergeable']
|
|
374
|
+
pr['last_checked'] = Time.now.iso8601
|
|
375
|
+
end
|
|
376
|
+
|
|
280
377
|
prs
|
|
281
378
|
end
|
|
282
379
|
|
|
@@ -353,15 +450,18 @@ class PinnedPRManager
|
|
|
353
450
|
""
|
|
354
451
|
end
|
|
355
452
|
|
|
356
|
-
reviews_str =
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
453
|
+
reviews_str =
|
|
454
|
+
if pr['reviews']
|
|
455
|
+
reviews = pr['reviews'].map do |r|
|
|
456
|
+
parts = []
|
|
457
|
+
parts << "#{r['approved']} approved" if r['approved'] > 0
|
|
458
|
+
parts << "#{r['changes_requested']} changes" if r['changes_requested'] > 0
|
|
459
|
+
parts.empty? ? "" : " | #{parts.join(', ')}"
|
|
460
|
+
end
|
|
461
|
+
reviews.join('; ')
|
|
462
|
+
else
|
|
463
|
+
""
|
|
464
|
+
end
|
|
365
465
|
|
|
366
466
|
"#{num} #{state_icon} ##{pr['number']} #{pr['title']}#{checks_str}#{reviews_str}".strip
|
|
367
467
|
end
|
|
@@ -436,34 +536,55 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
|
|
|
436
536
|
manager = PRManager.new(self)
|
|
437
537
|
pinned_manager = PinnedPRManager.new
|
|
438
538
|
|
|
539
|
+
resolve_pr = ->(ref) {
|
|
540
|
+
if ref.nil?
|
|
541
|
+
pinned = pinned_manager.load_pinned
|
|
542
|
+
if pinned.empty?
|
|
543
|
+
STDERR.puts "No pinned PRs. Use a PR number or 'h pr pin' to track PRs."
|
|
544
|
+
return nil
|
|
545
|
+
end
|
|
546
|
+
lines = pinned.each_with_index.each_with_object({}) do |(pr, idx), h|
|
|
547
|
+
h[pinned_manager.display_pinned(pr, idx)] = pr['number'].to_s
|
|
548
|
+
end
|
|
549
|
+
return fuzzyfind_from_map(lines)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
if (pin_value = pins.get(ref.to_s))
|
|
553
|
+
return pin_value
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
pinned = pinned_manager.load_pinned
|
|
557
|
+
|
|
558
|
+
if pinned.any? { |pr| pr['number'].to_s == ref.to_s }
|
|
559
|
+
return ref.to_s
|
|
560
|
+
end
|
|
561
|
+
|
|
562
|
+
if ref.to_s =~ /^\d+$/ && ref.to_i > 0
|
|
563
|
+
idx = ref.to_i - 1
|
|
564
|
+
return pinned[idx]['number'].to_s if idx < pinned.length
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
ref.to_s
|
|
568
|
+
}
|
|
569
|
+
|
|
439
570
|
watch_block = ->(original_pr_number=nil, *watch_args) {
|
|
440
571
|
watch = get_value(:watch)
|
|
441
572
|
fail_fast = get_value(:fail_fast)
|
|
442
573
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if !original_pr_number.nil? && pin_value = pins.get(original_pr_number)
|
|
446
|
-
pr_valid = true
|
|
447
|
-
pr_number = pin_value
|
|
448
|
-
end
|
|
449
|
-
|
|
450
|
-
pr_args = [pr_valid ? pr_number : original_pr_number].compact
|
|
451
|
-
check_args = [*pr_args, *watch_args]
|
|
574
|
+
pr_number = resolve_pr.call(original_pr_number)
|
|
575
|
+
return unless pr_number
|
|
452
576
|
|
|
453
577
|
base_cmd = %w[gh pr checks]
|
|
454
578
|
base_cmd << '--watch' if watch
|
|
455
579
|
base_cmd << '--fail-fast' if fail_fast
|
|
456
580
|
|
|
457
|
-
command = [
|
|
458
|
-
*base_cmd,
|
|
459
|
-
*check_args,
|
|
460
|
-
]
|
|
581
|
+
command = [*base_cmd, pr_number, *watch_args]
|
|
461
582
|
|
|
462
|
-
puts command: command, base_cmd: base_cmd, args:
|
|
583
|
+
puts command: command, base_cmd: base_cmd, args: [pr_number, *watch_args];
|
|
463
584
|
|
|
464
585
|
result = system(*command)
|
|
465
586
|
|
|
466
|
-
pr_info = JSON.parse(`gh pr view #{
|
|
587
|
+
pr_info = JSON.parse(`gh pr view #{pr_number} --json url,number,title`)
|
|
467
588
|
pr_url = pr_info['url']
|
|
468
589
|
pr_num = pr_info['number']
|
|
469
590
|
pr_title = pr_info['title']
|
|
@@ -508,8 +629,14 @@ Hiiro.run(*ARGV, plugins: [Pins]) do
|
|
|
508
629
|
add_subcmd(:edit) { system(ENV['EDITOR'] || 'nvim', __FILE__) }
|
|
509
630
|
add_subcmd(:save) { |pr_number=nil| manager.save(pr_number) }
|
|
510
631
|
add_subcmd(:current) { manager.current }
|
|
511
|
-
add_subcmd(:open) { |pr_number=nil|
|
|
512
|
-
|
|
632
|
+
add_subcmd(:open) { |pr_number=nil|
|
|
633
|
+
pr_number = resolve_pr.call(pr_number)
|
|
634
|
+
manager.open(pr_number) if pr_number
|
|
635
|
+
}
|
|
636
|
+
add_subcmd(:view) { |pr_number=nil|
|
|
637
|
+
pr_number = resolve_pr.call(pr_number)
|
|
638
|
+
manager.view(pr_number) if pr_number
|
|
639
|
+
}
|
|
513
640
|
|
|
514
641
|
add_subcmd(:select) do |*args|
|
|
515
642
|
# Get my open PRs
|
data/lib/hiiro/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: hiiro
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.161
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Joshua Toyota
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: pry
|
|
@@ -90,6 +89,7 @@ files:
|
|
|
90
89
|
- bin/h-claude
|
|
91
90
|
- bin/h-commit
|
|
92
91
|
- bin/h-config
|
|
92
|
+
- bin/h-cpr
|
|
93
93
|
- bin/h-jumplist
|
|
94
94
|
- bin/h-link
|
|
95
95
|
- bin/h-misc
|
|
@@ -156,12 +156,12 @@ files:
|
|
|
156
156
|
- plugins/pins.rb
|
|
157
157
|
- plugins/project.rb
|
|
158
158
|
- record-demo.sh
|
|
159
|
-
-
|
|
160
|
-
-
|
|
161
|
-
-
|
|
162
|
-
-
|
|
163
|
-
-
|
|
164
|
-
-
|
|
159
|
+
- script/compare
|
|
160
|
+
- script/install
|
|
161
|
+
- script/publish
|
|
162
|
+
- script/sync
|
|
163
|
+
- script/test
|
|
164
|
+
- script/update
|
|
165
165
|
- slides.md
|
|
166
166
|
homepage: https://github.com/unixsuperhero/hiiro
|
|
167
167
|
licenses:
|
|
@@ -170,7 +170,6 @@ metadata:
|
|
|
170
170
|
homepage_uri: https://github.com/unixsuperhero/hiiro
|
|
171
171
|
source_code_uri: https://github.com/unixsuperhero/hiiro
|
|
172
172
|
changelog_uri: https://github.com/unixsuperhero/hiiro/blob/main/CHANGELOG.md
|
|
173
|
-
post_install_message:
|
|
174
173
|
rdoc_options: []
|
|
175
174
|
require_paths:
|
|
176
175
|
- lib
|
|
@@ -185,8 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
185
184
|
- !ruby/object:Gem::Version
|
|
186
185
|
version: '0'
|
|
187
186
|
requirements: []
|
|
188
|
-
rubygems_version:
|
|
189
|
-
signing_key:
|
|
187
|
+
rubygems_version: 4.0.3
|
|
190
188
|
specification_version: 4
|
|
191
189
|
summary: A lightweight CLI framework for Ruby
|
|
192
190
|
test_files: []
|
/data/{scripts → script}/compare
RENAMED
|
File without changes
|
/data/{scripts → script}/install
RENAMED
|
File without changes
|
/data/{scripts → script}/publish
RENAMED
|
File without changes
|
/data/{scripts → script}/sync
RENAMED
|
File without changes
|
/data/{scripts → script}/test
RENAMED
|
File without changes
|
/data/{scripts → script}/update
RENAMED
|
File without changes
|