Skip to content

Commit 7fb46a3

Browse files
authoredSep 20, 2024··
fix: replace searchAPI usage with GraphQL in findSRIssue util (#907)
* feat: add graphql query loader `loadGetSRIssuesQuery` to fetch SRIssues * chore: add new `RELEASE_FAIL_LABEL` constant * feat: integrate issues fetch with graphql * feat: add fallback to searchAPI for backward compatibility * feat: integrated config label in SRIssues search * fix: error `getSRIssue` graphql query label param type * fix: undefined `data` property destructed from graphql reponse * refactor: modified wrong `body` property in query * refactor: remove conditions from searchAPI fallback logic * refactor: replace `getSRIssues` graphql query `label` param with `filter` * feat: implement unique issue sorting to address fallback `backwardIssues` conflict * feat: modify `findSRIssue` integration in `success` script; add `logger` to its params; * feat: integrate opinionated `RELEASE_FAIL_LABEL` into `fail` script * chore: Questions and lint fixes * refactor: modified `findSRIssues` integration in `fail` script * test: fixed `findSRIssue` units test * test: fixed `fail` unit tests * test: fix integrations test * test: fixed `success` unit tests * test: `Verify, release and notify success` fix attempt * test: addressed `"Verify, release and notify success"` case in `integrations` * test: fix `success` units * test: fix `fail` units * refactor: remove error object from searchAPI fallback error handle * test: add new case `"Handle error in searchAPI fallback"` * Revert "refactor: remove conditions from searchAPI fallback logic" This reverts commit a478a2b. * modified `RELEASE_FAIL_LABEL` value to `semantic-release` * test: fix cases for conditional `searchAPI` fallback consumption * Update lib/resolve-config.js
1 parent e57dc0c commit 7fb46a3

8 files changed

+998
-303
lines changed
 

‎lib/definitions/constants.js

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
export const ISSUE_ID = "<!-- semantic-release:github -->";
22

33
export const RELEASE_NAME = "GitHub release";
4+
5+
export const RELEASE_FAIL_LABEL = "semantic-release";

‎lib/fail.js

+10-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { template } from "lodash-es";
22
import debugFactory from "debug";
33

44
import parseGithubUrl from "./parse-github-url.js";
5-
import { ISSUE_ID } from "./definitions/constants.js";
5+
import { ISSUE_ID, RELEASE_FAIL_LABEL } from "./definitions/constants.js";
66
import resolveConfig from "./resolve-config.js";
77
import { toOctokitOptions } from "./octokit.js";
88
import findSRIssues from "./find-sr-issues.js";
@@ -57,7 +57,14 @@ export default async function fail(pluginConfig, context, { Octokit }) {
5757
const body = failComment
5858
? template(failComment)({ branch, errors })
5959
: getFailComment(branch, errors);
60-
const [srIssue] = await findSRIssues(octokit, failTitle, owner, repo);
60+
const [srIssue] = await findSRIssues(
61+
octokit,
62+
logger,
63+
failTitle,
64+
labels,
65+
owner,
66+
repo,
67+
);
6168

6269
const canCommentOnOrCreateIssue = failCommentCondition
6370
? template(failCommentCondition)({ ...context, issue: srIssue })
@@ -85,7 +92,7 @@ export default async function fail(pluginConfig, context, { Octokit }) {
8592
repo,
8693
title: failTitle,
8794
body: `${body}\n\n${ISSUE_ID}`,
88-
labels: labels || [],
95+
labels: (labels || []).concat([RELEASE_FAIL_LABEL]),
8996
assignees,
9097
};
9198
debug("create issue: %O", newIssue);

‎lib/find-sr-issues.js

+58-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,63 @@
1-
import { ISSUE_ID } from "./definitions/constants.js";
1+
import { uniqBy } from "lodash-es";
2+
import { ISSUE_ID, RELEASE_FAIL_LABEL } from "./definitions/constants.js";
3+
4+
export default async (octokit, logger, title, labels, owner, repo) => {
5+
let issues = [];
26

3-
export default async (octokit, title, owner, repo) => {
47
const {
5-
data: { items: issues },
6-
} = await octokit.request("GET /search/issues", {
7-
q: `in:title+repo:${owner}/${repo}+type:issue+state:open+${title}`,
8+
repository: {
9+
issues: { nodes: issueNodes },
10+
},
11+
} = await octokit.graphql(loadGetSRIssuesQuery, {
12+
owner,
13+
repo,
14+
filter: {
15+
labels: (labels || []).concat([RELEASE_FAIL_LABEL]),
16+
},
817
});
918

10-
return issues.filter((issue) => issue.body && issue.body.includes(ISSUE_ID));
19+
issues.push(...issueNodes);
20+
21+
/**
22+
* BACKWARD COMPATIBILITY: Fallback to the search API if the issue was not found in the GraphQL response.
23+
* This fallback will be removed in a future release
24+
*/
25+
if (issueNodes.length === 0) {
26+
try {
27+
const {
28+
data: { items: backwardIssues },
29+
} = await octokit.request("GET /search/issues", {
30+
q: `in:title+repo:${owner}/${repo}+type:issue+state:open+${title}`,
31+
});
32+
issues.push(...backwardIssues);
33+
} catch (error) {
34+
logger.log(
35+
"An error occured fetching issue via fallback (with GH SearchAPI)",
36+
);
37+
}
38+
}
39+
40+
const uniqueSRIssues = uniqBy(
41+
issues.filter((issue) => issue.body && issue.body.includes(ISSUE_ID)),
42+
"number",
43+
);
44+
45+
return uniqueSRIssues;
1146
};
47+
48+
/**
49+
* GraphQL Query to et the semantic-release issues for a repository.
50+
*/
51+
const loadGetSRIssuesQuery = `#graphql
52+
query getSRIssues($owner: String!, $repo: String!, $filter: IssueFilters) {
53+
repository(owner: $owner, name: $repo) {
54+
issues(first: 100, states: OPEN, filterBy: $filter) {
55+
nodes {
56+
number
57+
title
58+
body
59+
}
60+
}
61+
}
62+
}
63+
`;

‎lib/success.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export default async function success(pluginConfig, context, { Octokit }) {
2828
githubApiPathPrefix,
2929
githubApiUrl,
3030
proxy,
31+
labels,
3132
successComment,
3233
successCommentCondition,
3334
failTitle,
@@ -266,7 +267,14 @@ export default async function success(pluginConfig, context, { Octokit }) {
266267
if (failComment === false || failTitle === false) {
267268
logger.log("Skip closing issue.");
268269
} else {
269-
const srIssues = await findSRIssues(octokit, failTitle, owner, repo);
270+
const srIssues = await findSRIssues(
271+
octokit,
272+
logger,
273+
failTitle,
274+
labels,
275+
owner,
276+
repo,
277+
);
270278

271279
debug("found semantic-release issues: %O", srIssues);
272280

‎test/fail.test.js

+63-20
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import sinon from "sinon";
33
import test from "ava";
44
import fetchMock from "fetch-mock";
55

6-
import { ISSUE_ID } from "../lib/definitions/constants.js";
6+
import { ISSUE_ID, RELEASE_FAIL_LABEL } from "../lib/definitions/constants.js";
77
import { TestOctokit } from "./helpers/test-octokit.js";
88

99
/* eslint camelcase: ["error", {properties: "never"}] */
@@ -36,6 +36,13 @@ test("Open a new issue with the list of errors", async (t) => {
3636
.getOnce("https://api.github.local/repos/test_user/test_repo", {
3737
full_name: `${redirectedOwner}/${redirectedRepo}`,
3838
})
39+
.postOnce("https://api.github.local/graphql", {
40+
data: {
41+
repository: {
42+
issues: { nodes: [] },
43+
},
44+
},
45+
})
3946
.getOnce(
4047
`https://api.github.local/search/issues?q=${encodeURIComponent(
4148
"in:title",
@@ -59,7 +66,7 @@ test("Open a new issue with the list of errors", async (t) => {
5966
data.body,
6067
/---\n\n### Error message 1\n\nError 1 details\n\n---\n\n### Error message 2\n\nError 2 details\n\n---\n\n### Error message 3\n\nError 3 details\n\n---/,
6168
);
62-
t.deepEqual(data.labels, ["semantic-release"]);
69+
t.deepEqual(data.labels, ["semantic-release", RELEASE_FAIL_LABEL]);
6370
return true;
6471
},
6572
{
@@ -117,6 +124,13 @@ test("Open a new issue with the list of errors and custom title and comment", as
117124
full_name: `${owner}/${repo}`,
118125
clone_url: `https://api.github.local/${owner}/${repo}.git`,
119126
})
127+
.postOnce("https://api.github.local/graphql", {
128+
data: {
129+
repository: {
130+
issues: { nodes: [] },
131+
},
132+
},
133+
})
120134
.getOnce(
121135
`https://api.github.local/search/issues?q=${encodeURIComponent(
122136
"in:title",
@@ -132,7 +146,7 @@ test("Open a new issue with the list of errors and custom title and comment", as
132146
body: {
133147
title: failTitle,
134148
body: `branch master Error message 1 Error message 2 Error message 3\n\n${ISSUE_ID}`,
135-
labels: ["semantic-release"],
149+
labels: ["semantic-release", RELEASE_FAIL_LABEL],
136150
},
137151
},
138152
);
@@ -185,6 +199,13 @@ test("Open a new issue with assignees and the list of errors", async (t) => {
185199
full_name: `${owner}/${repo}`,
186200
clone_url: `https://api.github.local/${owner}/${repo}.git`,
187201
})
202+
.postOnce("https://api.github.local/graphql", {
203+
data: {
204+
repository: {
205+
issues: { nodes: [] },
206+
},
207+
},
208+
})
188209
.getOnce(
189210
`https://api.github.local/search/issues?q=${encodeURIComponent(
190211
"in:title",
@@ -203,7 +224,7 @@ test("Open a new issue with assignees and the list of errors", async (t) => {
203224
data.body,
204225
/---\n\n### Error message 1\n\nError 1 details\n\n---\n\n### Error message 2\n\nError 2 details\n\n---/,
205226
);
206-
t.deepEqual(data.labels, ["semantic-release"]);
227+
t.deepEqual(data.labels, ["semantic-release", RELEASE_FAIL_LABEL]);
207228
t.deepEqual(data.assignees, ["user1", "user2"]);
208229
return true;
209230
},
@@ -258,6 +279,13 @@ test("Open a new issue without labels and the list of errors", async (t) => {
258279
full_name: `${owner}/${repo}`,
259280
clone_url: `https://api.github.local/${owner}/${repo}.git`,
260281
})
282+
.postOnce("https://api.github.local/graphql", {
283+
data: {
284+
repository: {
285+
issues: { nodes: [] },
286+
},
287+
},
288+
})
261289
.getOnce(
262290
`https://api.github.local/search/issues?q=${encodeURIComponent(
263291
"in:title",
@@ -276,7 +304,7 @@ test("Open a new issue without labels and the list of errors", async (t) => {
276304
data.body,
277305
/---\n\n### Error message 1\n\nError 1 details\n\n---\n\n### Error message 2\n\nError 2 details\n\n---/,
278306
);
279-
t.deepEqual(data.labels, []);
307+
t.deepEqual(data.labels, [RELEASE_FAIL_LABEL]);
280308
return true;
281309
},
282310
{ html_url: "https://github.com/issues/1", number: 1 },
@@ -335,14 +363,13 @@ test("Update the first existing issue with the list of errors", async (t) => {
335363
full_name: `${owner}/${repo}`,
336364
clone_url: `https://api.github.local/${owner}/${repo}.git`,
337365
})
338-
.getOnce(
339-
`https://api.github.local/search/issues?q=${encodeURIComponent(
340-
"in:title",
341-
)}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent(
342-
"type:issue",
343-
)}+${encodeURIComponent("state:open")}+${encodeURIComponent(failTitle)}`,
344-
{ items: issues },
345-
)
366+
.postOnce("https://api.github.local/graphql", {
367+
data: {
368+
repository: {
369+
issues: { nodes: issues },
370+
},
371+
},
372+
})
346373
.postOnce(
347374
(url, { body }) => {
348375
t.is(
@@ -501,13 +528,17 @@ test('Does not post comments on existing issues when "failCommentCondition" is "
501528
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
502529
full_name: `${owner}/${repo}`,
503530
})
504-
.getOnce(
505-
`https://api.github.local/search/issues?q=${encodeURIComponent(
506-
"in:title",
507-
)}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent(
508-
"type:issue",
509-
)}+${encodeURIComponent("state:open")}+${encodeURIComponent(failTitle)}`,
510-
{ items: issues },
531+
.postOnce(
532+
(url, { body }) =>
533+
url === "https://api.github.local/graphql" &&
534+
JSON.parse(body).query.includes("query getSRIssues("),
535+
{
536+
data: {
537+
repository: {
538+
issues: { nodes: issues },
539+
},
540+
},
541+
},
511542
);
512543

513544
await fail(
@@ -551,6 +582,18 @@ test(`Post new issue if none exists yet, but don't comment on existing issues wh
551582
.getOnce(`https://api.github.local/repos/${owner}/${repo}`, {
552583
full_name: `${owner}/${repo}`,
553584
})
585+
.postOnce(
586+
(url, { body }) =>
587+
url === "https://api.github.local/graphql" &&
588+
JSON.parse(body).query.includes("query getSRIssues("),
589+
{
590+
data: {
591+
repository: {
592+
issues: { nodes: [] },
593+
},
594+
},
595+
},
596+
)
554597
.getOnce(
555598
`https://api.github.local/search/issues?q=${encodeURIComponent(
556599
"in:title",

‎test/find-sr-issue.test.js

+105-10
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ test("Filter out issues without ID", async (t) => {
1717
const owner = "test_user";
1818
const repo = "test_repo";
1919
const title = "The automated release is failing 🚨";
20+
const labels = [];
2021
const issues = [
2122
{ number: 1, body: "Issue 1 body", title },
2223
{ number: 2, body: `Issue 2 body\n\n${ISSUE_ID}`, title },
@@ -25,18 +26,19 @@ test("Filter out issues without ID", async (t) => {
2526

2627
const fetch = fetchMock
2728
.sandbox()
28-
.getOnce(
29-
`https://api.github.local/search/issues?q=${encodeURIComponent(
30-
"in:title",
31-
)}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent(
32-
"type:issue",
33-
)}+${encodeURIComponent("state:open")}+${encodeURIComponent(title)}`,
34-
{ items: issues },
35-
);
29+
.postOnce("https://api.github.local/graphql", {
30+
data: {
31+
repository: {
32+
issues: { nodes: issues },
33+
},
34+
},
35+
});
3636

3737
const srIssues = await findSRIssues(
3838
new TestOctokit({ request: { fetch } }),
39+
t.context.logger,
3940
title,
41+
labels,
4042
owner,
4143
repo,
4244
);
@@ -61,9 +63,17 @@ test("Return empty array if not issues found", async (t) => {
6163
const owner = "test_user";
6264
const repo = "test_repo";
6365
const title = "The automated release is failing 🚨";
66+
const labels = [];
6467
const issues = [];
6568
const fetch = fetchMock
6669
.sandbox()
70+
.postOnce("https://api.github.local/graphql", {
71+
data: {
72+
repository: {
73+
issues: { nodes: [] },
74+
},
75+
},
76+
})
6777
.getOnce(
6878
`https://api.github.local/search/issues?q=${encodeURIComponent(
6979
"in:title",
@@ -75,7 +85,9 @@ test("Return empty array if not issues found", async (t) => {
7585

7686
const srIssues = await findSRIssues(
7787
new TestOctokit({ request: { fetch } }),
88+
t.context.logger,
7889
title,
90+
labels,
7991
owner,
8092
repo,
8193
);
@@ -89,28 +101,111 @@ test("Return empty array if not issues has matching ID", async (t) => {
89101
const owner = "test_user";
90102
const repo = "test_repo";
91103
const title = "The automated release is failing 🚨";
104+
const labels = [];
92105
const issues = [
93106
{ number: 1, body: "Issue 1 body", title },
94107
{ number: 2, body: "Issue 2 body", title },
95108
];
96109
const fetch = fetchMock
97110
.sandbox()
111+
.postOnce("https://api.github.local/graphql", {
112+
data: {
113+
repository: {
114+
issues: { nodes: issues },
115+
},
116+
},
117+
});
118+
119+
const srIssues = await findSRIssues(
120+
new TestOctokit({ request: { fetch } }),
121+
t.context.logger,
122+
title,
123+
labels,
124+
owner,
125+
repo,
126+
);
127+
128+
t.deepEqual(srIssues, []);
129+
t.true(fetch.done());
130+
});
131+
132+
test("Handle error in searchAPI fallback", async (t) => {
133+
const owner = "test_user";
134+
const repo = "test_repo";
135+
const title = "The automated release is failing 🚨";
136+
const labels = [];
137+
const issues = [];
138+
139+
const response = new Response("Not Found", {
140+
url: "https://api.github.com/search/issues?q=in%3Atitle+repo%3Aourorg%2Frepo+type%3Aissue+state%3Aopen+The%20automated%20release%20is%20failing%20%F0%9F%9A%A8",
141+
status: 403,
142+
headers: {
143+
"access-control-allow-origin": "*",
144+
"access-control-expose-headers":
145+
"ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset",
146+
"content-encoding": "gzip",
147+
"content-security-policy": "default-repo 'none'",
148+
"content-type": "application/json; charset=utf-8",
149+
date: "Tue, 28 May 2024 19:49:00 GMT",
150+
"referrer-policy":
151+
"origin-when-cross-origin, strict-origin-when-cross-origin",
152+
server: "GitHub.com",
153+
"strict-transport-security":
154+
"max-age=31536000; includeSubdomains; preload",
155+
"transfer-encoding": "chunked",
156+
vary: "Accept-Encoding, Accept, X-Requested-With",
157+
"x-content-type-options": "nosniff",
158+
"x-frame-options": "deny",
159+
"x-github-api-version-selected": "2022-11-28",
160+
"x-github-media-type": "github.v3; format=json",
161+
"x-github-request-id": "2**0:29*****4:3868737:6*****3:6****52C",
162+
"x-ratelimit-limit": "30",
163+
"x-ratelimit-remaining": "30",
164+
"x-ratelimit-reset": "1716925800",
165+
"x-ratelimit-resource": "search",
166+
"x-ratelimit-used": "1",
167+
"x-xss-protection": "0",
168+
},
169+
data: {
170+
documentation_url:
171+
"https://docs.github.com/free-pro-team@latest/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits",
172+
message:
173+
"You have exceeded a secondary rate limit. Please wait a few minutes before you try again. If you reach out to GitHub Support for help, please include the request ID 2840:295B44:3868737:64A2183:6232352C.",
174+
},
175+
});
176+
177+
const fetch = fetchMock
178+
.sandbox()
179+
.postOnce("https://api.github.local/graphql", {
180+
data: {
181+
repository: {
182+
issues: { nodes: issues },
183+
},
184+
},
185+
})
98186
.getOnce(
99187
`https://api.github.local/search/issues?q=${encodeURIComponent(
100188
"in:title",
101189
)}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent(
102190
"type:issue",
103191
)}+${encodeURIComponent("state:open")}+${encodeURIComponent(title)}`,
104-
{ items: issues },
192+
response,
105193
);
106194

107195
const srIssues = await findSRIssues(
108196
new TestOctokit({ request: { fetch } }),
197+
t.context.logger,
109198
title,
199+
labels,
110200
owner,
111201
repo,
112202
);
113203

114-
t.deepEqual(srIssues, []);
204+
t.true(
205+
t.context.log.calledWith(
206+
"An error occured fetching issue via fallback (with GH SearchAPI)",
207+
),
208+
);
209+
t.log(t.context.log);
115210
t.true(fetch.done());
116211
});

‎test/integration.test.js

+113-39
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import test from "ava";
22
import sinon from "sinon";
33
import SemanticReleaseError from "@semantic-release/error";
44
import fetchMock from "fetch-mock";
5+
import { RELEASE_FAIL_LABEL } from "../lib/definitions/constants.js";
56

67
import { TestOctokit } from "./helpers/test-octokit.js";
78

@@ -450,22 +451,29 @@ test("Comment and add labels on PR included in the releases", async (t) => {
450451
repeat: 2,
451452
},
452453
)
453-
.postOnce("https://api.github.local/graphql", {
454-
data: {
455-
repository: {
456-
commit123: {
457-
oid: "123",
458-
associatedPullRequests: {
459-
pageInfo: {
460-
endCursor: "NI",
461-
hasNextPage: false,
454+
.postOnce(
455+
(url, { body }) => {
456+
t.is(url, "https://api.github.local/graphql");
457+
t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/);
458+
return true;
459+
},
460+
{
461+
data: {
462+
repository: {
463+
commit123: {
464+
oid: "123",
465+
associatedPullRequests: {
466+
pageInfo: {
467+
endCursor: "NI",
468+
hasNextPage: false,
469+
},
470+
nodes: [prs[0]],
462471
},
463-
nodes: [prs[0]],
464472
},
465473
},
466474
},
467475
},
468-
})
476+
)
469477
.getOnce(
470478
`https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`,
471479
[{ sha: commits[0].hash }],
@@ -491,6 +499,20 @@ test("Comment and add labels on PR included in the releases", async (t) => {
491499
body: ["released"],
492500
},
493501
)
502+
.postOnce(
503+
(url, { body }) => {
504+
t.is(url, "https://api.github.local/graphql");
505+
t.regex(JSON.parse(body).query, /query getSRIssues\(/);
506+
return true;
507+
},
508+
{
509+
data: {
510+
repository: {
511+
issues: { nodes: [] },
512+
},
513+
},
514+
},
515+
)
494516
.getOnce(
495517
`https://api.github.local/search/issues?q=${encodeURIComponent(
496518
"in:title",
@@ -556,6 +578,13 @@ test("Open a new issue with the list of errors", async (t) => {
556578
},
557579
{ repeat: 2 },
558580
)
581+
.postOnce("https://api.github.local/graphql", {
582+
data: {
583+
repository: {
584+
issues: { nodes: [] },
585+
},
586+
},
587+
})
559588
.getOnce(
560589
`https://api.github.local/search/issues?q=${encodeURIComponent(
561590
"in:title",
@@ -573,7 +602,7 @@ test("Open a new issue with the list of errors", async (t) => {
573602
data.body,
574603
/---\n\n### Error message 1\n\nError 1 details\n\n---\n\n### Error message 2\n\nError 2 details\n\n---\n\n### Error message 3\n\nError 3 details\n\n---/,
575604
);
576-
t.deepEqual(data.labels, ["semantic-release"]);
605+
t.deepEqual(data.labels, ["semantic-release", RELEASE_FAIL_LABEL]);
577606

578607
return true;
579608
},
@@ -653,6 +682,39 @@ test("Verify, release and notify success", async (t) => {
653682
repeat: 2,
654683
},
655684
)
685+
.postOnce(
686+
(url, { body }) =>
687+
url === "https://api.github.local/graphql" &&
688+
JSON.parse(body).query.includes("query getAssociatedPRs("),
689+
{
690+
data: {
691+
repository: {
692+
commit123: {
693+
oid: "123",
694+
associatedPullRequests: {
695+
pageInfo: {
696+
endCursor: "NI",
697+
hasNextPage: false,
698+
},
699+
nodes: [prs[0]],
700+
},
701+
},
702+
},
703+
},
704+
},
705+
)
706+
.postOnce(
707+
(url, { body }) =>
708+
url === "https://api.github.local/graphql" &&
709+
JSON.parse(body).query.includes("query getSRIssues("),
710+
{
711+
data: {
712+
repository: {
713+
issues: { nodes: [] },
714+
},
715+
},
716+
},
717+
)
656718
.postOnce(
657719
`https://api.github.local/repos/${owner}/${repo}/releases`,
658720
{
@@ -675,22 +737,6 @@ test("Verify, release and notify success", async (t) => {
675737
{ html_url: releaseUrl },
676738
{ body: { draft: false } },
677739
)
678-
.postOnce("https://api.github.local/graphql", {
679-
data: {
680-
repository: {
681-
commit123: {
682-
oid: "123",
683-
associatedPullRequests: {
684-
pageInfo: {
685-
endCursor: "NI",
686-
hasNextPage: false,
687-
},
688-
nodes: [prs[0]],
689-
},
690-
},
691-
},
692-
},
693-
})
694740
.getOnce(
695741
`https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`,
696742
[{ sha: commits[0].hash }],
@@ -834,22 +880,29 @@ test("Verify, update release and notify success", async (t) => {
834880
},
835881
},
836882
)
837-
.postOnce("https://api.github.local/graphql", {
838-
data: {
839-
repository: {
840-
commit123: {
841-
oid: "123",
842-
associatedPullRequests: {
843-
pageInfo: {
844-
endCursor: "NI",
845-
hasNextPage: false,
883+
.postOnce(
884+
(url, { body }) => {
885+
t.is(url, "https://api.github.local/graphql");
886+
t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/);
887+
return true;
888+
},
889+
{
890+
data: {
891+
repository: {
892+
commit123: {
893+
oid: "123",
894+
associatedPullRequests: {
895+
pageInfo: {
896+
endCursor: "NI",
897+
hasNextPage: false,
898+
},
899+
nodes: [prs[0]],
846900
},
847-
nodes: [prs[0]],
848901
},
849902
},
850903
},
851904
},
852-
})
905+
)
853906
.getOnce(
854907
`https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`,
855908
[{ sha: commits[0].hash }],
@@ -867,6 +920,20 @@ test("Verify, update release and notify success", async (t) => {
867920
body: ["released"],
868921
},
869922
)
923+
.postOnce(
924+
(url, { body }) => {
925+
t.is(url, "https://api.github.local/graphql");
926+
t.regex(JSON.parse(body).query, /query getSRIssues\(/);
927+
return true;
928+
},
929+
{
930+
data: {
931+
repository: {
932+
issues: { nodes: [] },
933+
},
934+
},
935+
},
936+
)
870937
.getOnce(
871938
`https://api.github.local/search/issues?q=${encodeURIComponent(
872939
"in:title",
@@ -957,6 +1024,13 @@ test("Verify and notify failure", async (t) => {
9571024
repeat: 2,
9581025
},
9591026
)
1027+
.postOnce("https://api.github.local/graphql", {
1028+
data: {
1029+
repository: {
1030+
issues: { nodes: [] },
1031+
},
1032+
},
1033+
})
9601034
.getOnce(
9611035
`https://api.github.local/search/issues?q=${encodeURIComponent(
9621036
"in:title",

‎test/success.test.js

+638-224
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.