diff --git a/lib/is-latest-release.js b/lib/is-latest-release.js new file mode 100644 index 00000000..8d4b7efd --- /dev/null +++ b/lib/is-latest-release.js @@ -0,0 +1,3 @@ +export default function isLatestRelease({ type, main }) { + return type === "release" && main ? "true" : "false"; +} diff --git a/lib/publish.js b/lib/publish.js index 752deb16..838c654d 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -11,6 +11,7 @@ import globAssets from "./glob-assets.js"; import resolveConfig from "./resolve-config.js"; import { toOctokitOptions } from "./octokit.js"; import isPrerelease from "./is-prerelease.js"; +import isLatestRelease from "./is-latest-release.js"; const debug = debugFactory("semantic-release:github"); @@ -52,6 +53,7 @@ export default async function publish(pluginConfig, context, { Octokit }) { name: template(releaseNameTemplate)(context), body: template(releaseBodyTemplate)(context), prerelease: isPrerelease(branch), + make_latest: isLatestRelease(branch), }; debug("release object: %O", release); diff --git a/test/integration.test.js b/test/integration.test.js index b4b83f55..9231ee4d 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -187,6 +187,189 @@ test("Throw SemanticReleaseError if invalid config", async (t) => { t.is(errors[8].code, "ENOGHTOKEN"); }); +test("Publish a release without assets on a main release branch", async (t) => { + const owner = "test_user"; + const repo = "test_repo"; + const env = { GITHUB_TOKEN: "github_token" }; + const nextRelease = { + gitTag: "v1.0.0", + name: "v1.0.0", + notes: "Test release note body", + }; + const options = { repositoryUrl: `https://github.com/${owner}/${repo}.git` }; + const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`; + const releaseId = 1; + + const fetch = fetchMock + .sandbox() + .getOnce(`https://api.github.local/repos/${owner}/${repo}`, { + permissions: { + push: true, + }, + clone_url: `https://api.github.local/${owner}/${repo}.git`, + }) + .postOnce( + `https://api.github.local/repos/${owner}/${repo}/releases`, + { html_url: releaseUrl, id: releaseId }, + { + body: { + tag_name: nextRelease.gitTag, + name: nextRelease.name, + body: nextRelease.notes, + prerelease: false, + make_latest: "true", + }, + }, + ); + + const result = await t.context.m.publish( + {}, + { + cwd, + env, + options, + branch: { type: "release", main: true }, + nextRelease, + logger: t.context.logger, + }, + { + Octokit: TestOctokit.defaults((options) => ({ + ...options, + request: { ...options.request, fetch }, + })), + }, + ); + + t.is(result.url, releaseUrl); + t.is(result.name, "GitHub release"); + t.is(result.id, releaseId); + t.deepEqual(t.context.log.args[0], ["Verify GitHub authentication"]); + t.true(t.context.log.calledWith("Published GitHub release: %s", releaseUrl)); + t.true(fetch.done()); +}); + +test("Publish a release without assets on a non-main release branch", async (t) => { + const owner = "test_user"; + const repo = "test_repo"; + const env = { GITHUB_TOKEN: "github_token" }; + const nextRelease = { + gitTag: "v1.0.0", + name: "v1.0.0", + notes: "Test release note body", + }; + const options = { repositoryUrl: `https://github.com/${owner}/${repo}.git` }; + const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`; + const releaseId = 1; + + const fetch = fetchMock + .sandbox() + .getOnce(`https://api.github.local/repos/${owner}/${repo}`, { + permissions: { + push: true, + }, + clone_url: `https://api.github.local/${owner}/${repo}.git`, + }) + .postOnce( + `https://api.github.local/repos/${owner}/${repo}/releases`, + { html_url: releaseUrl, id: releaseId }, + { + body: { + tag_name: nextRelease.gitTag, + name: nextRelease.name, + body: nextRelease.notes, + prerelease: true, + make_latest: "false", + }, + }, + ); + + const result = await t.context.m.publish( + {}, + { + cwd, + env, + options, + branch: { type: "release" }, + nextRelease, + logger: t.context.logger, + }, + { + Octokit: TestOctokit.defaults((options) => ({ + ...options, + request: { ...options.request, fetch }, + })), + }, + ); + + t.is(result.url, releaseUrl); + t.is(result.name, "GitHub release"); + t.is(result.id, releaseId); + t.deepEqual(t.context.log.args[0], ["Verify GitHub authentication"]); + t.true(t.context.log.calledWith("Published GitHub release: %s", releaseUrl)); + t.true(fetch.done()); +}); + +test("Publish a release without assets on a maintenance branch", async (t) => { + const owner = "test_user"; + const repo = "test_repo"; + const env = { GITHUB_TOKEN: "github_token" }; + const nextRelease = { + gitTag: "v1.0.0", + name: "v1.0.0", + notes: "Test release note body", + }; + const options = { repositoryUrl: `https://github.com/${owner}/${repo}.git` }; + const releaseUrl = `https://github.com/${owner}/${repo}/releases/${nextRelease.version}`; + const releaseId = 1; + + const fetch = fetchMock + .sandbox() + .getOnce(`https://api.github.local/repos/${owner}/${repo}`, { + permissions: { + push: true, + }, + clone_url: `https://api.github.local/${owner}/${repo}.git`, + }) + .postOnce( + `https://api.github.local/repos/${owner}/${repo}/releases`, + { html_url: releaseUrl, id: releaseId }, + { + body: { + tag_name: nextRelease.gitTag, + name: nextRelease.name, + body: nextRelease.notes, + prerelease: false, + make_latest: "false", + }, + }, + ); + + const result = await t.context.m.publish( + {}, + { + cwd, + env, + options, + branch: { type: "maintenance" }, + nextRelease, + logger: t.context.logger, + }, + { + Octokit: TestOctokit.defaults((options) => ({ + ...options, + request: { ...options.request, fetch }, + })), + }, + ); + + t.is(result.url, releaseUrl); + t.is(result.name, "GitHub release"); + t.is(result.id, releaseId); + t.deepEqual(t.context.log.args[0], ["Verify GitHub authentication"]); + t.true(t.context.log.calledWith("Published GitHub release: %s", releaseUrl)); + t.true(fetch.done()); +}); + test("Publish a release with an array of assets", async (t) => { const owner = "test_user"; const repo = "test_repo"; @@ -227,6 +410,7 @@ test("Publish a release with an array of assets", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ) @@ -322,6 +506,7 @@ test("Publish a release with release information in assets", async (t) => { body: nextRelease.notes, draft: true, prerelease: true, + make_latest: "false", }, }, ) @@ -718,6 +903,7 @@ test("Verify, release and notify success", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ) diff --git a/test/is-latest-release.test.js b/test/is-latest-release.test.js new file mode 100644 index 00000000..966be457 --- /dev/null +++ b/test/is-latest-release.test.js @@ -0,0 +1,39 @@ +import test from "ava"; +import isLatestRelease from "../lib/is-latest-release.js"; + +test("Test for empty object", (t) => { + const branch = {}; + t.is(isLatestRelease(branch), "false"); +}); + +test("Test if type release and main is used correctly", (t) => { + const branch = { + type: "release", + main: true, + }; + t.is(isLatestRelease(branch), "true"); +}); + +test("Test if type prerelease is used correctly", (t) => { + const branch = { + type: "prerelease", + main: true, + }; + t.is(isLatestRelease(branch), "false"); +}); + +test("Test if type main property as boolean is used correctly", (t) => { + const branch = { + type: "release", + main: false, + }; + t.is(isLatestRelease(branch), "false"); +}); + +test("Test maintenance branch returns false", (t) => { + const branch = { + type: "maintenance", + main: false, + }; + t.is(isLatestRelease(branch), "false"); +}); diff --git a/test/publish.test.js b/test/publish.test.js index 3009068a..e321051b 100644 --- a/test/publish.test.js +++ b/test/publish.test.js @@ -53,6 +53,7 @@ test("Publish a release without creating discussion", async (t) => { name: nextRelease.name, body: nextRelease.notes, prerelease: false, + make_latest: "true", }, }, ); @@ -117,6 +118,7 @@ test("Publish a release and create discussion", async (t) => { name: nextRelease.name, body: nextRelease.notes, prerelease: false, + make_latest: "true", discussion_category_name: pluginConfig.discussionCategoryName, }, }, @@ -182,6 +184,7 @@ test("Publish a release on a channel", async (t) => { name: nextRelease.name, body: nextRelease.notes, prerelease: true, + make_latest: "false", }, }, ); @@ -212,7 +215,7 @@ test("Publish a release on a channel", async (t) => { t.true(fetch.done()); }); -test("Publish a prerelease wihtout creating discussion", async (t) => { +test("Publish a prerelease without creating discussion", async (t) => { const owner = "test_user"; const repo = "test_repo"; const env = { GITHUB_TOKEN: "github_token" }; @@ -242,6 +245,7 @@ test("Publish a prerelease wihtout creating discussion", async (t) => { name: nextRelease.name, body: nextRelease.notes, prerelease: true, + make_latest: "false", }, }, ); @@ -305,6 +309,7 @@ test("Publish a prerelease and create discussion", async (t) => { name: nextRelease.name, body: nextRelease.notes, prerelease: true, + make_latest: "false", discussion_category_name: pluginConfig.discussionCategoryName, }, }, @@ -371,6 +376,7 @@ test("Publish a maintenance release", async (t) => { name: nextRelease.name, body: nextRelease.notes, prerelease: false, + make_latest: "false", }, }, ); @@ -448,6 +454,7 @@ test("Publish a release with one asset", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ) @@ -535,6 +542,7 @@ test("Publish a release with one asset and custom github url", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ) @@ -616,6 +624,7 @@ test("Publish a release with an array of missing assets", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ) @@ -705,6 +714,7 @@ test("Publish a release with asset and create discussion", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ) @@ -790,6 +800,7 @@ test("Publish a draft release", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ); @@ -862,6 +873,7 @@ test("Publish a draft release with one asset", async (t) => { body: nextRelease.notes, draft: true, prerelease: false, + make_latest: "true", }, }, ) @@ -934,6 +946,7 @@ test("Publish a release when env.GITHUB_URL is set to https://github.com (Defaul name: nextRelease.name, body: nextRelease.notes, prerelease: false, + make_latest: "true", }, }, ); @@ -997,6 +1010,7 @@ test("Publish a custom release body", async (t) => { name: nextRelease.name, body: `To install this run npm install package@${nextRelease.name}\n\n${nextRelease.notes}`, prerelease: false, + make_latest: "true", }, }, ); @@ -1060,6 +1074,7 @@ test("Publish a custom release name", async (t) => { name: `omg its the best release: ${nextRelease.name} 🌈🌈`, body: nextRelease.notes, prerelease: false, + make_latest: "true", }, }, );