Skip to content

Commit dfe47e9

Browse files
authored
fix(edge-case): fetching associatedPRs on 100+ context.commits in success lifecycle (#892)
* refactor: stop export of `buildAssociatedPRsQuery` * feat: add `pageInfo` to `getAssociatedPRs` query * feat: add `loadSingleCommitAssociatedPRs` graphql query * feat: implement logic to fetch more `associatedPRs` * test: fix unit tests in `success` * test: fix `intergration` * feat: implement logic to handle associatedPRs fetch on 100+ commits * test: add test case `dd comment and labels to PRs associated with release commits and issues (multipaged associatedPRs)`
1 parent d07718a commit dfe47e9

File tree

3 files changed

+440
-8
lines changed

3 files changed

+440
-8
lines changed

lib/success.js

Lines changed: 69 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,44 @@ export default async function success(pluginConfig, context, { Octokit }) {
6767
const releaseInfos = releases.filter((release) => Boolean(release.name));
6868
const shas = commits.map(({ hash }) => hash);
6969

70-
const { repository } = await octokit.graphql(
71-
buildAssociatedPRsQuery(shas),
72-
{ owner, repo },
73-
);
74-
const associatedPRs = Object.values(repository).map(
75-
(item) => item.associatedPullRequests.nodes,
76-
);
70+
const associatedPRs = [];
71+
72+
// Split commit shas into chunks of 100 shas
73+
const chunkSize = 100;
74+
const shasChunks = [];
75+
for (let i = 0; i < shas.length; i += chunkSize) {
76+
const chunk = shas.slice(i, i + chunkSize);
77+
shasChunks.push(chunk);
78+
}
79+
for (const chunk of shasChunks) {
80+
const { repository } = await octokit.graphql(
81+
buildAssociatedPRsQuery(chunk),
82+
{ owner, repo },
83+
);
84+
const responseAssociatedPRs = Object.values(repository).map(
85+
(item) => item.associatedPullRequests,
86+
);
87+
for (const { nodes, pageInfo } of responseAssociatedPRs) {
88+
associatedPRs.push(nodes);
89+
if (pageInfo.hasNextPage) {
90+
let cursor = pageInfo.endCursor;
91+
let hasNextPage = true;
92+
while (hasNextPage) {
93+
const { repository } = await octokit.graphql(
94+
loadSingleCommitAssociatedPRs,
95+
{ owner, repo, sha: response.commit.oid, cursor },
96+
);
97+
const { associatedPullRequests } = repository.commit;
98+
associatedPRs.push(associatedPullRequests.nodes);
99+
if (associatedPullRequests.pageInfo.hasNextPage) {
100+
cursor = associatedPullRequests.pageInfo.endCursor;
101+
} else {
102+
hasNextPage = false;
103+
}
104+
}
105+
}
106+
}
107+
}
77108

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

@@ -252,15 +283,20 @@ export default async function success(pluginConfig, context, { Octokit }) {
252283
* @param {Array<string>} shas
253284
* @returns {string}
254285
*/
255-
export function buildAssociatedPRsQuery(shas) {
286+
function buildAssociatedPRsQuery(shas) {
256287
return `#graphql
257288
query getAssociatedPRs($owner: String!, $repo: String!) {
258289
repository(owner: $owner, name: $repo) {
259290
${shas
260291
.map((sha) => {
261292
return `commit${sha.slice(0, 6)}: object(oid: "${sha}") {
262293
...on Commit {
294+
oid
263295
associatedPullRequests(first: 100) {
296+
pageInfo {
297+
endCursor
298+
hasNextPage
299+
}
264300
nodes {
265301
url
266302
number
@@ -275,3 +311,28 @@ export function buildAssociatedPRsQuery(shas) {
275311
}
276312
`;
277313
}
314+
315+
/**
316+
* GraphQL Query to fetch additional associatedPR for commits that has more than 100 associatedPRs
317+
*/
318+
const loadSingleCommitAssociatedPRs = `#graphql
319+
query getCommitAssociatedPRs($owner: String!, $repo: String!, $sha: String!, $cursor: String) {
320+
repository(owner: $owner, name: $repo) {
321+
commit: object(oid: $sha) {
322+
...on Commit {
323+
associatedPullRequests(after: $cursor, first: 100) {
324+
pageInfo {
325+
endCursor
326+
hasNextPage
327+
}
328+
nodes {
329+
url
330+
number
331+
body
332+
}
333+
}
334+
}
335+
}
336+
}
337+
}
338+
`;

test/integration.test.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,12 @@ test("Comment and add labels on PR included in the releases", async (t) => {
454454
data: {
455455
repository: {
456456
commit123: {
457+
oid: "123",
457458
associatedPullRequests: {
459+
pageInfo: {
460+
endCursor: "NI",
461+
hasNextPage: false,
462+
},
458463
nodes: [prs[0]],
459464
},
460465
},
@@ -674,7 +679,12 @@ test("Verify, release and notify success", async (t) => {
674679
data: {
675680
repository: {
676681
commit123: {
682+
oid: "123",
677683
associatedPullRequests: {
684+
pageInfo: {
685+
endCursor: "NI",
686+
hasNextPage: false,
687+
},
678688
nodes: [prs[0]],
679689
},
680690
},
@@ -828,7 +838,12 @@ test("Verify, update release and notify success", async (t) => {
828838
data: {
829839
repository: {
830840
commit123: {
841+
oid: "123",
831842
associatedPullRequests: {
843+
pageInfo: {
844+
endCursor: "NI",
845+
hasNextPage: false,
846+
},
832847
nodes: [prs[0]],
833848
},
834849
},

0 commit comments

Comments
 (0)
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