diff --git a/lib/success.js b/lib/success.js index 5363863c..b82ec468 100644 --- a/lib/success.js +++ b/lib/success.js @@ -57,16 +57,19 @@ export default async function success(pluginConfig, context, { Octokit }) { const errors = []; - if (successComment === false || isEmpty(commits)) { + if ( + (successComment === false && releasedLabels === false) || + isEmpty(commits) + ) { if (isEmpty(commits)) { logger.log("No commits found in release"); } - logger.log("Skip commenting on issues and pull requests."); + logger.log("Skip commenting / adding labels on issues and pull requests."); logger.warn( `DEPRECATION: 'false' for 'successComment' is deprecated and will be removed in a future major version. Use 'successCommentCondition' instead.`, ); - } else if (successCommentCondition === false) { - logger.log("Skip commenting on issues and pull requests."); + } else if (successCommentCondition === false && releasedLabels === false) { + logger.log("Skip commenting / adding labels on issues and pull requests."); } else { const parser = issueParser( "github", @@ -202,23 +205,25 @@ export default async function success(pluginConfig, context, { Octokit }) { return; } - const body = successComment - ? template(successComment)({ ...context, issue }) - : getSuccessComment(issue, releaseInfos, nextRelease); try { - const comment = { owner, repo, issue_number: issue.number, body }; - debug("create comment: %O", comment); - const { - data: { html_url: url }, - } = await octokit.request( - "POST /repos/{owner}/{repo}/issues/{issue_number}/comments", - comment, - ); - logger.log( - `Added comment to ${issueOrPR} #%d: %s`, - issue.number, - url, - ); + if (successComment !== false) { + const body = successComment + ? template(successComment)({ ...context, issue }) + : getSuccessComment(issue, releaseInfos, nextRelease); + const comment = { owner, repo, issue_number: issue.number, body }; + debug("create comment: %O", comment); + const { + data: { html_url: url }, + } = await octokit.request( + "POST /repos/{owner}/{repo}/issues/{issue_number}/comments", + comment, + ); + logger.log( + `Added comment to ${issueOrPR} #%d: %s`, + issue.number, + url, + ); + } if (releasedLabels) { const labels = releasedLabels.map((label) => @@ -242,18 +247,18 @@ export default async function success(pluginConfig, context, { Octokit }) { } catch (error) { if (error.status === 403) { logger.error( - `Not allowed to add a comment to the issue/PR #%d.`, + `Not allowed to add a comment/label to the issue/PR #%d.`, issue.number, ); } else if (error.status === 404) { logger.error( - `Failed to add a comment to the issue/PR #%d as it doesn't exist.`, + `Failed to add a comment/label to the issue/PR #%d as it doesn't exist.`, issue.number, ); } else { errors.push(error); logger.error( - `Failed to add a comment to the issue/PR #%d.`, + `Failed to add a comment/label to the issue/PR #%d.`, issue.number, ); // Don't throw right away and continue to update other issues diff --git a/test/integration.test.js b/test/integration.test.js index ffcae3ed..0830413e 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -501,7 +501,7 @@ test("Comment and add labels on PR included in the releases", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( @@ -749,7 +749,7 @@ test("Verify, release and notify success", async (t) => { .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .getOnce( `https://api.github.local/search/issues?q=${encodeURIComponent( @@ -922,7 +922,7 @@ test("Verify, update release and notify success", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( diff --git a/test/success.test.js b/test/success.test.js index 6f8a4ed5..142a7903 100644 --- a/test/success.test.js +++ b/test/success.test.js @@ -197,7 +197,7 @@ test("Add comment and labels to PRs associated with release commits and issues s .postOnce( `https://api.github.local/repos/${redirectedOwner}/${redirectedRepo}/issues/1/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( `https://api.github.local/repos/${redirectedOwner}/${redirectedRepo}/issues/2/comments`, @@ -206,7 +206,7 @@ test("Add comment and labels to PRs associated with release commits and issues s .postOnce( `https://api.github.local/repos/${redirectedOwner}/${redirectedRepo}/issues/2/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( `https://api.github.local/repos/${redirectedOwner}/${redirectedRepo}/issues/3/comments`, @@ -215,7 +215,7 @@ test("Add comment and labels to PRs associated with release commits and issues s .postOnce( `https://api.github.local/repos/${redirectedOwner}/${redirectedRepo}/issues/3/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( `https://api.github.local/repos/${redirectedOwner}/${redirectedRepo}/issues/4/comments`, @@ -224,7 +224,7 @@ test("Add comment and labels to PRs associated with release commits and issues s .postOnce( `https://api.github.local/repos/${redirectedOwner}/${redirectedRepo}/issues/4/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( (url, { body }) => { @@ -769,7 +769,7 @@ test("Add comment and labels to PRs associated with release commits and issues c .postOnce( `https://custom-url.com/prefix/repos/${owner}/${repo}/issues/1/labels`, {}, - { body: ["released on @next"] }, + { labels: ["released on @next"] }, ) .postOnce( `https://custom-url.com/prefix/repos/${owner}/${repo}/issues/2/comments`, @@ -780,7 +780,7 @@ test("Add comment and labels to PRs associated with release commits and issues c .postOnce( `https://custom-url.com/prefix/repos/${owner}/${repo}/issues/2/labels`, {}, - { body: ["released on @next"] }, + { labels: ["released on @next"] }, ) .postOnce( `https://custom-url.com/prefix/repos/${owner}/${repo}/issues/3/comments`, @@ -791,7 +791,7 @@ test("Add comment and labels to PRs associated with release commits and issues c .postOnce( `https://custom-url.com/prefix/repos/${owner}/${repo}/issues/3/labels`, {}, - { body: ["released on @next"] }, + { labels: ["released on @next"] }, ) .postOnce( `https://custom-url.com/prefix/repos/${owner}/${repo}/issues/4/comments`, @@ -802,7 +802,7 @@ test("Add comment and labels to PRs associated with release commits and issues c .postOnce( `https://custom-url.com/prefix/repos/${owner}/${repo}/issues/4/labels`, {}, - { body: ["released on @next"] }, + { labels: ["released on @next"] }, ) .postOnce( (url, { body }) => { @@ -1047,7 +1047,7 @@ test("Make multiple search queries if necessary", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( @@ -1058,7 +1058,7 @@ test("Make multiple search queries if necessary", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/2/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( @@ -1069,7 +1069,7 @@ test("Make multiple search queries if necessary", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/3/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( @@ -1080,7 +1080,7 @@ test("Make multiple search queries if necessary", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/4/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( @@ -1091,7 +1091,7 @@ test("Make multiple search queries if necessary", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/5/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( @@ -1102,7 +1102,7 @@ test("Make multiple search queries if necessary", async (t) => { `https://api.github.local/repos/${owner}/${repo}/issues/6/labels`, {}, { - body: ["released"], + labels: ["released"], }, ) .postOnce( @@ -1294,7 +1294,7 @@ test("Do not add comment and labels for unrelated PR returned by search (compare .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( (url, { body }) => { @@ -1498,7 +1498,9 @@ test("Do not add comment and labels if no commits is found for release", async ( t.true(fetch.done()); t.true(t.context.log.calledWith("No commits found in release")); t.true( - t.context.log.calledWith("Skip commenting on issues and pull requests."), + t.context.log.calledWith( + "Skip commenting / adding labels on issues and pull requests.", + ), ); }); @@ -1620,7 +1622,7 @@ test("Do not add comment and labels to PR/issues from other repo", async (t) => .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/2/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( (url, { body }) => { @@ -1889,7 +1891,7 @@ test("Ignore missing and forbidden issues/PRs", async (t) => { .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/2/comments`, @@ -1906,7 +1908,7 @@ test("Ignore missing and forbidden issues/PRs", async (t) => { .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/4/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/5/comments`, @@ -1915,7 +1917,7 @@ test("Ignore missing and forbidden issues/PRs", async (t) => { .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/5/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( (url, { body }) => { @@ -1990,13 +1992,13 @@ test("Ignore missing and forbidden issues/PRs", async (t) => { ); t.true( t.context.error.calledWith( - "Failed to add a comment to the issue/PR #%d as it doesn't exist.", + "Failed to add a comment/label to the issue/PR #%d as it doesn't exist.", 2, ), ); t.true( t.context.error.calledWith( - "Not allowed to add a comment to the issue/PR #%d.", + "Not allowed to add a comment/label to the issue/PR #%d.", 3, ), ); @@ -2070,7 +2072,7 @@ test("Add custom comment and labels", async (t) => { .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, - { body: ["released on @next", "released from master"] }, + { labels: ["released on @next", "released from master"] }, ) .postOnce( (url, { body }) => { @@ -2187,7 +2189,7 @@ test("Add custom label", async (t) => { .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, {}, - { body: ["custom label"] }, + { labels: ["custom label"] }, ) .postOnce( (url, { body }) => { @@ -2245,7 +2247,7 @@ test("Add custom label", async (t) => { t.true(fetch.done()); }); -test("Comment on issue/PR without ading a label", async (t) => { +test("Comment on issue/PR without adding a label", async (t) => { const owner = "test_user"; const repo = "test_repo"; const env = { GITHUB_TOKEN: "github_token" }; @@ -3153,7 +3155,7 @@ test("Ignore errors when adding comments and closing issues", async (t) => { .postOnce( `https://api.github.local/repos/${owner}/${repo}/issues/2/labels`, {}, - { body: ["released"] }, + { labels: ["released"] }, ) .postOnce( (url, { body }) => { @@ -3223,7 +3225,7 @@ test("Ignore errors when adding comments and closing issues", async (t) => { t.is(error2.status, 500); t.true( t.context.error.calledWith( - "Failed to add a comment to the issue/PR #%d.", + "Failed to add a comment/label to the issue/PR #%d.", 1, ), ); @@ -3367,7 +3369,126 @@ test('Skip comment on on issues/PR if "successComment" is "false"', async (t) => const env = { GITHUB_TOKEN: "github_token" }; const failTitle = "The automated release is failing 🚨"; const pluginConfig = { failTitle, successComment: false }; + const prs = [{ number: 1, pull_request: {}, state: "closed" }]; + const options = { + branch: "master", + repositoryUrl: `https://github.com/${owner}/${repo}.git`, + }; + const commits = [ + { + hash: "123", + message: "Commit 1 message\n\n Fix #1", + tree: { long: "aaa" }, + }, + ]; + const nextRelease = { version: "1.0.0" }; + const releases = [ + { name: "GitHub release", url: "https://github.com/release" }, + ]; + + const fetch = fetchMock + .sandbox() + .getOnce(`https://api.github.local/repos/${owner}/${repo}`, { + full_name: `${owner}/${repo}`, + }) + .postOnce("https://api.github.local/graphql", { + data: { + repository: { + commit123: { + associatedPullRequests: { + pageInfo: { + endCursor: "NI", + hasNextPage: false, + }, + nodes: [prs[0]], + }, + }, + }, + }, + }) + .getOnce( + `https://api.github.local/repos/${owner}/${repo}/pulls/1/commits`, + [{ sha: commits[0].hash }], + ) + .postOnce( + `https://api.github.local/repos/${owner}/${repo}/issues/1/labels`, + {}, + { labels: ["released"] }, + ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getRelatedIssues\(/); + return true; + }, + { + data: { + repository: {}, + }, + }, + ) + .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", + )}+${encodeURIComponent( + `repo:${owner}/${repo}`, + )}+${encodeURIComponent("type:issue")}+${encodeURIComponent( + "state:open", + )}+${encodeURIComponent(failTitle)}`, + { items: [] }, + ); + + await success( + pluginConfig, + { + env, + options, + commits, + nextRelease, + releases, + logger: t.context.logger, + }, + { + Octokit: TestOctokit.defaults((options) => ({ + ...options, + request: { ...options.request, fetch }, + })), + }, + ); + + t.true( + t.context.log.calledWith("Added labels %O to issue #%d", ["released"], 1), + ); + + t.true(fetch.done()); +}); + +test('Skip comment on issues/PR and skip label if "successComment" is "false" / "releasedLabels" is "false"', async (t) => { + const owner = "test_user"; + const repo = "test_repo"; + const env = { GITHUB_TOKEN: "github_token" }; + const failTitle = "The automated release is failing 🚨"; + const pluginConfig = { + failTitle, + successComment: false, + releasedLabels: false, + }; const options = { + branch: "master", repositoryUrl: `https://github.com/${owner}/${repo}.git`, }; const commits = [ @@ -3431,7 +3552,9 @@ test('Skip comment on on issues/PR if "successComment" is "false"', async (t) => ); t.true( - t.context.log.calledWith("Skip commenting on issues and pull requests."), + t.context.log.calledWith( + "Skip commenting / adding labels on issues and pull requests.", + ), ); t.true(fetch.done()); }); @@ -3462,19 +3585,61 @@ 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: [] }, + .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: [], + }, + }, + }, }, }, - }) + ) + .postOnce( + (url, { body }) => { + t.is(url, "https://api.github.local/graphql"); + t.regex(JSON.parse(body).query, /query getRelatedIssues\(/); + return true; + }, + { + data: { + repository: {}, + }, + }, + ) + .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", - )}+${encodeURIComponent(`repo:${owner}/${repo}`)}+${encodeURIComponent( - "type:issue", - )}+${encodeURIComponent("state:open")}+${encodeURIComponent(failTitle)}`, + )}+${encodeURIComponent( + `repo:${owner}/${repo}`, + )}+${encodeURIComponent("type:issue")}+${encodeURIComponent( + "state:open", + )}+${encodeURIComponent(failTitle)}`, { items: [] }, ); @@ -3483,7 +3648,6 @@ test('Does not comment/label on issues/PR if "successCommentCondition" is "false { env, options, - branch: { name: "master" }, commits, nextRelease, releases, @@ -3497,13 +3661,10 @@ test('Does not comment/label on issues/PR if "successCommentCondition" is "false }, ); - t.true( - t.context.log.calledWith("Skip commenting on issues and pull requests."), - ); t.true(fetch.done()); }); -test('Add comment and label to found issues/associatedPR using the "successCommentCondition": if specific label is found', async (t) => { +test('Add comment and label to found issues/associated PR using the "successCommentCondition": if specific label is found', async (t) => { const owner = "test_user"; const repo = "test_repo"; const env = { GITHUB_TOKEN: "github_token" };