Skip to content

Commit eb4945e

Browse files
committed
Add optional since filter, to get issues based on last update to issue
1 parent f90251f commit eb4945e

File tree

1 file changed

+55
-23
lines changed

1 file changed

+55
-23
lines changed

pkg/github/issues.go

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -56,34 +56,60 @@ type IssueQueryFragment struct {
5656
TotalCount int
5757
}
5858

59+
// ListIssuesQueryNoLabels is the query structure for fetching issues without label filtering.
60+
type ListIssuesQuery struct {
61+
Repository struct {
62+
Issues IssueQueryFragment `graphql:"issues(first: $first, after: $after, states: $states, orderBy: {field: $orderBy, direction: $direction})"`
63+
} `graphql:"repository(owner: $owner, name: $repo)"`
64+
}
65+
5966
// ListIssuesQuery is the root query structure for fetching issues with optional label filtering.
60-
type ListIssuesQueryType struct {
67+
type ListIssuesQueryTypeWithLabels struct {
6168
Repository struct {
6269
Issues IssueQueryFragment `graphql:"issues(first: $first, after: $after, labels: $labels, states: $states, orderBy: {field: $orderBy, direction: $direction})"`
6370
} `graphql:"repository(owner: $owner, name: $repo)"`
6471
}
6572

66-
// ListIssuesQueryNoLabels is the query structure for fetching issues without label filtering.
67-
type ListIssuesQueryNoLabelsType struct {
73+
// ListIssuesQueryWithSince is the query structure for fetching issues without label filtering but with since filtering.
74+
type ListIssuesQueryWithSince struct {
6875
Repository struct {
69-
Issues IssueQueryFragment `graphql:"issues(first: $first, after: $after, states: $states, orderBy: {field: $orderBy, direction: $direction})"`
76+
Issues IssueQueryFragment `graphql:"issues(first: $first, after: $after, states: $states, orderBy: {field: $orderBy, direction: $direction}, filterBy: {since: $since})"`
77+
} `graphql:"repository(owner: $owner, name: $repo)"`
78+
}
79+
80+
// ListIssuesQueryTypeWithLabelsWithSince is the query structure for fetching issues with both label and since filtering.
81+
type ListIssuesQueryTypeWithLabelsWithSince struct {
82+
Repository struct {
83+
Issues IssueQueryFragment `graphql:"issues(first: $first, after: $after, labels: $labels, states: $states, orderBy: {field: $orderBy, direction: $direction}, filterBy: {since: $since})"`
7084
} `graphql:"repository(owner: $owner, name: $repo)"`
7185
}
7286

73-
// Implement the interface for both query types
74-
func (q *ListIssuesQueryType) GetIssueFragment() IssueQueryFragment {
87+
// Implement the interface for all query types
88+
func (q *ListIssuesQueryTypeWithLabels) GetIssueFragment() IssueQueryFragment {
89+
return q.Repository.Issues
90+
}
91+
92+
func (q *ListIssuesQuery) GetIssueFragment() IssueQueryFragment {
7593
return q.Repository.Issues
7694
}
7795

78-
func (q *ListIssuesQueryNoLabelsType) GetIssueFragment() IssueQueryFragment {
96+
func (q *ListIssuesQueryWithSince) GetIssueFragment() IssueQueryFragment {
7997
return q.Repository.Issues
8098
}
8199

82-
func getIssueQueryType(hasLabels bool) any {
83-
if hasLabels {
84-
return &ListIssuesQueryType{}
100+
func (q *ListIssuesQueryTypeWithLabelsWithSince) GetIssueFragment() IssueQueryFragment {
101+
return q.Repository.Issues
102+
}
103+
104+
func getIssueQueryType(hasLabels bool, hasSince bool) any {
105+
if hasLabels && hasSince {
106+
return &ListIssuesQueryTypeWithLabelsWithSince{}
107+
} else if hasLabels {
108+
return &ListIssuesQueryTypeWithLabels{}
109+
} else if hasSince {
110+
return &ListIssuesQueryWithSince{}
85111
}
86-
return &ListIssuesQueryNoLabelsType{}
112+
return &ListIssuesQuery{}
87113
}
88114

89115
func fragmentToIssue(fragment IssueFragment) *github.Issue {
@@ -911,18 +937,20 @@ func ListIssues(getGQLClient GetGQLClientFn, t translations.TranslationHelperFun
911937
direction = "DESC"
912938
}
913939

914-
// since, err := OptionalParam[string](request, "since")
915-
// if err != nil {
916-
// return mcp.NewToolResultError(err.Error()), nil
917-
// }
940+
since, err := OptionalParam[string](request, "since")
941+
if err != nil {
942+
return mcp.NewToolResultError(err.Error()), nil
943+
}
918944

919-
// var sinceTime time.Time
920-
// if since != "" {
921-
// sinceTime, err = parseISOTimestamp(since)
922-
// if err != nil {
923-
// return mcp.NewToolResultError(fmt.Sprintf("failed to list issues: %s", err.Error())), nil
924-
// }
925-
// }
945+
var sinceTime time.Time
946+
var hasSince bool
947+
if since != "" {
948+
sinceTime, err = parseISOTimestamp(since)
949+
if err != nil {
950+
return mcp.NewToolResultError(fmt.Sprintf("failed to list issues: %s", err.Error())), nil
951+
}
952+
hasSince = true
953+
}
926954

927955
// Get pagination parameters and convert to GraphQL format
928956
pagination, err := OptionalCursorPaginationParams(request)
@@ -982,7 +1010,11 @@ func ListIssues(getGQLClient GetGQLClientFn, t translations.TranslationHelperFun
9821010
vars["labels"] = labelStrings
9831011
}
9841012

985-
issueQuery := getIssueQueryType(hasLabels)
1013+
if hasSince {
1014+
vars["since"] = githubv4.DateTime{Time: sinceTime}
1015+
}
1016+
1017+
issueQuery := getIssueQueryType(hasLabels, hasSince)
9861018
if err := client.Query(ctx, issueQuery, vars); err != nil {
9871019
return mcp.NewToolResultError(err.Error()), nil
9881020
}

0 commit comments

Comments
 (0)