Skip to content

Add a new tool to find closing PRs for issues #816

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

lumaxis
Copy link

@lumaxis lumaxis commented Aug 4, 2025

This PR adds a new tool that uses closedByPullRequestsReferences on Issue to specifically find PRs in a repo that closed the specified issues. We'd like to use this to find code changes that solved similar issues to a given new issue.

@lumaxis lumaxis requested a review from Copilot August 4, 2025 14:54
Copilot

This comment was marked as outdated.

@lumaxis lumaxis requested a review from Copilot August 4, 2025 16:26
Copilot

This comment was marked as outdated.

@lumaxis lumaxis marked this pull request as ready for review August 5, 2025 09:09
@lumaxis lumaxis requested a review from a team as a code owner August 5, 2025 09:09
@Copilot Copilot AI review requested due to automatic review settings August 5, 2025 09:09
Copilot

This comment was marked as outdated.

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@Copilot Copilot AI review requested due to automatic review settings August 5, 2025 09:27
Copilot

This comment was marked as outdated.

@Copilot Copilot AI review requested due to automatic review settings August 5, 2025 10:24
@lumaxis lumaxis force-pushed the lumaxis/add-tool-issue-closing-pr branch from ec67616 to 94af699 Compare August 5, 2025 10:24
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new tool called find_closing_pull_requests that leverages GitHub's GraphQL API to find pull requests that closed specific issues using the closedByPullRequestsReferences field. This functionality helps identify code changes that resolved similar issues.

Key changes:

  • Added FindClosingPullRequests tool with advanced GraphQL parameters including pagination, filtering, and ordering options
  • Implemented helper functions OptionalIntArrayParam and RequiredIntArrayParam for handling integer array parameters
  • Added comprehensive test coverage for the new functionality

Reviewed Changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
pkg/github/tools.go Added the new tool to the default toolset group
pkg/github/server.go Added helper functions for handling integer array parameters
pkg/github/issues.go Implemented the core FindClosingPullRequests tool with GraphQL queries
pkg/github/server_test.go Added unit tests for the new integer array parameter functions
pkg/github/find_closing_prs_integration_test.go Added integration tests for the new tool
e2e/e2e_test.go Added comprehensive end-to-end tests covering various scenarios
README.md Updated documentation with the new tool's parameters
Comments suppressed due to low confidence (2)

e2e/e2e_test.go:1737

  • The JSON field name closingPullRequests doesn't match the actual field name closing_pull_requests used in the response structure. This should be closing_pull_requests to match the API response format.
					} `json:"closingPullRequests"`

e2e/e2e_test.go:1738

  • The JSON field name totalCount doesn't match the actual field name total_count used in the response structure. This should be total_count to match the API response format.
					TotalCount int    `json:"totalCount"`

variables := map[string]any{
"owner": githubv4.String(owner),
"repo": githubv4.String(repo),
"number": githubv4.Int(issueNumber), // #nosec G115 - issueNumber validated to be positive
Copy link
Preview

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment references validation that doesn't exist. The function only checks if issueNumber < 0 but doesn't validate it to be positive (greater than 0). Consider adding proper validation or updating the comment to be accurate.

Copilot uses AI. Check for mistakes.

}

// Validate issue number (basic bounds check)
if issueNumber < 0 {
Copy link
Preview

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue number validation should check for both negative values and zero, as GitHub issue numbers start from 1. Consider changing the condition to issueNumber <= 0 for more accurate validation.

Suggested change
if issueNumber < 0 {
if issueNumber <= 0 {

Copilot uses AI. Check for mistakes.

variables["last"] = githubv4.Int(params.Last) // #nosec G115 - params.Last validated to be positive
variables["first"] = (*githubv4.Int)(nil)
} else {
variables["first"] = githubv4.Int(params.First) // #nosec G115 - params.First validated to be positive
Copy link
Preview

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments claim validation that doesn't match the actual validation logic. The validation only checks if values are non-negative, not positive. Update the comments to reflect the actual validation or improve the validation to match the comments.

Suggested change
variables["first"] = githubv4.Int(params.First) // #nosec G115 - params.First validated to be positive
"number": githubv4.Int(issueNumber), // #nosec G115 - issueNumber validated to be non-negative
}
if params.Last != 0 {
variables["last"] = githubv4.Int(params.Last) // #nosec G115 - params.Last validated to be non-negative
variables["first"] = (*githubv4.Int)(nil)
} else {
variables["first"] = githubv4.Int(params.First) // #nosec G115 - params.First validated to be non-negative

Copilot uses AI. Check for mistakes.

variables["last"] = githubv4.Int(params.Last) // #nosec G115 - params.Last validated to be positive
variables["first"] = (*githubv4.Int)(nil)
} else {
variables["first"] = githubv4.Int(params.First) // #nosec G115 - params.First validated to be positive
Copy link
Preview

Copilot AI Aug 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comments claim validation that doesn't match the actual validation logic. The validation only checks if values are non-negative, not positive. Update the comments to reflect the actual validation or improve the validation to match the comments.

Suggested change
variables["first"] = githubv4.Int(params.First) // #nosec G115 - params.First validated to be positive
"number": githubv4.Int(issueNumber), // #nosec G115 - issueNumber validated to be non-negative
}
if params.Last != 0 {
variables["last"] = githubv4.Int(params.Last) // #nosec G115 - params.Last validated to be non-negative
variables["first"] = (*githubv4.Int)(nil)
} else {
variables["first"] = githubv4.Int(params.First) // #nosec G115 - params.First validated to be non-negative

Copilot uses AI. Check for mistakes.

Copy link
Contributor

@LuluBeatson LuluBeatson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @lumaxis for adding this new tool!

I'd like to suggest some small changes:

  • Issue number should be positive (as mentioned in your comments). So you should use issueNumber <=0 as the invalid range. This should resolve the 4 copilot review comments about issueNumber validation
  • We have existing GQL pagination parameter parsing helpers. You can find an example usage in ListDiscussions in ./pkg/github/discussions.go. This should resolve the 4 copilot review comments about nosec G115.

A few other items to better fit into existing patterns:

  • testing, mocking, toolsnaps: details in comment
  • Error tool results: For errors from the GitHub REST/GraphQL clients we use NewGitHubAPIErrorResponse/NewGitHubGraphQLErrorResponse. More info can be found in ./docs/error-handling.md

And finally, a more subjective comment: I think the tool should be named get_issue_pull_requests and take a single issue number instead of an array of them. This mirrors get_issue_comments, makes it simpler/easier for models to use.

)

// TestFindClosingPullRequestsIntegration tests the FindClosingPullRequests tool with real GitHub API calls
func TestFindClosingPullRequestsIntegration(t *testing.T) {
Copy link
Contributor

@LuluBeatson LuluBeatson Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Integration tests are better placed in the ./e2e/ directory.

Alternatively/additionally, you should add a unit test to ./pkg/github/issues_test.go, naming it Test_FindClosingPullRequests and mock the github clients to prevent breaking tests should any live data change. Test_FindClosingPullRequestsshould also include a toolsnaps.Test (e.g Test_CreateIssue) and you can generate/update toolsnaps when running tests by using:

UPDATE_TOOLSNAPS=true go test ./...

More info: https://github.com/github/github-mcp-server/blob/main/docs/testing.md

Comment on lines +1405 to +1416
mcp.WithString("after",
mcp.Description("Cursor for forward pagination (use with first/limit)"),
),
mcp.WithString("before",
mcp.Description("Cursor for backward pagination (use with last)"),
),
mcp.WithNumber("last",
mcp.Description(fmt.Sprintf(
"Number of results from end for backward pagination (max: %d)",
MaxGraphQLPageSize,
)),
),
Copy link
Contributor

@LuluBeatson LuluBeatson Aug 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have existing GQL pagination parameter parsing helpers: WithCursorPagination, OptionalCursorPaginationParams in ./pkg/github/server.go. You can find an example usage in ListDiscussions in ./pkg/github/discussions.go. Instead of limit/after/before/last, we keep it simple by just using perPage/after.

This will also resolve many of the Copilot review comments about pagination param validation logic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy