Skip to content

Feat add Get pull requests associated to a commit's SHA#36617

Draft
kevo-1 wants to merge 9 commits into
go-gitea:mainfrom
kevo-1:feature/commit-pulls-api
Draft

Feat add Get pull requests associated to a commit's SHA#36617
kevo-1 wants to merge 9 commits into
go-gitea:mainfrom
kevo-1:feature/commit-pulls-api

Conversation

@kevo-1
Copy link
Copy Markdown

@kevo-1 kevo-1 commented Feb 13, 2026

Add API endpoint to get pull requests associated with a commit

Fixes #36613

Changes

  • Added new API endpoint GET /repos/{owner}/{repo}/commits/{sha}/pulls
  • Returns all pull requests where the commit SHA matches the commit_id
  • Returns empty array if no PRs are associated with the commit

API Usage

GET /api/v1/repos/{owner}/{repo}/commits/{sha}/pulls

Response: Array of pull requests or empty array []

Testing

  • Added integration tests covering:
    • Valid merged commits with associated PRs
    • Valid commits without associated PRs
    • Invalid/nonexistent commits

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Feb 13, 2026
@kevo-1 kevo-1 marked this pull request as ready for review February 13, 2026 17:16
@silverwind
Copy link
Copy Markdown
Member

Revert assets/go-licenses.json.

Copy link
Copy Markdown
Contributor

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 pull request adds a new API endpoint to retrieve all pull requests associated with a specific commit SHA, addressing issue #36613. The feature mirrors GitHub's /commits/{sha}/pulls endpoint, enabling users to discover which PRs contain a given commit.

Changes:

  • Added GET /repos/{owner}/{repo}/commits/{sha}/pulls API endpoint that returns an array of pull requests
  • Created GetPullRequestsByMergedCommit model function to query PRs by merged commit ID
  • Added comprehensive integration tests covering merged commits, commits without PRs, and invalid/nonexistent commits

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
routers/api/v1/api.go Registers the new /commits/{sha}/pulls route with appropriate permissions
routers/api/v1/repo/commits.go Implements the GetCommitPullRequests API handler with conversion logic
models/issues/pull.go Adds GetPullRequestsByMergedCommit database query function
templates/swagger/v1_json.tmpl Documents the new endpoint in the Swagger specification
tests/integration/api_repo_get_commit_pull_request_test.go Provides integration tests for various scenarios

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread routers/api/v1/repo/commits.go Outdated
Comment thread tests/integration/api_repo_get_commit_pull_request_test.go
Comment thread models/issues/pull.go Outdated
Comment thread models/issues/pull.go Outdated
@silverwind silverwind added type/feature Completely new functionality. Can only be merged if feature freeze is not active. topic/api Concerns mainly the API and removed type/feature Completely new functionality. Can only be merged if feature freeze is not active. labels Feb 13, 2026
Comment thread go-licenses.json
return
}

baseRepo := ctx.Repo.Repository
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It seems it missed the permission check. It needs a read permission of pull request.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Thanks for the review, could you clarify more?

The route is inside /commits PathGroup which already does the check using reqRepoReader.
Should I add an inline check for read permission?
or did I misunderstand something.

and thank you again.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just add a permission check inside the function. The endpoint is special because it needs both code unit permission and pull request unit permission.

kevo-1 and others added 5 commits February 13, 2026 20:43
Signed-off-by: kevo-1 <kevin.bastawrous@gmail.com>
Signed-off-by: kevo-1 <kevin.bastawrous@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Kevin <154337845+kevo-1@users.noreply.github.com>
Signed-off-by: Kevin <154337845+kevo-1@users.noreply.github.com>
Signed-off-by: kevo-1 <kevin.bastawrous@gmail.com>
@kevo-1 kevo-1 force-pushed the feature/commit-pulls-api branch from 1bbb427 to a4f0c00 Compare February 13, 2026 18:43
@silverwind
Copy link
Copy Markdown
Member

silverwind commented Feb 13, 2026

Before continuing, compare your /pulls endpoint with existing /pull. my understanding is they may do exactly the same. If so, your endpoint could just be aliased to /pull.

@wxiaoguang
Copy link
Copy Markdown
Contributor

  • Why not use existing /repos/{owner}/{repo}/commits/{sha}/pull ?
  • Why a commit ID can have multiple PRs (GetPullRequestsByMergedCommit) ?

@wxiaoguang wxiaoguang marked this pull request as draft February 13, 2026 19:16
@silverwind
Copy link
Copy Markdown
Member

Why not use existing /repos/{owner}/{repo}/commits/{sha}/pull ?

I think compat with GitHub's path at /pulls is good, but could be an alias as mentioned.

Get every PR that contains a commit SHA in the queried repo and it's branches

Signed-off-by: kevo-1 <kevin.bastawrous@gmail.com>
Signed-off-by: kevo-1 <kevin.bastawrous@gmail.com>
@kevo-1
Copy link
Copy Markdown
Author

kevo-1 commented Feb 14, 2026

As I have misunderstood what the proposal was actually asking for, this commit adds the pulls endpoint where every PR containing the commit SHA is returned, not just merged commits.

@lunny
Copy link
Copy Markdown
Member

lunny commented Feb 14, 2026

  • Why a commit ID can have multiple PRs (GetPullRequestsByMergedCommit) ?

I guess different branches could have the same commitid. And some pull requests could have the same merged commitids because the base branch might be different.

@kevo-1 kevo-1 marked this pull request as ready for review February 14, 2026 07:16
@silverwind
Copy link
Copy Markdown
Member

This comment was written by Claude Code on behalf of @silverwind.

Review: /pull vs /pulls endpoints

The PR adds GET /repos/{owner}/{repo}/commits/{sha}/pulls (plural) alongside the existing GET /repos/{owner}/{repo}/commits/{sha}/pull (singular). They are not the same endpoint:

Existing /pull (singular) New /pulls (plural)
Returns Single PullRequest object Array of PullRequest objects
Scope Only finds the PR whose merge commit matches the SHA Finds PRs by merge commit and by branch containment (any PR whose head branch contains the commit)
On miss Returns 404 Returns empty array []
GitHub compat No GitHub equivalent Matches GitHub's GET /repos/{owner}/{repo}/commits/{commit_sha}/pulls

Does it make sense to have both?

Yes, having both endpoints is justified:

  1. They have different semantics. /pull answers "which PR was this SHA the merge commit of?" (a narrow, specific question). /pulls answers "which PRs contain this commit?" (a broader question). The GitHub API only has the broader one.

  2. GitHub API compatibility. GitHub's endpoint is at /pulls (plural), returns an array, and finds PRs both by merge commit and by branch containment — exactly what this PR implements. Adding /pulls gives tooling that targets the GitHub API (CI tools, scripts) a compatible endpoint.

  3. Backward compatibility. The existing /pull endpoint is already in use. Removing or changing its return type from a single object to an array would be a breaking change. Keeping it as-is is correct.

Issues worth addressing

  1. GetPullRequestsByHeadBranch only matches on head_repo_id, which means it only finds PRs originating from the same repo. For forked PRs, the head repo ID differs from the base repo ID, so those would be missed. The query should likely also (or instead) consider base_repo_id, or the function should accept both IDs.

  2. No pagination. GitHub's equivalent supports per_page and page. The new endpoint returns everything in one response. For repos with many PRs touching the same branches, this could be large. Worth adding pagination via utils.GetListOptions().

  3. git for-each-ref --contains can be slow on large repositories with many branches. There's no timeout or limit on the number of branches returned. This could be a performance concern.

  4. Error swallowing. When GetBranchesContaining fails (e.g., invalid SHA), the error is silently ignored and branches is set to nil. This means an invalid SHA returns 200 OK with an empty array rather than a 404. GitHub does the same, so this may be intentional, but worth being explicit about.

@silverwind
Copy link
Copy Markdown
Member

silverwind commented Feb 14, 2026

@kevo-1 check the 4 points above. I think they are all worth addressing.

@wxiaoguang
Copy link
Copy Markdown
Contributor

As I have misunderstood what the proposal was actually asking for, this commit adds the pulls endpoint where every PR containing the commit SHA is returned, not just merged commits.

I don't think it is true, the author of #36613 asked for:

In GitHub, it is possible to determine which Pull Request (PR) introduced a given commit by using the commit ID.
Gitea currently lacks a direct API or UI feature to retrieve the PR number associated with a commit SHA.

The issue reporter's requirement is already in Gitea #29243 , the author just didn't find it.

I don't see a real world use case for your new change.

@silverwind
Copy link
Copy Markdown
Member

silverwind commented Feb 14, 2026

I don't see a real world use case for your new change.

The use case seems to be (from #36617 (comment)):

/pull answers "which PR was this SHA the merge commit of?" (a narrow, specific question). /pulls answers "which PRs contain this commit?" (a broader question)

I think it might be a match to the original issue actually.

-Changed the GetPullRequestsByHeadBranch to also match on head repo id and base repo id  -Applied Pagination to PRs list  -The error swallowing behaviour is intended to match Github's API behaviour

Signed-off-by: kevo-1 <kevin.bastawrous@gmail.com>
Signed-off-by: kevo-1 <kevin.bastawrous@gmail.com>
@kevo-1
Copy link
Copy Markdown
Author

kevo-1 commented Feb 14, 2026

@kevo-1 check the 4 points above. I think they are all worth addressing.

For the 4th issue, it was intentional to match Github's API behaviour, but I added comments to clarify that the behavior was intentional.

@wxiaoguang
Copy link
Copy Markdown
Contributor

I don't see a real world use case for your new change.

The use case seems to be:

/pull answers "which PR was this SHA the merge commit of?" (a narrow, specific question). /pulls answers "which PRs contain this commit?" (a broader question)

I think it might be a match to the original issue actually.

But why? Can you show a real world case that such behavior is useful?

And there is another question: if a repo contains thousands of PRs, and you query the first "init" commit, then all these thousands of PRs will be in the response? Does it make sense? Will it just cause DoS and take down the server?

It is a kind of laziness and ignorance that only guess and imagine something is right but not really investigate into it.

@silverwind
Copy link
Copy Markdown
Member

silverwind commented Feb 14, 2026

I fully understand the difference now: A commit can be theoretically be contained in multiple PRs and only /pulls delivers that while /pull can only deliver a single result.

@wxiaoguang
Copy link
Copy Markdown
Contributor

Why not use existing /repos/{owner}/{repo}/commits/{sha}/pull ?

I think compat with GitHub's path at /pulls is good, but could be an alias as mentioned.

Does GitHub really work this way? Besides the problems mentioned above, the current logic is also not right, for example: the PR branches usually are deleted after merge, then GetBranchesContaining won't see these branches.

@silverwind
Copy link
Copy Markdown
Member

silverwind commented Feb 14, 2026

Does GitHub really work this way

Info on when GitHub's List pull requests associated with a commit API returns multiple pull requests in the array (written by Claude):

  1. Commit not on the default branch — When the commit SHA is not present in the default branch, the API returns both merged and open pull requests associated with that commit. For example, a commit could exist on a feature branch that has an open PR, and also have been cherry-picked into another branch via a separate merged PR.

  2. Branch name used as commit_sha — You can pass a branch name instead of an actual SHA. This returns all open or merged pull requests associated with that branch, which can easily be multiple.

  3. Multiple PRs genuinely reference the same commit — Even on the default branch, a single commit can be associated with more than one merged PR. Common cases:

    • A commit is part of a PR that gets merged, then that same commit (same SHA) appears in a second PR (e.g., a backport/cherry-pick that preserves the SHA, or a PR merged into an intermediate branch which was then merged to default).
    • A PR is merged, then reverted (revert PR references the original commits), and re-merged via a third PR.
    • In monorepo or stacked-PR workflows, the same commit can end up referenced by multiple PRs.

The most common real-world scenario for multiple results is case 1: querying a commit that only lives on feature branches, where it may be associated with both an open PR and a previously merged PR.

@wxiaoguang
Copy link
Copy Markdown
Contributor

Info on when GitHub's List pull requests associated with a commit API returns multiple pull requests in the array (written by Claude):

1. **Commit not on the default branch** — When the commit SHA is not present in the default branch, the API returns both merged _and_ open pull requests associated with that commit. For example, a commit could exist on a feature branch that has an open PR, and also have been cherry-picked into another branch via a separate merged PR.

2. **Branch name used as `commit_sha`** — You can pass a branch name instead of an actual SHA. This returns all open or merged pull requests associated with that branch, which can easily be multiple.

3. **Multiple PRs genuinely reference the same commit** — Even on the default branch, a single commit can be associated with more than one merged PR. Common cases:
   
   * A commit is part of a PR that gets merged, then that same commit (same SHA) appears in a second PR (e.g., a backport/cherry-pick that preserves the SHA, or a PR merged into an intermediate branch which was then merged to default).
   * A PR is merged, then reverted (revert PR references the original commits), and re-merged via a third PR.
   * In monorepo or stacked-PR workflows, the same commit can end up referenced by multiple PRs.

The most common real-world scenario for multiple results is case 1: querying a commit that only lives on feature branches, where it may be associated with both an open PR and a previously merged PR.

Do you really understand how GitHub works, or have you really tested its API? Or it is just your guess and imagination?

@silverwind
Copy link
Copy Markdown
Member

silverwind commented Feb 14, 2026

Do you really understand how GitHub works, or have you really tested its API? Or it is just your guess and imagination?

I created a reproduction on my test repo, check this:

$ curl -s -H "Accept: application/vnd.github+json" "https://api.github.com/repos/silverwind/symlink-test/commits/3cd304bb35c220fe69879c3d1d468d9f5c1b472f/pulls" | jq length
2

This clearly demonstrates our singular /pull api is insufficient. The referenced pull are silverwind/symlink-test#22 and silverwind/symlink-test#23.

@wxiaoguang
Copy link
Copy Markdown
Contributor

wxiaoguang commented Feb 14, 2026

Do you think GetBranchesContaining + GetPullRequestsByHeadBranch is right? It doesn't implement the GitHub's behavior.

@silverwind
Copy link
Copy Markdown
Member

Do you think GetBranchesContaining + GetPullRequestsByHeadBranch is right?

I don't have a opinion on that, but see #36617 (comment) about it.

@wxiaoguang
Copy link
Copy Markdown
Contributor

wxiaoguang commented Feb 14, 2026

Do you think GetBranchesContaining + GetPullRequestsByHeadBranch is right?

I don't have a opinion on that, but see #36617 (comment) about it.

So you mean you haven't really understood this PR's behavior and GitHub's behavior? And you haven't really tested them either? But just copy-paste the crap from AI?

For what I can see, GitHub's behavior is useful. But this PR's behavior isn't and it is wrong.

@silverwind
Copy link
Copy Markdown
Member

So you mean you haven't really understood this PR's behavior and GitHub's behavior?

I fully understand the API and I have demonstrated how it works. I don't care about this feature itself so I won't waste time diving into the code myself.

But this PR's behavior isn't and it is wrong.

Then raise these concerns clearly, just saying "wrong" is not constructive feedback that can be acted upon.

@wxiaoguang
Copy link
Copy Markdown
Contributor

wxiaoguang commented Feb 14, 2026

So you mean you haven't really understood this PR's behavior and GitHub's behavior?

I fully understand the API and I have demonstrated how it works. I don't care about this feature itself so I won't waste time diving into the code myself.

But this PR's behavior isn't and it is wrong.

Then raise these concerns clearly, just saying "wrong" is not constructive feedback that can be acted upon.

The same to me: I don't care about this feature itself so I won't waste time diving into the code myself.

I can tell it is wrong, and I have explained again and again above (#36617 (comment) , #36617 (comment) , #36617 (comment)), you just don't understand it.

@silverwind
Copy link
Copy Markdown
Member

Yeah then let's wait on the author to resolve :)

@kevo-1
Copy link
Copy Markdown
Author

kevo-1 commented Feb 14, 2026

Do you think GetBranchesContaining + GetPullRequestsByHeadBranch is right? It doesn't implement the GitHub's behavior.

You're right that GetBranchesContaining + GetPullRequestsByHeadBranch is not fully equivalent to GitHub’s implementation.
Scenarios like deleted branches, squash merges, or rebases may diverge from GitHub behavior.
If strict GitHub parity is required, we would need to store commit-to-PR mappings at PR update time instead of resolving them from branch state.

Would you like me to:

  • Close this PR as the current approach isn't viable?
  • Alias the /pulls endpoint to the existing /pull endpoint behavior instead?

@wxiaoguang
Copy link
Copy Markdown
Contributor

It's up to you.

/pulls can't be aliased to existing /pull. They are different.

@kevo-1 kevo-1 marked this pull request as draft February 15, 2026 06:18
@kevo-1
Copy link
Copy Markdown
Author

kevo-1 commented Feb 15, 2026

For what I can see, GitHub's behavior is useful. But this PR's behavior isn't and it is wrong.

Do you think GetBranchesContaining + GetPullRequestsByHeadBranch is right? It doesn't implement the GitHub's behavior.

Would you care to emphasize more what you expect the /pulls endpoint to do?

@wxiaoguang
Copy link
Copy Markdown
Contributor

wxiaoguang commented Feb 15, 2026

Would you care to emphasize more what you expect the /pulls endpoint to do?

GitHub is here, you can try to figure out its design by testing on it directly, or if you need this feature, you should be able to know what its behavior should be.

I only occasionally review PRs to prevent from design problems. For the features I don't need, I don't have a full picture either.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. topic/api Concerns mainly the API

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ability to Retrieve Pull Request Number From a Commit ID in Gitea

6 participants