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)