Setting the file. One moment.
Query Discussions · GitHub Discussion Query · github/gh-aw · Skills Docs
ContentsBack to the top of the page
query-discussions.py
query-discussions.py
Python · 127 lines · 5 KB
json
17 import subprocess
18 import sys
19 from typing import Optional
20
21
22 def _run_subprocess (cmd: list , error_prefix: str , not_found_message: str , input_data: Optional[ str ] = None ) -> str :
23 """Run a subprocess command, printing a consistent error and exiting on failure."""
24 try :
25 result = subprocess.run(cmd, input = input_data, capture_output = True , text = True , check = True )
26 return result.stdout
27 except subprocess.CalledProcessError as e:
28 print ( f " { error_prefix } : { e.stderr } " , file = sys.stderr)
29 sys.exit( 1 )
30 except FileNotFoundError :
31 print (not_found_message, file = sys.stderr)
32 sys.exit( 1 )
33
34
35 def run_gh_command (repo: Optional[ str ], limit: int ) -> str :
36 """Run gh discussion list command and return JSON output."""
37 json_fields = "number,title,author,createdAt,updatedAt,body,category,labels,comments,answer,url"
38
39 cmd = [ "gh" , "discussion" , "list" , "--limit" , str (limit), "--json" , json_fields]
40
41 if repo:
42 cmd.extend([ "--repo" , repo])
43
44 return _run_subprocess(cmd, "Error running gh command" , "Error: gh CLI not found. Please install GitHub CLI." )
45
46
47 def apply_jq_filter (data: str , jq_filter: str ) -> str :
48 """Apply jq filter to JSON data."""
49 return _run_subprocess(
50 [ "jq" , jq_filter],
51 "Error applying jq filter" ,
52 "Error: jq not found. Please install jq." ,
53 input_data = data,
54 )
55
56
57 def generate_schema_response (data: str ) -> str :
58 """Generate schema and metadata response when no jq filter is provided."""
59 try :
60 parsed = json.loads(data)
61 item_count = len (parsed) if isinstance (parsed, list ) else 0
62 data_size = len (data)
63 except json.JSONDecodeError:
64 item_count = 0
65 data_size = len (data)
66
67 schema = {
68 "message" : "No --jq filter provided. Use --jq to filter and retrieve data." ,
69 "item_count" : item_count,
70 "data_size_bytes" : data_size,
71 "schema" : {
72 "type" : "array" ,
73 "description" : "Array of discussion objects" ,
74 "item_fields" : {
75 "number" : "integer - Discussion number" ,
76 "title" : "string - Discussion title" ,
77 "author" : "object - Author info with login field" ,
78 "createdAt" : "string - ISO timestamp of creation" ,
79 "updatedAt" : "string - ISO timestamp of last update" ,
80 "body" : "string - Discussion body content" ,
81 "category" : "object - Category info with name field" ,
82 "labels" : "array - Array of label objects with name field" ,
83 "comments" : "object - Comments info with totalCount field" ,
84 "answer" : "object|null - Accepted answer if exists" ,
85 "url" : "string - Discussion URL"
86 }
87 },
88 "suggested_queries" : [
89 { "description" : "Get all data" , "query" : "." },
90 { "description" : "Get discussion numbers and titles" , "query" : ".[] | {number, title}" },
91 { "description" : "Get discussions by author" , "query" : '.[] | select(.author.login == "USERNAME")' },
92 { "description" : "Get discussions in category" , "query" : '.[] | select(.category.name == "Ideas")' },
93 { "description" : "Get answered discussions" , "query" : ".[] | select(.answer != null)" },
94 { "description" : "Get unanswered discussions" , "query" : ".[] | select(.answer == null) | {number, title, category: .category.name}" },
95 { "description" : "Get discussions with labels" , "query" : ".[] | {number, title, labels: [.labels[].name]}" },
96 { "description" : "Count by category" , "query" : "group_by(.category.name) | map( {category: .[0].category.name, count: length} )" }
97 ]
98 }
99
100 return json.dumps(schema, indent = 2 )
101
102
103 def main ():
104 parser = argparse.ArgumentParser(
105 description = "Query GitHub discussions with jq filtering support" ,
106 formatter_class = argparse.RawDescriptionHelpFormatter
107 )
108 parser.add_argument( "--repo" , help = "Repository to query (default: current repo)" )
109 parser.add_argument( "--limit" , type = int , default = 30 , help = "Maximum number of discussions (default: 30)" )
110 parser.add_argument( "--jq" , dest = "jq_filter" , help = "jq filter expression to apply to output" )
111
112 args = parser.parse_args()
113
114 # Get data from gh CLI
115 output = run_gh_command(args.repo, args.limit)
116
117 # Apply jq filter if provided, otherwise return schema
118 if args.jq_filter:
119 result = apply_jq_filter(output, args.jq_filter)
120 print (result, end = '' )
121 else :
122 result = generate_schema_response(output)
123 print (result)
124
125
126 if __name__ == "__main__" :
127 main()