git-markdown 0.1.7 → 0.1.8
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 +3 -3
- data/lib/git/markdown/api/client.rb +11 -0
- data/lib/git/markdown/configuration.rb +11 -1
- data/lib/git/markdown/markdown/generator.rb +2 -2
- data/lib/git/markdown/models/comment.rb +6 -0
- data/lib/git/markdown/providers/github/graphql.rb +95 -0
- data/lib/git/markdown/providers/github.rb +35 -6
- data/lib/git/markdown/version.rb +1 -1
- data/lib/git_markdown.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 06b5aeed8786c57bb26b159375e7dcbb449e12b2ef4068f5aade847e1ffb809b
|
|
4
|
+
data.tar.gz: 3c60e2b038a66ca27183e27c54efba8bc05a0cd0395f3c9ce6f735e401840702
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d5156133e179f31b2271f67caed36f9d90dfc0404cb25134097ae6a208861249959f6a3c4aefa7f1f7649d5f1ab25db11fb352de6bd2c11df8962139b2d2c327
|
|
7
|
+
data.tar.gz: cbd01023d035fea4d1f82759e8d829d645ddbcbbf40fa8d5acaf5eff1a777861a9566d2c13dd078efe1abbe3995abd00b2d1e6ba8d9c3f2e364eebf5ae0aae2d
|
data/CHANGELOG.md
CHANGED
|
@@ -5,9 +5,9 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
-
## [0.1.
|
|
8
|
+
## [0.1.8] - 2026-03-20
|
|
9
9
|
|
|
10
|
-
### <!--
|
|
11
|
-
-
|
|
10
|
+
### <!-- 0 -->🚀 Features
|
|
11
|
+
- filter GitHub-native resolved comments via GraphQL
|
|
12
12
|
|
|
13
13
|
|
|
@@ -17,6 +17,17 @@ module GitMarkdown
|
|
|
17
17
|
Response.new(response)
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def post(path, body = {})
|
|
21
|
+
uri = build_uri(path, {})
|
|
22
|
+
request = Net::HTTP::Post.new(uri)
|
|
23
|
+
set_headers(request)
|
|
24
|
+
request["Content-Type"] = "application/json"
|
|
25
|
+
request.body = JSON.generate(body)
|
|
26
|
+
|
|
27
|
+
response = http_request(uri, request)
|
|
28
|
+
Response.new(response)
|
|
29
|
+
end
|
|
30
|
+
|
|
20
31
|
private
|
|
21
32
|
|
|
22
33
|
def build_uri(path, params)
|
|
@@ -7,13 +7,14 @@ module GitMarkdown
|
|
|
7
7
|
XDG_CONFIG_HOME = ENV.fetch("XDG_CONFIG_HOME", File.expand_path("~/.config"))
|
|
8
8
|
DEFAULT_PROVIDER = :github
|
|
9
9
|
|
|
10
|
-
attr_accessor :token, :provider, :api_url, :output_dir, :default_status
|
|
10
|
+
attr_accessor :token, :provider, :api_url, :graphql_url, :output_dir, :default_status
|
|
11
11
|
|
|
12
12
|
def initialize
|
|
13
13
|
@provider = DEFAULT_PROVIDER
|
|
14
14
|
@output_dir = Dir.pwd
|
|
15
15
|
@default_status = :unresolved
|
|
16
16
|
@api_url = nil
|
|
17
|
+
@graphql_url = nil
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def self.load
|
|
@@ -24,6 +25,7 @@ module GitMarkdown
|
|
|
24
25
|
load_from_file if config_file_exist?
|
|
25
26
|
resolve_credentials
|
|
26
27
|
resolve_api_url if api_url.nil?
|
|
28
|
+
resolve_graphql_url if graphql_url.nil?
|
|
27
29
|
self
|
|
28
30
|
end
|
|
29
31
|
|
|
@@ -67,6 +69,7 @@ module GitMarkdown
|
|
|
67
69
|
)
|
|
68
70
|
@provider = config[:provider] if config[:provider]
|
|
69
71
|
@api_url = config[:api_url] if config[:api_url]
|
|
72
|
+
@graphql_url = config[:graphql_url] if config[:graphql_url]
|
|
70
73
|
@output_dir = config[:output_dir] if config[:output_dir]
|
|
71
74
|
@default_status = config[:default_status].to_sym if config[:default_status]
|
|
72
75
|
end
|
|
@@ -81,10 +84,17 @@ module GitMarkdown
|
|
|
81
84
|
end
|
|
82
85
|
end
|
|
83
86
|
|
|
87
|
+
def resolve_graphql_url
|
|
88
|
+
@graphql_url = ENV.fetch("GITHUB_GRAPHQL_URL") do
|
|
89
|
+
(@provider == :github) ? "https://api.github.com/graphql" : nil
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
84
93
|
def config_to_yaml
|
|
85
94
|
{
|
|
86
95
|
provider: @provider,
|
|
87
96
|
api_url: @api_url,
|
|
97
|
+
graphql_url: @graphql_url,
|
|
88
98
|
output_dir: @output_dir,
|
|
89
99
|
default_status: @default_status
|
|
90
100
|
}.to_yaml
|
|
@@ -50,9 +50,9 @@ module GitMarkdown
|
|
|
50
50
|
def include_comment?(comment)
|
|
51
51
|
case @status_filter
|
|
52
52
|
when :unresolved
|
|
53
|
-
!comment.body.include?("[resolved]") && !comment.body.include?("[done]")
|
|
53
|
+
!comment.resolved? && !comment.body.include?("[resolved]") && !comment.body.include?("[done]")
|
|
54
54
|
when :resolved
|
|
55
|
-
comment.body.include?("[resolved]") || comment.body.include?("[done]")
|
|
55
|
+
comment.resolved? || comment.body.include?("[resolved]") || comment.body.include?("[done]")
|
|
56
56
|
else
|
|
57
57
|
true
|
|
58
58
|
end
|
|
@@ -4,6 +4,7 @@ module GitMarkdown
|
|
|
4
4
|
module Models
|
|
5
5
|
class Comment
|
|
6
6
|
attr_reader :id, :body, :author, :path, :line, :html_url, :created_at, :updated_at, :in_reply_to_id
|
|
7
|
+
attr_accessor :resolved
|
|
7
8
|
|
|
8
9
|
def initialize(attrs = {})
|
|
9
10
|
@id = attrs[:id]
|
|
@@ -15,6 +16,7 @@ module GitMarkdown
|
|
|
15
16
|
@created_at = attrs[:created_at]
|
|
16
17
|
@updated_at = attrs[:updated_at]
|
|
17
18
|
@in_reply_to_id = attrs[:in_reply_to_id]
|
|
19
|
+
@resolved = attrs.fetch(:resolved, false)
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
def self.from_api(data)
|
|
@@ -38,6 +40,10 @@ module GitMarkdown
|
|
|
38
40
|
def reply?
|
|
39
41
|
!@in_reply_to_id.nil?
|
|
40
42
|
end
|
|
43
|
+
|
|
44
|
+
def resolved?
|
|
45
|
+
@resolved == true
|
|
46
|
+
end
|
|
41
47
|
end
|
|
42
48
|
end
|
|
43
49
|
end
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module GitMarkdown
|
|
4
|
+
module Providers
|
|
5
|
+
class GitHub
|
|
6
|
+
class Graphql
|
|
7
|
+
RESOLVED_STATE_QUERY = <<~GRAPHQL
|
|
8
|
+
query($owner: String!, $repo: String!, $number: Int!, $threadsAfter: String, $commentsAfter: String) {
|
|
9
|
+
repository(owner: $owner, name: $repo) {
|
|
10
|
+
pullRequest(number: $number) {
|
|
11
|
+
reviewThreads(first: 100, after: $threadsAfter) {
|
|
12
|
+
pageInfo {
|
|
13
|
+
hasNextPage
|
|
14
|
+
endCursor
|
|
15
|
+
}
|
|
16
|
+
nodes {
|
|
17
|
+
isResolved
|
|
18
|
+
comments(first: 100, after: $commentsAfter) {
|
|
19
|
+
pageInfo {
|
|
20
|
+
hasNextPage
|
|
21
|
+
endCursor
|
|
22
|
+
}
|
|
23
|
+
nodes {
|
|
24
|
+
databaseId
|
|
25
|
+
body
|
|
26
|
+
path
|
|
27
|
+
line
|
|
28
|
+
createdAt
|
|
29
|
+
updatedAt
|
|
30
|
+
author {
|
|
31
|
+
login
|
|
32
|
+
}
|
|
33
|
+
replyTo {
|
|
34
|
+
databaseId
|
|
35
|
+
}
|
|
36
|
+
url
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
GRAPHQL
|
|
45
|
+
|
|
46
|
+
def initialize(config)
|
|
47
|
+
@config = config
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def fetch_resolved_states(owner, repo, number)
|
|
51
|
+
resolved_ids = Set.new
|
|
52
|
+
threads_after = nil
|
|
53
|
+
|
|
54
|
+
loop do
|
|
55
|
+
response = client.post("", {
|
|
56
|
+
query: RESOLVED_STATE_QUERY,
|
|
57
|
+
variables: {owner: owner, repo: repo, number: number,
|
|
58
|
+
threadsAfter: threads_after}
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
raise ApiError, "GraphQL request failed: #{response.error_message}" unless response.success?
|
|
62
|
+
|
|
63
|
+
data = response.data
|
|
64
|
+
threads_data = data.dig("data", "repository", "pullRequest", "reviewThreads")
|
|
65
|
+
break unless threads_data
|
|
66
|
+
|
|
67
|
+
threads_data["nodes"].each do |thread|
|
|
68
|
+
next unless thread["isResolved"]
|
|
69
|
+
|
|
70
|
+
thread["comments"]["nodes"].each do |comment|
|
|
71
|
+
resolved_ids.add(comment["databaseId"]) if comment["databaseId"]
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
threads_page = threads_data["pageInfo"]
|
|
76
|
+
break unless threads_page["hasNextPage"]
|
|
77
|
+
|
|
78
|
+
threads_after = threads_page["endCursor"]
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
resolved_ids
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def client
|
|
87
|
+
@client ||= Api::Client.new(
|
|
88
|
+
base_url: @config.graphql_url,
|
|
89
|
+
token: @config.token
|
|
90
|
+
)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -21,23 +21,36 @@ module GitMarkdown
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def fetch_reviews(owner, repo, number)
|
|
24
|
+
resolved_ids = fetch_resolved_comment_ids(owner, repo, number)
|
|
25
|
+
|
|
24
26
|
path = "/repos/#{owner}/#{repo}/pulls/#{number}/reviews"
|
|
25
27
|
reviews = fetch_all_pages(path)
|
|
26
28
|
|
|
29
|
+
all_pr_comments = fetch_all_pr_comments(owner, repo, number)
|
|
30
|
+
|
|
27
31
|
reviews.map do |review_data|
|
|
28
32
|
review = Models::Review.from_api(review_data)
|
|
29
|
-
review.comments =
|
|
33
|
+
review.comments = all_pr_comments
|
|
34
|
+
.select { |c| c["pull_request_review_id"] == review.id }
|
|
35
|
+
.map do |data|
|
|
36
|
+
comment = Models::Comment.from_api(data)
|
|
37
|
+
comment.resolved = resolved_ids.include?(comment.id)
|
|
38
|
+
comment
|
|
39
|
+
end
|
|
30
40
|
review
|
|
31
41
|
end
|
|
32
42
|
end
|
|
33
43
|
|
|
34
|
-
def fetch_review_comments(owner, repo, review_id)
|
|
35
|
-
|
|
36
|
-
all_comments = fetch_all_pages(path)
|
|
44
|
+
def fetch_review_comments(owner, repo, review_id, resolved_ids = Set.new)
|
|
45
|
+
all_pr_comments = fetch_all_pr_comments(owner, repo)
|
|
37
46
|
|
|
38
|
-
|
|
47
|
+
all_pr_comments
|
|
39
48
|
.select { |c| c["pull_request_review_id"] == review_id }
|
|
40
|
-
.map
|
|
49
|
+
.map do |data|
|
|
50
|
+
comment = Models::Comment.from_api(data)
|
|
51
|
+
comment.resolved = resolved_ids.include?(comment.id)
|
|
52
|
+
comment
|
|
53
|
+
end
|
|
41
54
|
end
|
|
42
55
|
|
|
43
56
|
private
|
|
@@ -49,6 +62,22 @@ module GitMarkdown
|
|
|
49
62
|
)
|
|
50
63
|
end
|
|
51
64
|
|
|
65
|
+
def graphql_client
|
|
66
|
+
@graphql_client ||= Graphql.new(@config)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def fetch_resolved_comment_ids(owner, repo, number)
|
|
70
|
+
graphql_client.fetch_resolved_states(owner, repo, number)
|
|
71
|
+
rescue ApiError
|
|
72
|
+
Set.new
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def fetch_all_pr_comments(owner, repo, _number = nil)
|
|
76
|
+
@all_pr_comments ||= {}
|
|
77
|
+
key = "#{owner}/#{repo}"
|
|
78
|
+
@all_pr_comments[key] ||= fetch_all_pages("/repos/#{owner}/#{repo}/pulls/comments")
|
|
79
|
+
end
|
|
80
|
+
|
|
52
81
|
def fetch_all_pages(path, params = {})
|
|
53
82
|
results = []
|
|
54
83
|
page = 1
|
data/lib/git/markdown/version.rb
CHANGED
data/lib/git_markdown.rb
CHANGED
|
@@ -15,6 +15,7 @@ require_relative "git/markdown/credentials"
|
|
|
15
15
|
require_relative "git/markdown/remote_parser"
|
|
16
16
|
require_relative "git/markdown/providers/base"
|
|
17
17
|
require_relative "git/markdown/providers/github"
|
|
18
|
+
require_relative "git/markdown/providers/github/graphql"
|
|
18
19
|
require_relative "git/markdown/api/client"
|
|
19
20
|
require_relative "git/markdown/api/response"
|
|
20
21
|
require_relative "git/markdown/models/pull_request"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: git-markdown
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Paulo Fidalgo
|
|
@@ -123,6 +123,7 @@ files:
|
|
|
123
123
|
- lib/git/markdown/models/review.rb
|
|
124
124
|
- lib/git/markdown/providers/base.rb
|
|
125
125
|
- lib/git/markdown/providers/github.rb
|
|
126
|
+
- lib/git/markdown/providers/github/graphql.rb
|
|
126
127
|
- lib/git/markdown/remote_parser.rb
|
|
127
128
|
- lib/git/markdown/version.rb
|
|
128
129
|
- lib/git_markdown.rb
|
|
@@ -151,7 +152,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
151
152
|
- !ruby/object:Gem::Version
|
|
152
153
|
version: '0'
|
|
153
154
|
requirements: []
|
|
154
|
-
rubygems_version: 4.0.
|
|
155
|
+
rubygems_version: 4.0.6
|
|
155
156
|
specification_version: 4
|
|
156
157
|
summary: Convert GitHub PRs to Markdown for local AI code review
|
|
157
158
|
test_files: []
|