import { Octokit } from '@octokit/rest'; import { IPullRequest, IRepoDetails } from './types'; export interface IGetPullRequestFromCommitParams { github: Octokit; repoDetails: IRepoDetails; /** Commit hash */ commit: string; /** Provide this to have it included in the resulting IPullRequest */ authorEmail?: string; verbose?: boolean; } /** * Get the pull request info corresponding to the given commit. * (The `author.email` property is only present if `authorEmail` is provided.) */ export async function getPullRequestForCommit( params: IGetPullRequestFromCommitParams, ): Promise { const { github, repoDetails, commit, authorEmail, verbose } = params; verbose && console.log(`Looking for the PR containing ${commit}...`); try { // Attempt to directly find the PR corresponding to the commit from the change file const result = await github.repos.listPullRequestsAssociatedWithCommit({ commit_sha: commit, ...repoDetails }); // Filter out unmerged PRs, in case the commit has been in multiple PRs but only one got merged // (check merged_at because that's only set if the PR has been merged, whereas merge_commit_sha // is set even for un-merged PRs, to the most recent intermediate merge) const prs = result.data.filter(result => !!result.merged_at); if (prs.length > 1) { // In case the commit was in PRs to multiple branches or something? console.warn(`Multiple PRs found for ${commit}:`); console.warn(prs.map(pr => ` ${pr.url}`).join('\n')); } if (prs[0]) { verbose && console.log(`Found matching PR #${prs[0].number}.\n`); return processPullRequestApiResponse(prs[0], authorEmail); } } catch (ex) { console.warn(`Error finding PR for ${commit}`, ex); return; } console.warn(`Could not find a PR matching ${commit}.`); } /** * Convert a GitHub API response to an IPullRequest. * The `author.email` property is only present if `authorEmail` is provided. */ export function processPullRequestApiResponse( pr: | Octokit.ReposListPullRequestsAssociatedWithCommitResponseItem | Octokit.SearchIssuesAndPullRequestsResponseItemsItem, authorEmail?: string, ): IPullRequest { return { number: pr.number, url: pr.html_url, author: { email: authorEmail, username: pr.user.login, url: pr.user.html_url, }, }; }