From 7fb46a3370908d738a094b39783ce898edaeeba1 Mon Sep 17 00:00:00 2001 From: Olabode Lawal-Shittabey Date: Fri, 20 Sep 2024 19:16:38 +0100 Subject: [PATCH] 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 a478a2b7c63ed65578045caadad6132621c4da03. * modified `RELEASE_FAIL_LABEL` value to `semantic-release` * test: fix cases for conditional `searchAPI` fallback consumption * Update lib/resolve-config.js --- lib/definitions/constants.js | 2 + lib/fail.js | 13 +- lib/find-sr-issues.js | 64 ++- lib/success.js | 10 +- test/fail.test.js | 83 +++- test/find-sr-issue.test.js | 115 ++++- test/integration.test.js | 152 ++++-- test/success.test.js | 862 ++++++++++++++++++++++++++--------- 8 files changed, 998 insertions(+), 303 deletions(-) diff --git a/lib/definitions/constants.js b/lib/definitions/constants.js index dc22169a..c0400947 100644 --- a/lib/definitions/constants.js +++ b/lib/definitions/constants.js @@ -1,3 +1,5 @@ export const ISSUE_ID = ""; export const RELEASE_NAME = "GitHub release"; + +export const RELEASE_FAIL_LABEL = "semantic-release"; diff --git a/lib/fail.js b/lib/fail.js index 070b076e..723b0510 100644 --- a/lib/fail.js +++ b/lib/fail.js @@ -2,7 +2,7 @@ import { template } from "lodash-es"; import debugFactory from "debug"; import parseGithubUrl from "./parse-github-url.js"; -import { ISSUE_ID } from "./definitions/constants.js"; +import { ISSUE_ID, RELEASE_FAIL_LABEL } from "./definitions/constants.js"; import resolveConfig from "./resolve-config.js"; import { toOctokitOptions } from "./octokit.js"; import findSRIssues from "./find-sr-issues.js"; @@ -57,7 +57,14 @@ export default async function fail(pluginConfig, context, { Octokit }) { const body = failComment ? template(failComment)({ branch, errors }) : getFailComment(branch, errors); - const [srIssue] = await findSRIssues(octokit, failTitle, owner, repo); + const [srIssue] = await findSRIssues( + octokit, + logger, + failTitle, + labels, + owner, + repo, + ); const canCommentOnOrCreateIssue = failCommentCondition ? template(failCommentCondition)({ ...context, issue: srIssue }) @@ -85,7 +92,7 @@ export default async function fail(pluginConfig, context, { Octokit }) { repo, title: failTitle, body: `${body}\n\n${ISSUE_ID}`, - labels: labels || [], + labels: (labels || []).concat([RELEASE_FAIL_LABEL]), assignees, }; debug("create issue: %O", newIssue); diff --git a/lib/find-sr-issues.js b/lib/find-sr-issues.js index d0fe8760..47af4104 100644 --- a/lib/find-sr-issues.js +++ b/lib/find-sr-issues.js @@ -1,11 +1,63 @@ -import { ISSUE_ID } from "./definitions/constants.js"; +import { uniqBy } from "lodash-es"; +import { ISSUE_ID, RELEASE_FAIL_LABEL } from "./definitions/constants.js"; + +export default async (octokit, logger, title, labels, owner, repo) => { + let issues = []; -export default async (octokit, title, owner, repo) => { const { - data: { items: issues }, - } = await octokit.request("GET /search/issues", { - q: `in:title+repo:${owner}/${repo}+type:issue+state:open+${title}`, + repository: { + issues: { nodes: issueNodes }, + }, + } = await octokit.graphql(loadGetSRIssuesQuery, { + owner, + repo, + filter: { + labels: (labels || []).concat([RELEASE_FAIL_LABEL]), + }, }); - return issues.filter((issue) => issue.body && issue.body.includes(ISSUE_ID)); + issues.push(...issueNodes); + + /** + * BACKWARD COMPATIBILITY: Fallback to the search API if the issue was not found in the GraphQL response. + * This fallback will be removed in a future release + */ + if (issueNodes.length === 0) { + try { + const { + data: { items: backwardIssues }, + } = await octokit.request("GET /search/issues", { + q: `in:title+repo:${owner}/${repo}+type:issue+state:open+${title}`, + }); + issues.push(...backwardIssues); + } catch (error) { + logger.log( + "An error occured fetching issue via fallback (with GH SearchAPI)", + ); + } + } + + const uniqueSRIssues = uniqBy( + issues.filter((issue) => issue.body && issue.body.includes(ISSUE_ID)), + "number", + ); + + return uniqueSRIssues; }; + +/** + * GraphQL Query to et the semantic-release issues for a repository. + */ +const loadGetSRIssuesQuery = `#graphql + query getSRIssues($owner: String!, $repo: String!, $filter: IssueFilters) { + repository(owner: $owner, name: $repo) { + issues(first: 100, states: OPEN, filterBy: $filter) { + nodes { + number + title + body + } + } + } + } +`; diff --git a/lib/success.js b/lib/success.js index 06fe203c..705f02aa 100644 --- a/lib/success.js +++ b/lib/success.js @@ -28,6 +28,7 @@ export default async function success(pluginConfig, context, { Octokit }) { githubApiPathPrefix, githubApiUrl, proxy, + labels, successComment, successCommentCondition, failTitle, @@ -266,7 +267,14 @@ export default async function success(pluginConfig, context, { Octokit }) { if (failComment === false || failTitle === false) { logger.log("Skip closing issue."); } else { - const srIssues = await findSRIssues(octokit, failTitle, owner, repo); + const srIssues = await findSRIssues( + octokit, + logger, + failTitle, + labels, + owner, + repo, + ); debug("found semantic-release issues: %O", srIssues); diff --git a/test/fail.test.js b/test/fail.test.js index f0277d8d..37ceb6bd 100644 --- a/test/fail.test.js +++ b/test/fail.test.js @@ -3,7 +3,7 @@ import sinon from "sinon"; import test from "ava"; import fetchMock from "fetch-mock"; -import { ISSUE_ID } from "../lib/definitions/constants.js"; +import { ISSUE_ID, RELEASE_FAIL_LABEL } from "../lib/definitions/constants.js"; import { TestOctokit } from "./helpers/test-octokit.js"; /* eslint camelcase: ["error", {properties: "never"}] */ @@ -36,6 +36,13 @@ test("Open a new issue with the list of errors", async (t) => { .getOnce("https://api.github.local/repos/test_user/test_repo", { full_name: `${redirectedOwner}/${redirectedRepo}`, }) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -59,7 +66,7 @@ test("Open a new issue with the list of errors", async (t) => { data.body, /---\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---/, ); - t.deepEqual(data.labels, ["semantic-release"]); + t.deepEqual(data.labels, ["semantic-release", RELEASE_FAIL_LABEL]); return true; }, { @@ -117,6 +124,13 @@ test("Open a new issue with the list of errors and custom title and comment", as full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -132,7 +146,7 @@ test("Open a new issue with the list of errors and custom title and comment", as body: { title: failTitle, body: `branch master Error message 1 Error message 2 Error message 3\n\n${ISSUE_ID}`, - labels: ["semantic-release"], + labels: ["semantic-release", RELEASE_FAIL_LABEL], }, }, ); @@ -185,6 +199,13 @@ test("Open a new issue with assignees and the list of errors", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -203,7 +224,7 @@ test("Open a new issue with assignees and the list of errors", async (t) => { data.body, /---\n\n### Error message 1\n\nError 1 details\n\n---\n\n### Error message 2\n\nError 2 details\n\n---/, ); - t.deepEqual(data.labels, ["semantic-release"]); + t.deepEqual(data.labels, ["semantic-release", RELEASE_FAIL_LABEL]); t.deepEqual(data.assignees, ["user1", "user2"]); return true; }, @@ -258,6 +279,13 @@ test("Open a new issue without labels and the list of errors", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -276,7 +304,7 @@ test("Open a new issue without labels and the list of errors", async (t) => { data.body, /---\n\n### Error message 1\n\nError 1 details\n\n---\n\n### Error message 2\n\nError 2 details\n\n---/, ); - t.deepEqual(data.labels, []); + t.deepEqual(data.labels, [RELEASE_FAIL_LABEL]); return true; }, { 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) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .getOnce( - `https://api.github.local/search/issues?q=${encodeURIComponent( - "in:title", - )}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent( - "type:issue", - )}+${encodeURIComponent("state:open")}+${encodeURIComponent(failTitle)}`, - { items: issues }, - ) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: issues }, + }, + }, + }) .postOnce( (url, { body }) => { t.is( @@ -501,13 +528,17 @@ test('Does not post comments on existing issues when "failCommentCondition" is " .getOnce(`https://api.github.local/repos/${owner}/${repo}`, { full_name: `${owner}/${repo}`, }) - .getOnce( - `https://api.github.local/search/issues?q=${encodeURIComponent( - "in:title", - )}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent( - "type:issue", - )}+${encodeURIComponent("state:open")}+${encodeURIComponent(failTitle)}`, - { items: issues }, + .postOnce( + (url, { body }) => + url === "https://api.github.local/graphql" && + JSON.parse(body).query.includes("query getSRIssues("), + { + data: { + repository: { + issues: { nodes: issues }, + }, + }, + }, ); await fail( @@ -551,6 +582,18 @@ test(`Post new issue if none exists yet, but don't comment on existing issues wh .getOnce(`https://api.github.local/repos/${owner}/${repo}`, { full_name: `${owner}/${repo}`, }) + .postOnce( + (url, { body }) => + url === "https://api.github.local/graphql" && + JSON.parse(body).query.includes("query getSRIssues("), + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", diff --git a/test/find-sr-issue.test.js b/test/find-sr-issue.test.js index b6e4cefd..fc10c2f0 100644 --- a/test/find-sr-issue.test.js +++ b/test/find-sr-issue.test.js @@ -17,6 +17,7 @@ test("Filter out issues without ID", async (t) => { const owner = "test_user"; const repo = "test_repo"; const title = "The automated release is failing 🚨"; + const labels = []; const issues = [ { number: 1, body: "Issue 1 body", title }, { number: 2, body: `Issue 2 body\n\n${ISSUE_ID}`, title }, @@ -25,18 +26,19 @@ test("Filter out issues without ID", async (t) => { const fetch = fetchMock .sandbox() - .getOnce( - `https://api.github.local/search/issues?q=${encodeURIComponent( - "in:title", - )}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent( - "type:issue", - )}+${encodeURIComponent("state:open")}+${encodeURIComponent(title)}`, - { items: issues }, - ); + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: issues }, + }, + }, + }); const srIssues = await findSRIssues( new TestOctokit({ request: { fetch } }), + t.context.logger, title, + labels, owner, repo, ); @@ -61,9 +63,17 @@ test("Return empty array if not issues found", async (t) => { const owner = "test_user"; const repo = "test_repo"; const title = "The automated release is failing 🚨"; + const labels = []; const issues = []; const fetch = fetchMock .sandbox() + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -75,7 +85,9 @@ test("Return empty array if not issues found", async (t) => { const srIssues = await findSRIssues( new TestOctokit({ request: { fetch } }), + t.context.logger, title, + labels, owner, repo, ); @@ -89,28 +101,111 @@ test("Return empty array if not issues has matching ID", async (t) => { const owner = "test_user"; const repo = "test_repo"; const title = "The automated release is failing 🚨"; + const labels = []; const issues = [ { number: 1, body: "Issue 1 body", title }, { number: 2, body: "Issue 2 body", title }, ]; const fetch = fetchMock .sandbox() + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: issues }, + }, + }, + }); + + const srIssues = await findSRIssues( + new TestOctokit({ request: { fetch } }), + t.context.logger, + title, + labels, + owner, + repo, + ); + + t.deepEqual(srIssues, []); + t.true(fetch.done()); +}); + +test("Handle error in searchAPI fallback", async (t) => { + const owner = "test_user"; + const repo = "test_repo"; + const title = "The automated release is failing 🚨"; + const labels = []; + const issues = []; + + const response = new Response("Not Found", { + 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", + status: 403, + headers: { + "access-control-allow-origin": "*", + "access-control-expose-headers": + "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", + "content-encoding": "gzip", + "content-security-policy": "default-repo 'none'", + "content-type": "application/json; charset=utf-8", + date: "Tue, 28 May 2024 19:49:00 GMT", + "referrer-policy": + "origin-when-cross-origin, strict-origin-when-cross-origin", + server: "GitHub.com", + "strict-transport-security": + "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + vary: "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-api-version-selected": "2022-11-28", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "2**0:29*****4:3868737:6*****3:6****52C", + "x-ratelimit-limit": "30", + "x-ratelimit-remaining": "30", + "x-ratelimit-reset": "1716925800", + "x-ratelimit-resource": "search", + "x-ratelimit-used": "1", + "x-xss-protection": "0", + }, + data: { + documentation_url: + "https://docs.github.com/free-pro-team@latest/rest/overview/rate-limits-for-the-rest-api#about-secondary-rate-limits", + message: + "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.", + }, + }); + + const fetch = fetchMock + .sandbox() + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: issues }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", )}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent( "type:issue", )}+${encodeURIComponent("state:open")}+${encodeURIComponent(title)}`, - { items: issues }, + response, ); const srIssues = await findSRIssues( new TestOctokit({ request: { fetch } }), + t.context.logger, title, + labels, owner, repo, ); - t.deepEqual(srIssues, []); + t.true( + t.context.log.calledWith( + "An error occured fetching issue via fallback (with GH SearchAPI)", + ), + ); + t.log(t.context.log); t.true(fetch.done()); }); diff --git a/test/integration.test.js b/test/integration.test.js index f512c7fa..91400d35 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -2,6 +2,7 @@ import test from "ava"; import sinon from "sinon"; import SemanticReleaseError from "@semantic-release/error"; import fetchMock from "fetch-mock"; +import { RELEASE_FAIL_LABEL } from "../lib/definitions/constants.js"; import { TestOctokit } from "./helpers/test-octokit.js"; @@ -450,22 +451,29 @@ test("Comment and add labels on PR included in the releases", async (t) => { repeat: 2, }, ) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -491,6 +499,20 @@ test("Comment and add labels on PR included in the releases", async (t) => { body: ["released"], }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -556,6 +578,13 @@ test("Open a new issue with the list of errors", async (t) => { }, { repeat: 2 }, ) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -573,7 +602,7 @@ test("Open a new issue with the list of errors", async (t) => { data.body, /---\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---/, ); - t.deepEqual(data.labels, ["semantic-release"]); + t.deepEqual(data.labels, ["semantic-release", RELEASE_FAIL_LABEL]); return true; }, @@ -653,6 +682,39 @@ test("Verify, release and notify success", async (t) => { repeat: 2, }, ) + .postOnce( + (url, { body }) => + url === "https://api.github.local/graphql" && + JSON.parse(body).query.includes("query getAssociatedPRs("), + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], + }, + }, + }, + }, + }, + ) + .postOnce( + (url, { body }) => + url === "https://api.github.local/graphql" && + JSON.parse(body).query.includes("query getSRIssues("), + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .postOnce( `https://api.github.local/repos/${owner}/${repo}/releases`, { @@ -675,22 +737,6 @@ test("Verify, release and notify success", async (t) => { { html_url: releaseUrl }, { body: { draft: false } }, ) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, - }, - nodes: [prs[0]], - }, - }, - }, - }, - }) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -834,22 +880,29 @@ test("Verify, update release and notify success", async (t) => { }, }, ) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -867,6 +920,20 @@ test("Verify, update release and notify success", async (t) => { body: ["released"], }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -957,6 +1024,13 @@ test("Verify and notify failure", async (t) => { repeat: 2, }, ) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", diff --git a/test/success.test.js b/test/success.test.js index 36d88c81..29f0c892 100644 --- a/test/success.test.js +++ b/test/success.test.js @@ -215,6 +215,20 @@ test("Add comment and labels to PRs associated with release commits and issues s {}, { body: ["released"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -493,6 +507,20 @@ test("Add comment and labels to PRs associated with release commits and issues ( {}, { body: ["released"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -753,6 +781,20 @@ test("Add comment and labels to PRs associated with release commits and issues c {}, { body: ["released on @next"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://custom-url.com/prefix/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://custom-url.com/prefix/search/issues?q=${encodeURIComponent( "in:title", @@ -877,72 +919,79 @@ test("Make multiple search queries if necessary", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .post("https://api.github.local/graphql", { - data: { - repository: { - commitaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: { - oid: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commitaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: { + oid: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, - }, - commitbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: { - oid: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + commitbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb: { + oid: "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[1]], }, - nodes: [prs[1]], }, - }, - commitcccccccccccccccccccccccccccccccccccccccccc: { - oid: "cccccccccccccccccccccccccccccccccccccccccc", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + commitcccccccccccccccccccccccccccccccccccccccccc: { + oid: "cccccccccccccccccccccccccccccccccccccccccc", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[2]], }, - nodes: [prs[2]], }, - }, - commiteeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee: { - oid: "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + commiteeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee: { + oid: "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[3]], }, - nodes: [prs[3]], }, - }, - commitffffffffffffffffffffffffffffffffffffffffff: { - oid: "ffffffffffffffffffffffffffffffffffffffffff", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + commitffffffffffffffffffffffffffffffffffffffffff: { + oid: "ffffffffffffffffffffffffffffffffffffffffff", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[4]], }, - nodes: [prs[4]], }, - }, - commitgggggggggggggggggggggggggggggggggggggggggg: { - oid: "gggggggggggggggggggggggggggggggggggggggggg", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + commitgggggggggggggggggggggggggggggggggggggggggg: { + oid: "gggggggggggggggggggggggggggggggggggggggggg", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[5]], }, - nodes: [prs[5]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -1033,6 +1082,20 @@ test("Make multiple search queries if necessary", async (t) => { body: ["released"], }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -1152,32 +1215,39 @@ test("Do not add comment and labels for unrelated PR returned by search (compare full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, - }, - commit456: { - oid: "456", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + commit456: { + oid: "456", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[1]], }, - nodes: [prs[1]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: "rebased_sha" }], @@ -1203,6 +1273,20 @@ test("Do not add comment and labels for unrelated PR returned by search (compare {}, { body: ["released"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -1265,22 +1349,43 @@ test("Do not add comment and labels if no PR is associated with release commits" full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [], }, - nodes: [], }, }, }, }, - }) + ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -1333,6 +1438,13 @@ test("Do not add comment and labels if no commits is found for release", async ( full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -1485,6 +1597,20 @@ test("Do not add comment and labels to PR/issues from other repo", async (t) => {}, { body: ["released"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -1757,6 +1883,20 @@ test("Ignore missing and forbidden issues/PRs", async (t) => { {}, { body: ["released"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -1859,22 +1999,29 @@ test("Add custom comment and labels", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -1891,6 +2038,20 @@ test("Add custom comment and labels", async (t) => { {}, { body: ["released on @next", "released from master"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -1958,22 +2119,29 @@ test("Add custom label", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -1987,6 +2155,20 @@ test("Add custom label", async (t) => { {}, { body: ["custom label"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2050,22 +2232,29 @@ test("Comment on issue/PR without ading a label", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2074,6 +2263,20 @@ test("Comment on issue/PR without ading a label", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/1/comments`, { html_url: "https://github.com/successcomment-1" }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2149,22 +2352,29 @@ test("Editing the release to include all release links at the bottom", async (t) full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2173,6 +2383,20 @@ test("Editing the release to include all release links at the bottom", async (t) `https://api.github.local/repos/${owner}/${repo}/issues/1/comments`, { html_url: "https://github.com/successcomment-1" }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2259,22 +2483,29 @@ test("Editing the release to include all release links at the top", async (t) => full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2283,6 +2514,20 @@ test("Editing the release to include all release links at the top", async (t) => `https://api.github.local/repos/${owner}/${repo}/issues/1/comments`, { html_url: "https://github.com/successcomment-1" }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2366,22 +2611,29 @@ test("Editing the release to include all release links with no additional releas full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2390,6 +2642,20 @@ test("Editing the release to include all release links with no additional releas `https://api.github.local/repos/${owner}/${repo}/issues/1/comments`, { html_url: "https://github.com/successcomment-1" }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2462,22 +2728,29 @@ test("Editing the release to include all release links with no additional releas full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2486,6 +2759,20 @@ test("Editing the release to include all release links with no additional releas `https://api.github.local/repos/${owner}/${repo}/issues/1/comments`, { html_url: "https://github.com/successcomment-1" }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2551,22 +2838,29 @@ test("Editing the release to include all release links with no releases", async full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2575,6 +2869,20 @@ test("Editing the release to include all release links with no releases", async `https://api.github.local/repos/${owner}/${repo}/issues/1/comments`, { html_url: "https://github.com/successcomment-1" }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2642,22 +2950,29 @@ test("Editing the release with no ID in the release", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2666,6 +2981,20 @@ test("Editing the release with no ID in the release", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/1/comments`, { html_url: "https://github.com/successcomment-1" }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2738,32 +3067,39 @@ test("Ignore errors when adding comments and closing issues", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], }, - nodes: [prs[0]], }, - }, - commit456: { - oid: "456", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + commit456: { + oid: "456", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[1]], }, - nodes: [prs[1]], }, }, }, }, - }) + ) .getOnce( `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, [{ sha: commits[0].hash }], @@ -2785,6 +3121,20 @@ test("Ignore errors when adding comments and closing issues", async (t) => { {}, { body: ["released"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -2885,29 +3235,42 @@ test("Close open issues when a release is successful", async (t) => { full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) - .postOnce("https://api.github.local/graphql", { - data: { - repository: { - commit123: { - oid: "123", - associatedPullRequests: { - pageInfo: { - endCursor: "NI", - hasNextPage: false, + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getAssociatedPRs\(/); + return true; + }, + { + data: { + repository: { + commit123: { + oid: "123", + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [], }, - nodes: [], }, }, }, }, - }) - .getOnce( - `https://api.github.local/search/issues?q=${encodeURIComponent( - "in:title", - )}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent( - "type:issue", - )}+${encodeURIComponent("state:open")}+${encodeURIComponent(failTitle)}`, - { items: issues }, + ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: issues }, + }, + }, + }, ) .patchOnce( `https://api.github.local/repos/${owner}/${repo}/issues/2`, @@ -2991,6 +3354,20 @@ test('Skip comment on on issues/PR if "successComment" is "false"', async (t) => full_name: `${owner}/${repo}`, clone_url: `https://api.github.local/${owner}/${repo}.git`, }) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -3051,6 +3428,13 @@ test('Does not comment/label on issues/PR if "successCommentCondition" is "false .getOnce(`https://api.github.local/repos/${owner}/${repo}`, { full_name: `${owner}/${repo}`, }) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -3256,6 +3640,18 @@ test('Add comment and label to found issues/associatedPR using the "successComme `https://api.github.local/repos/${owner}/${repo}/pulls/5/commits`, [{ sha: commits[1].hash }], ) + .postOnce( + (url, { body }) => + url === "https://api.github.local/graphql" && + JSON.parse(body).query.includes("query getSRIssues("), + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -3584,6 +3980,20 @@ test('Does not comment/label associatedPR and relatedIssues created by "Bots"', {}, { body: ["released"] }, ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getSRIssues\(/); + return true; + }, + { + data: { + repository: { + issues: { nodes: [] }, + }, + }, + }, + ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( "in:title", @@ -3775,13 +4185,17 @@ test('Does not comment/label "associatedPR" when "successCommentCondition" disab {}, { body: ["released"] }, ) - .getOnce( - `https://api.github.local/search/issues?q=${encodeURIComponent( - "in:title", - )}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent( - "type:issue", - )}+${encodeURIComponent("state:open")}+${encodeURIComponent(failTitle)}`, - { items: issues }, + .postOnce( + (url, { body }) => + url === "https://api.github.local/graphql" && + JSON.parse(body).query.includes("query getSRIssues("), + { + data: { + repository: { + issues: { nodes: issues }, + }, + }, + }, ) .patchOnce( `https://api.github.local/repos/${owner}/${repo}/issues/1`,