Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
132 changes: 59 additions & 73 deletions lib/success.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { isNil, uniqBy, template, flatten, isEmpty, merge } from "lodash-es";
import { isNil, uniqBy, template, isEmpty, merge } from "lodash-es";
import pFilter from "p-filter";
import AggregateError from "aggregate-error";
import issueParser from "issue-parser";
Expand Down Expand Up @@ -75,47 +75,29 @@ export default async function success(pluginConfig, context, { Octokit }) {
const releaseInfos = releases.filter((release) => Boolean(release.name));
const shas = commits.map(({ hash }) => hash);

// For commits that are not on the default branch, `associatedPullRequests`
// also returns pull requests of other repositories (e.g. forks syncing from
// this one). Their numbers refer to the other repository, so skip them.
const isFromThisRepository = ({ repository }) =>
!repository || repository.nameWithOwner === `${owner}/${repo}`;

// Get associatedPRs
const associatedPRs = await inChunks(shas, 100, async (chunk) => {
const responsePRs = [];
const { repository } = await octokit.graphql(
buildAssociatedPRsQuery(chunk),
{ owner, repo },
);
const responseAssociatedPRs = Object.values(repository).map(
(item) => item.associatedPullRequests,
const nodes = await Promise.all(
Object.values(repository).map((commit) =>
getAssociatedPRsOfCommit(octokit, owner, repo, commit),
),
);
return buildIssuesOrPRsFromResponseNode(
nodes.flat().filter(isFromThisRepository),
);
for (const { nodes, pageInfo } of responseAssociatedPRs) {
if (nodes.length === 0) continue;

responsePRs.push(...buildIssuesOrPRsFromResponseNode(nodes));
if (pageInfo.hasNextPage) {
let cursor = pageInfo.endCursor;
let hasNextPage = true;
while (hasNextPage) {
const { repository } = await octokit.graphql(
loadSingleCommitAssociatedPRs,
{ owner, repo, sha: response.commit.oid, cursor },
);
const { associatedPullRequests } = repository.commit;
responsePRs.push(
...buildIssuesOrPRsFromResponseNode(
associatedPullRequests.nodes,
"PR",
),
);
if (associatedPullRequests.pageInfo.hasNextPage) {
cursor = associatedPullRequests.pageInfo.endCursor;
} else {
hasNextPage = false;
}
}
}
}
return responsePRs;
});

const uniqueAssociatedPRs = uniqBy(flatten(associatedPRs), "number");
const uniqueAssociatedPRs = uniqBy(associatedPRs, "number");

const prs = await pFilter(uniqueAssociatedPRs, async ({ number }) => {
const commits = await octokit.paginate(
Expand Down Expand Up @@ -169,7 +151,7 @@ export default async function success(pluginConfig, context, { Octokit }) {
let issues = [];

if (!isEmpty(parsedIssues)) {
const uniqueParsedIssues = uniqBy(flatten(parsedIssues), "number");
const uniqueParsedIssues = uniqBy(parsedIssues, "number");

// Get relatedIssues (or relatedPRs i.e. Issues/PRs that are closed by an associatedPR)
issues = await inChunks(uniqueParsedIssues, 100, async (chunk) => {
Expand Down Expand Up @@ -354,6 +336,24 @@ async function inChunks(items, chunkSize, callback) {
return results.flat();
}

/**
* Returns the `associatedPullRequests` nodes of a commit from the `getAssociatedPRs`
* response, loading the remaining pages for commits that have more than 100 of them.
*/
async function getAssociatedPRsOfCommit(octokit, owner, repo, commit) {
let page = commit.associatedPullRequests;
const nodes = [...page.nodes];
while (page.pageInfo.hasNextPage) {
const { repository } = await octokit.graphql(
loadSingleCommitAssociatedPRs,
{ owner, repo, sha: commit.oid, cursor: page.pageInfo.endCursor },
);
page = repository.commit.associatedPullRequests;
nodes.push(...page.nodes);
}
return nodes;
}

/**
* Fields common accross PRs and Issue
*/
Expand Down Expand Up @@ -408,6 +408,28 @@ const baseFields = `
locked
`;

/**
* Fields of a PR, on top of the `baseFields`
*/
const prFields = `
${baseFields}
repository {
nameWithOwner
}
mergeable
changedFiles
mergedAt
isDraft
mergedBy {
login
avatarUrl
url
}
commits {
totalCount
}
`;

/**
* Builds GraphQL query for fetching PRs/Commits related Issues to a list of commit hash (sha)
* @param {Array<number>} numbers
Expand All @@ -424,19 +446,7 @@ function buildRelatedIssuesQuery(numbers) {
${baseFields}
}
... on PullRequest {
${baseFields}
mergeable
changedFiles
mergedAt
isDraft
mergedBy {
login
avatarUrl
url
}
commits {
totalCount
}
${prFields}
}
}`;
})
Expand Down Expand Up @@ -466,19 +476,7 @@ function buildAssociatedPRsQuery(shas) {
hasNextPage
}
nodes {
${baseFields}
mergeable
changedFiles
mergedAt
isDraft
mergedBy {
login
avatarUrl
url
}
commits {
totalCount
}
${prFields}
}
}
}
Expand All @@ -505,19 +503,7 @@ const loadSingleCommitAssociatedPRs = `#graphql
hasNextPage
}
nodes {
${baseFields}
mergeable
changedFiles
mergedAt
isDraft
mergedBy {
login
avatarUrl
url
}
commits {
totalCount
}
${prFields}
}
}
}
Expand Down
Loading
Loading