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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7b54256dcd569639e4995d505d50c18635935bf4a397aab6b61ab9d03354cf60
4
- data.tar.gz: da76e2e67d339131b9e0044f2ebd7069ef6dfadbcc27ac0d84fbb1e194792b0a
3
+ metadata.gz: 06b5aeed8786c57bb26b159375e7dcbb449e12b2ef4068f5aade847e1ffb809b
4
+ data.tar.gz: 3c60e2b038a66ca27183e27c54efba8bc05a0cd0395f3c9ce6f735e401840702
5
5
  SHA512:
6
- metadata.gz: 10de61bf0523a66e46aab43b637d7132d76c4bdbb878ce94c900c4a319d5c0841d2329166b48922134ab42f10f308d4e689efc2bdeb25da9ace585b836231113
7
- data.tar.gz: 65ca8d4ec9d25fbd51a7442827551beaf50d79974b2f9d07327d0860d75ac9fa7a1ed093ac3eb0aa178aaf2ecb1541699b5c72c95c6b4533f8eae34b6f14d981
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.7] - 2026-02-08
8
+ ## [0.1.8] - 2026-03-20
9
9
 
10
- ### <!-- 1 -->🐛 Bug Fixes
11
- - read version from GitMarkdown::VERSION constant
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 = fetch_review_comments(owner, repo, review.id)
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
- path = "/repos/#{owner}/#{repo}/pulls/comments"
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
- all_comments
47
+ all_pr_comments
39
48
  .select { |c| c["pull_request_review_id"] == review_id }
40
- .map { |data| Models::Comment.from_api(data) }
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module GitMarkdown
4
- VERSION = "0.1.7"
4
+ VERSION = "0.1.8"
5
5
  end
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.7
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.3
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: []