diff --git a/lib/definitions/errors.js b/lib/definitions/errors.js index 7df6336a..51508538 100644 --- a/lib/definitions/errors.js +++ b/lib/definitions/errors.js @@ -41,20 +41,20 @@ Your configuration for the \`labels\` option is \`${stringify(labels)}\`.`, }), EINVALIDGITLABURL: () => ({ message: 'The git repository URL is not a valid GitLab URL.', - details: `The **semantic-release** \`repositoryUrl\` option must a valid GitLab URL with the format \`/.git\`. + details: `The **semantic-release** \`repositoryUrl\` option must a valid GitLab URL with the format \`/.git\`. By default the \`repositoryUrl\` option is retrieved from the \`repository\` property of your \`package.json\` or the [git origin url](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) of the repository cloned by your CI environment.`, }), - EINVALIDGLTOKEN: ({repoId}) => ({ + EINVALIDGLTOKEN: ({projectPath}) => ({ message: 'Invalid GitLab token.', details: `The [GitLab token](${linkify( 'README.md#gitlab-authentication' - )}) configured in the \`GL_TOKEN\` or \`GITLAB_TOKEN\` environment variable must be a valid [personal access token](https://docs.gitlab.com/ce/user/profile/personal_access_tokens.html) allowing to push to the repository ${repoId}. + )}) configured in the \`GL_TOKEN\` or \`GITLAB_TOKEN\` environment variable must be a valid [personal access token](https://docs.gitlab.com/ce/user/profile/personal_access_tokens.html) allowing to push to the repository ${projectPath}. Please make sure to set the \`GL_TOKEN\` or \`GITLAB_TOKEN\` environment variable in your CI with the exact value of the GitLab personal token.`, }), - EMISSINGREPO: ({repoId}) => ({ - message: `The repository ${repoId} doesn't exist.`, + EMISSINGREPO: ({projectPath}) => ({ + message: `The repository ${projectPath} doesn't exist.`, details: `The **semantic-release** \`repositoryUrl\` option must refer to your GitLab repository. The repository must be accessible with the [GitLab API](https://docs.gitlab.com/ce/api/README.html). By default the \`repositoryUrl\` option is retrieved from the \`repository\` property of your \`package.json\` or the [git origin url](https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes) of the repository cloned by your CI environment. @@ -63,21 +63,21 @@ If you are using [GitLab Enterprise Edition](https://about.gitlab.com/gitlab-ee) 'README.md#options' )}).`, }), - EGLNOPUSHPERMISSION: ({repoId}) => ({ - message: `The GitLab token doesn't allow to push on the repository ${repoId}.`, + EGLNOPUSHPERMISSION: ({projectPath}) => ({ + message: `The GitLab token doesn't allow to push on the repository ${projectPath}.`, details: `The user associated with the [GitLab token](${linkify( 'README.md#gitlab-authentication' - )}) configured in the \`GL_TOKEN\` or \`GITLAB_TOKEN\` environment variable must allows to push to the repository ${repoId}. + )}) configured in the \`GL_TOKEN\` or \`GITLAB_TOKEN\` environment variable must allows to push to the repository ${projectPath}. -Please make sure the GitLab user associated with the token has the [permission to push](https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions) to the repository ${repoId}.`, +Please make sure the GitLab user associated with the token has the [permission to push](https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions) to the repository ${projectPath}.`, }), - EGLNOPULLPERMISSION: ({repoId}) => ({ - message: `The GitLab token doesn't allow to pull from the repository ${repoId}.`, + EGLNOPULLPERMISSION: ({projectPath}) => ({ + message: `The GitLab token doesn't allow to pull from the repository ${projectPath}.`, details: `The user associated with the [GitLab token](${linkify( 'README.md#gitlab-authentication' - )}) configured in the \`GL_TOKEN\` or \`GITLAB_TOKEN\` environment variable must allow pull from the repository ${repoId}. + )}) configured in the \`GL_TOKEN\` or \`GITLAB_TOKEN\` environment variable must allow pull from the repository ${projectPath}. -Please make sure the GitLab user associated with the token has the [permission to push](https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions) to the repository ${repoId}.`, +Please make sure the GitLab user associated with the token has the [permission to push](https://docs.gitlab.com/ee/user/permissions.html#project-members-permissions) to the repository ${projectPath}.`, }), ENOGLTOKEN: ({repositoryUrl}) => ({ message: 'No GitLab token specified.', diff --git a/lib/fail.js b/lib/fail.js index d33a0c90..05516313 100644 --- a/lib/fail.js +++ b/lib/fail.js @@ -4,8 +4,8 @@ import got from "got"; import _debug from "debug"; const debug = _debug("semantic-release:gitlab"); import resolveConfig from "./resolve-config.js"; -import getRepoId from "./get-repo-id.js"; import getFailComment from "./get-fail-comment.js"; +import getProjectContext from "./get-project-context.js"; export default async (pluginConfig, context) => { const { @@ -25,8 +25,8 @@ export default async (pluginConfig, context) => { assignee, retryLimit, } = resolveConfig(pluginConfig, context); - const repoId = getRepoId(context, gitlabUrl, repositoryUrl); - const encodedRepoId = encodeURIComponent(repoId); + const { encodedProjectPath, projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl); + const apiOptions = { headers: { "PRIVATE-TOKEN": gitlabToken }, retry: { limit: retryLimit }, @@ -42,7 +42,7 @@ Using 'false' for 'failComment' or 'failTitle' is deprecated and will be removed const encodedFailTitle = encodeURIComponent(failTitle); const description = failComment ? template(failComment)({ branch, errors }) : getFailComment(branch, errors); - const issuesEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/issues`); + const issuesEndpoint = urlJoin(projectApiUrl, `issues`); const openFailTitleIssueEndpoint = urlJoin(issuesEndpoint, `?state=opened&search=${encodedFailTitle}`); const openFailTitleIssues = await got(openFailTitleIssueEndpoint, { ...apiOptions }).json(); @@ -67,7 +67,7 @@ Using 'false' for 'failComment' or 'failTitle' is deprecated and will be removed const { id, web_url } = existingIssue; logger.log("Commented on issue #%d: %s.", id, web_url); } else { - const newIssue = { id: encodedRepoId, description, labels, title: failTitle, assignee_id: assignee }; + const newIssue = { id: encodedProjectPath, description, labels, title: failTitle, assignee_id: assignee }; debug("create issue: %O", newIssue); /* eslint camelcase: off */ diff --git a/lib/get-project-context.js b/lib/get-project-context.js new file mode 100644 index 00000000..ad7bd049 --- /dev/null +++ b/lib/get-project-context.js @@ -0,0 +1,27 @@ +import escapeStringRegexp from "escape-string-regexp"; +import parseUrl from "parse-url"; +import urlJoin from "url-join"; + +export default ( + { envCi: { service } = {}, env: { CI_PROJECT_ID, CI_PROJECT_PATH } }, + gitlabUrl, + gitlabApiUrl, + repositoryUrl +) => { + const projectId = service === "gitlab" && CI_PROJECT_ID ? CI_PROJECT_ID : null; + const projectPath = + service === "gitlab" && CI_PROJECT_PATH + ? CI_PROJECT_PATH + : parseUrl(repositoryUrl) + .pathname.replace(new RegExp(`^${escapeStringRegexp(parseUrl(gitlabUrl).pathname)}`), "") + .replace(/^\//, "") + .replace(/\/$/, "") + .replace(/\.git$/, ""); + const encodedProjectPath = encodeURIComponent(projectPath); + const projectApiUrl = urlJoin(gitlabApiUrl, `/projects/${projectId ?? encodedProjectPath}`); + return { + projectPath, + encodedProjectPath, + projectApiUrl, + }; +}; diff --git a/lib/get-repo-id.js b/lib/get-repo-id.js deleted file mode 100644 index f56cf82b..00000000 --- a/lib/get-repo-id.js +++ /dev/null @@ -1,11 +0,0 @@ -import parseUrl from "parse-url"; -import escapeStringRegexp from "escape-string-regexp"; - -export default ({ envCi: { service } = {}, env: { CI_PROJECT_PATH } }, gitlabUrl, repositoryUrl) => - service === "gitlab" && CI_PROJECT_PATH - ? CI_PROJECT_PATH - : parseUrl(repositoryUrl) - .pathname.replace(new RegExp(`^${escapeStringRegexp(parseUrl(gitlabUrl).pathname)}`), "") - .replace(/^\//, "") - .replace(/\/$/, "") - .replace(/\.git$/, ""); diff --git a/lib/publish.js b/lib/publish.js index f3a1cc5c..3f92f7e4 100644 --- a/lib/publish.js +++ b/lib/publish.js @@ -9,9 +9,9 @@ import got from "got"; import _debug from "debug"; const debug = _debug("semantic-release:gitlab"); import resolveConfig from "./resolve-config.js"; -import getRepoId from "./get-repo-id.js"; import getAssets from "./glob-assets.js"; import { RELEASE_NAME } from "./definitions/constants.js"; +import getProjectContext from "./get-project-context.js"; const isUrlScheme = (value) => /^(https|http|ftp):\/\//.test(value); @@ -27,8 +27,8 @@ export default async (pluginConfig, context) => { context ); const assetsList = []; - const repoId = getRepoId(context, gitlabUrl, repositoryUrl); - const encodedRepoId = encodeURIComponent(repoId); + const { projectPath, projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl); + const encodedGitTag = encodeURIComponent(gitTag); const encodedVersion = encodeURIComponent(version); const apiOptions = { @@ -52,7 +52,7 @@ export default async (pluginConfig, context) => { retry: { limit: retryLimit }, }; - debug("repoId: %o", repoId); + debug("projectPath: %o", projectPath); debug("release name: %o", gitTag); debug("release ref: %o", gitHead); debug("milestones: %o", milestones); @@ -114,8 +114,8 @@ export default async (pluginConfig, context) => { const encodedLabel = encodeURIComponent(label); // https://docs.gitlab.com/ee/user/packages/generic_packages/#publish-a-package-file uploadEndpoint = urlJoin( - gitlabApiUrl, - `/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}?${ + projectApiUrl, + `packages/generic/release/${encodedVersion}/${encodedLabel}?${ status ? `status=${status}&` : "" }select=package_file` ); @@ -130,17 +130,14 @@ export default async (pluginConfig, context) => { } // https://docs.gitlab.com/ee/user/packages/generic_packages/#download-package-file - const url = urlJoin( - gitlabApiUrl, - `/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}` - ); + const url = urlJoin(projectApiUrl, `packages/generic/release/${encodedVersion}/${encodedLabel}`); assetsList.push({ label, alt: "release", url, type: "package", filepath }); logger.log("Uploaded file: %s (%s)", url, response.file.url); } else { // Handle normal assets - uploadEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/uploads`); + uploadEndpoint = urlJoin(projectApiUrl, "uploads"); debug("POST-ing the file %s to %s", file, uploadEndpoint); @@ -167,7 +164,7 @@ export default async (pluginConfig, context) => { debug("Create a release for git tag %o with commit %o", gitTag, gitHead); - const createReleaseEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/releases`); + const createReleaseEndpoint = urlJoin(projectApiUrl, "releases"); const json = { /* eslint-disable camelcase */ @@ -178,7 +175,7 @@ export default async (pluginConfig, context) => { links: assetsList.map(({ label, alt, url, type, filepath, rawUrl }) => { return { name: label || alt, - url: rawUrl || (isUrlScheme(url) ? url : urlJoin(gitlabUrl, repoId, url)), + url: rawUrl || (isUrlScheme(url) ? url : urlJoin(gitlabUrl, projectPath, url)), link_type: type, filepath, }; @@ -202,7 +199,7 @@ export default async (pluginConfig, context) => { logger.log("Published GitLab release: %s", gitTag); - const releaseUrl = urlJoin(gitlabUrl, repoId, `/-/releases/${encodedGitTag}`); + const releaseUrl = urlJoin(gitlabUrl, projectPath, `/-/releases/${encodedGitTag}`); return { name: RELEASE_NAME, url: releaseUrl }; }; diff --git a/lib/success.js b/lib/success.js index f7ed11f9..929b6b9e 100644 --- a/lib/success.js +++ b/lib/success.js @@ -4,7 +4,7 @@ import got from "got"; import _debug from "debug"; const debug = _debug("semantic-release:gitlab"); import resolveConfig from "./resolve-config.js"; -import getRepoId from "./get-repo-id.js"; +import getProjectContext from "./get-project-context.js"; import getSuccessComment from "./get-success-comment.js"; export default async (pluginConfig, context) => { @@ -17,8 +17,7 @@ export default async (pluginConfig, context) => { } = context; const { gitlabToken, gitlabUrl, gitlabApiUrl, successComment, successCommentCondition, proxy, retryLimit } = resolveConfig(pluginConfig, context); - const repoId = getRepoId(context, gitlabUrl, repositoryUrl); - const encodedRepoId = encodeURIComponent(repoId); + const { projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl); const apiOptions = { headers: { "PRIVATE-TOKEN": gitlabToken }, retry: { limit: retryLimit }, @@ -77,10 +76,7 @@ Using 'false' for 'successComment' is deprecated and will be removed in a future }; const getRelatedMergeRequests = async (commitHash) => { - const relatedMergeRequestsEndpoint = urlJoin( - gitlabApiUrl, - `/projects/${encodedRepoId}/repository/commits/${commitHash}/merge_requests` - ); + const relatedMergeRequestsEndpoint = urlJoin(projectApiUrl, `repository/commits/${commitHash}/merge_requests`); debug("Getting MRs from %s", relatedMergeRequestsEndpoint); const relatedMergeRequests = await got .get(relatedMergeRequestsEndpoint, { diff --git a/lib/verify.js b/lib/verify.js index e7091ef1..fdfc3b7f 100644 --- a/lib/verify.js +++ b/lib/verify.js @@ -1,11 +1,10 @@ import { isString, isPlainObject, isNil, isArray } from "lodash-es"; -import urlJoin from "url-join"; import got from "got"; import _debug from "debug"; const debug = _debug("semantic-release:gitlab"); import AggregateError from "aggregate-error"; import resolveConfig from "./resolve-config.js"; -import getRepoId from "./get-repo-id.js"; +import getProjectContext from "./get-project-context.js"; import getError from "./get-error.js"; const isNonEmptyString = (value) => isString(value) && value.trim(); @@ -32,10 +31,10 @@ export default async (pluginConfig, context) => { logger, } = context; const { gitlabToken, gitlabUrl, gitlabApiUrl, proxy, ...options } = resolveConfig(pluginConfig, context); - const repoId = getRepoId(context, gitlabUrl, repositoryUrl); + const { projectPath, projectApiUrl } = getProjectContext(context, gitlabUrl, gitlabApiUrl, repositoryUrl); debug("apiUrl: %o", gitlabApiUrl); - debug("repoId: %o", repoId); + debug("projectPath: %o", projectPath); const isValid = (option, value) => { const validator = VALIDATORS[option]; @@ -46,7 +45,7 @@ export default async (pluginConfig, context) => { .filter(([option, value]) => !isValid(option, value)) .map(([option, value]) => getError(`EINVALID${option.toUpperCase()}`, { [option]: value })); - if (!repoId) { + if (!projectPath) { errors.push(getError("EINVALIDGITLABURL")); } @@ -54,7 +53,7 @@ export default async (pluginConfig, context) => { errors.push(getError("ENOGLTOKEN", { repositoryUrl })); } - if (gitlabToken && repoId) { + if (gitlabToken && projectPath) { let projectAccess; let groupAccess; @@ -64,7 +63,7 @@ export default async (pluginConfig, context) => { ({ permissions: { project_access: projectAccess, group_access: groupAccess }, } = await got - .get(urlJoin(gitlabApiUrl, `/projects/${encodeURIComponent(repoId)}`), { + .get(projectApiUrl, { headers: { "PRIVATE-TOKEN": gitlabToken }, ...proxy, }) @@ -73,17 +72,17 @@ export default async (pluginConfig, context) => { context.options.dryRun && !((projectAccess && projectAccess.access_level >= 10) || (groupAccess && groupAccess.access_level >= 10)) ) { - errors.push(getError("EGLNOPULLPERMISSION", { repoId })); + errors.push(getError("EGLNOPULLPERMISSION", { projectPath })); } else if ( !((projectAccess && projectAccess.access_level >= 30) || (groupAccess && groupAccess.access_level >= 30)) ) { - errors.push(getError("EGLNOPUSHPERMISSION", { repoId })); + errors.push(getError("EGLNOPUSHPERMISSION", { projectPath })); } } catch (error) { if (error.response && error.response.statusCode === 401) { - errors.push(getError("EINVALIDGLTOKEN", { repoId })); + errors.push(getError("EINVALIDGLTOKEN", { projectPath })); } else if (error.response && error.response.statusCode === 404) { - errors.push(getError("EMISSINGREPO", { repoId })); + errors.push(getError("EMISSINGREPO", { projectPath })); } else { throw error; } diff --git a/test/fail.test.js b/test/fail.test.js index 9c6f52df..59de52cb 100644 --- a/test/fail.test.js +++ b/test/fail.test.js @@ -26,10 +26,10 @@ test.serial("Post new issue if none exists yet", async (t) => { const branch = { name: "main" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; const errors = [{ message: "An error occured" }]; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedFailTitle = encodeURIComponent("The automated release is failing 🚨"); const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/issues?state=opened&&search=${encodedFailTitle}`) + .get(`/projects/${encodedProjectPath}/issues?state=opened&&search=${encodedFailTitle}`) .reply(200, [ { id: 2, @@ -39,7 +39,7 @@ test.serial("Post new issue if none exists yet", async (t) => { title: "API should implemented authentication", }, ]) - .post(`/projects/${encodedRepoId}/issues`, { + .post(`/projects/${encodedProjectPath}/issues`, { id: "test_user%2Ftest_repo", description: `## :rotating_light: The automated release from the \`main\` branch failed. :rotating_light: @@ -92,10 +92,10 @@ test.serial("Post comments to existing issue", async (t) => { const branch = { name: "main" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; const errors = [{ message: "An error occured" }]; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedFailTitle = encodeURIComponent("The automated release is failing 🚨"); const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/issues?state=opened&search=${encodedFailTitle}`) + .get(`/projects/${encodedProjectPath}/issues?state=opened&search=${encodedFailTitle}`) .reply(200, [ { id: 1, @@ -160,10 +160,10 @@ test.serial("Post comments to existing issue with custom template", async (t) => const branch = { name: "main" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; const errors = [{ message: "An error occured" }]; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedFailTitle = encodeURIComponent("Semantic Release Failure"); const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/issues?state=opened&search=${encodedFailTitle}`) + .get(`/projects/${encodedProjectPath}/issues?state=opened&search=${encodedFailTitle}`) .reply(200, [ { id: 1, @@ -252,10 +252,10 @@ test.serial("Does not post comments when failCommentCondition disables it", asyn const branch = { name: "main" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; const errors = [{ message: "An error occured" }]; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedFailTitle = encodeURIComponent("The automated release is failing 🚨"); const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/issues?state=opened&&search=${encodedFailTitle}`) + .get(`/projects/${encodedProjectPath}/issues?state=opened&&search=${encodedFailTitle}`) .reply(200, [ { id: 2, @@ -279,10 +279,10 @@ test.serial("Does not post comments on existing issues when failCommentCondition const branch = { name: "main" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; const errors = [{ message: "An error occured" }]; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedFailTitle = encodeURIComponent("The automated release is failing 🚨"); const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/issues?state=opened&&search=${encodedFailTitle}`) + .get(`/projects/${encodedProjectPath}/issues?state=opened&&search=${encodedFailTitle}`) .reply(200, [ { id: 1, @@ -316,10 +316,10 @@ test.serial("Post new issue if none exists yet with disabled comment on existing const branch = { name: "main" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; const errors = [{ message: "An error occured" }]; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedFailTitle = encodeURIComponent("The automated release is failing 🚨"); const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/issues?state=opened&&search=${encodedFailTitle}`) + .get(`/projects/${encodedProjectPath}/issues?state=opened&&search=${encodedFailTitle}`) .reply(200, [ { id: 2, @@ -329,7 +329,7 @@ test.serial("Post new issue if none exists yet with disabled comment on existing title: "API should implemented authentication", }, ]) - .post(`/projects/${encodedRepoId}/issues`, { + .post(`/projects/${encodedProjectPath}/issues`, { id: "test_user%2Ftest_repo", description: `Error: Release for branch main failed with error: An error occured`, labels: "semantic-release", diff --git a/test/get-project-context.test.js b/test/get-project-context.test.js new file mode 100644 index 00000000..2ef3dfb4 --- /dev/null +++ b/test/get-project-context.test.js @@ -0,0 +1,147 @@ +import test from "ava"; +import getProjectContext from "../lib/get-project-context.js"; + +test("Parse project path with https URL", (t) => { + t.is( + getProjectContext({ env: {} }, "https://gitlab.com", "https://api.gitlab.com", "https://gitlab.com/owner/repo.git") + .projectPath, + "owner/repo" + ); + t.is( + getProjectContext({ env: {} }, "https://gitlab.com", "https://api.gitlab.com", "https://gitlab.com/owner/repo") + .projectPath, + "owner/repo" + ); +}); + +test("Parse project path with git URL", (t) => { + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com", + "https://api.gitlab.com", + "git+ssh://git@gitlab.com/owner/repo.git" + ).projectPath, + "owner/repo" + ); + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com", + "https://api.gitlab.com", + "git+ssh://git@gitlab.com/owner/repo" + ).projectPath, + "owner/repo" + ); +}); + +test("Parse project path with context in repo URL", (t) => { + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com/context", + "https://api.gitlab.com", + "https://gitlab.com/context/owner/repo.git" + ).projectPath, + "owner/repo" + ); + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com/context", + "https://api.gitlab.com", + "git+ssh://git@gitlab.com/context/owner/repo.git" + ).projectPath, + "owner/repo" + ); +}); + +test("Parse project path with context not in repo URL", (t) => { + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com/context", + "https://api.gitlab.com", + "https://gitlab.com/owner/repo.git" + ).projectPath, + "owner/repo" + ); + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com/context", + "https://api.gitlab.com", + "git+ssh://git@gitlab.com/owner/repo.git" + ).projectPath, + "owner/repo" + ); +}); + +test("Parse project path with organization and subgroup", (t) => { + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com/context", + "https://api.gitlab.com", + "https://gitlab.com/orga/subgroup/owner/repo.git" + ).projectPath, + "orga/subgroup/owner/repo" + ); + t.is( + getProjectContext( + { env: {} }, + "https://gitlab.com/context", + "https://api.gitlab.com", + "git+ssh://git@gitlab.com/orga/subgroup/owner/repo.git" + ).projectPath, + "orga/subgroup/owner/repo" + ); +}); + +test("Get project path from GitLab CI", (t) => { + t.is( + getProjectContext( + { envCi: { service: "gitlab" }, env: { CI_PROJECT_PATH: "other-owner/other-repo" } }, + "https://gitlab.com", + "https://api.gitlab.com", + "https://gitlab.com/owner/repo.git" + ).projectPath, + "other-owner/other-repo" + ); +}); + +test("Ignore CI_PROJECT_PATH if not on GitLab CI", (t) => { + t.is( + getProjectContext( + { envCi: { service: "travis" }, env: { CI_PROJECT_PATH: "other-owner/other-repo" } }, + "https://gitlab.com", + "https://api.gitlab.com", + "https://gitlab.com/owner/repo.git" + ).projectPath, + "owner/repo" + ); +}); + +test("Uses project API URL with project path", (t) => { + t.is( + getProjectContext( + { envCi: { service: "gitlab" }, env: { CI_PROJECT_PATH: "other-owner/other-repo" } }, + "https://gitlab.com", + "https://api.gitlab.com", + "https://gitlab.com/owner/repo.git" + ).projectApiUrl, + "https://api.gitlab.com/projects/other-owner%2Fother-repo" + ); +}); + +test("Uses project API URL with project ID", (t) => { + t.is( + getProjectContext( + { envCi: { service: "gitlab" }, env: { CI_PROJECT_ID: "42" } }, + "https://gitlab.com", + "https://api.gitlab.com", + "https://gitlab.com/owner/repo.git" + ).projectApiUrl, + "https://api.gitlab.com/projects/42" + ); +}); diff --git a/test/get-repo-id.test.js b/test/get-repo-id.test.js deleted file mode 100644 index f7f09fc1..00000000 --- a/test/get-repo-id.test.js +++ /dev/null @@ -1,61 +0,0 @@ -import test from "ava"; -import getRepoId from "../lib/get-repo-id.js"; - -test("Parse repo id with https URL", (t) => { - t.is(getRepoId({ env: {} }, "https://gitlbab.com", "https://gitlab.com/owner/repo.git"), "owner/repo"); - t.is(getRepoId({ env: {} }, "https://gitlbab.com", "https://gitlab.com/owner/repo"), "owner/repo"); -}); - -test("Parse repo id with git URL", (t) => { - t.is(getRepoId({ env: {} }, "https://gitlab.com", "git+ssh://git@gitlab.com/owner/repo.git"), "owner/repo"); - t.is(getRepoId({ env: {} }, "https://gitlab.com", "git+ssh://git@gitlab.com/owner/repo"), "owner/repo"); -}); - -test("Parse repo id with context in repo URL", (t) => { - t.is( - getRepoId({ env: {} }, "https://gitlbab.com/context", "https://gitlab.com/context/owner/repo.git"), - "owner/repo" - ); - t.is( - getRepoId({ env: {} }, "https://gitlab.com/context", "git+ssh://git@gitlab.com/context/owner/repo.git"), - "owner/repo" - ); -}); - -test("Parse repo id with context not in repo URL", (t) => { - t.is(getRepoId({ env: {} }, "https://gitlbab.com/context", "https://gitlab.com/owner/repo.git"), "owner/repo"); - t.is(getRepoId({ env: {} }, "https://gitlab.com/context", "git+ssh://git@gitlab.com/owner/repo.git"), "owner/repo"); -}); - -test("Parse repo id with organization and subgroup", (t) => { - t.is( - getRepoId({ env: {} }, "https://gitlbab.com/context", "https://gitlab.com/orga/subgroup/owner/repo.git"), - "orga/subgroup/owner/repo" - ); - t.is( - getRepoId({ env: {} }, "https://gitlab.com/context", "git+ssh://git@gitlab.com/orga/subgroup/owner/repo.git"), - "orga/subgroup/owner/repo" - ); -}); - -test("Get repo id from GitLab CI", (t) => { - t.is( - getRepoId( - { envCi: { service: "gitlab" }, env: { CI_PROJECT_PATH: "other-owner/other-repo" } }, - "https://gitlbab.com", - "https://gitlab.com/owner/repo.git" - ), - "other-owner/other-repo" - ); -}); - -test("Ignore CI_PROJECT_PATH if not on GitLab CI", (t) => { - t.is( - getRepoId( - { envCi: { service: "travis" }, env: { CI_PROJECT_PATH: "other-owner/other-repo" } }, - "https://gitlbab.com", - "https://gitlab.com/owner/repo.git" - ), - "owner/repo" - ); -}); diff --git a/test/integration.test.js b/test/integration.test.js index 5e18cd43..dbfd9f2c 100644 --- a/test/integration.test.js +++ b/test/integration.test.js @@ -62,12 +62,12 @@ test.serial("Publish a release", async (t) => { const env = { GL_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { branch: "master", repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}`) + .get(`/projects/${encodedProjectPath}`) .reply(200, { permissions: { project_access: { access_level: 30 } } }) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -89,13 +89,13 @@ test.serial("Verify Github auth and release", async (t) => { const owner = "test_user"; const repo = "test_repo"; const options = { repositoryUrl: `https://github.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}`) + .get(`/projects/${encodedProjectPath}`) .reply(200, { permissions: { project_access: { access_level: 30 } } }) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { diff --git a/test/publish.test.js b/test/publish.test.js index 8771b051..249e8bcf 100644 --- a/test/publish.test.js +++ b/test/publish.test.js @@ -26,10 +26,10 @@ test.serial("Publish a release", async (t) => { const pluginConfig = {}; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -52,7 +52,7 @@ test.serial("Publish a release with templated path", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token", FIXTURE: "upload" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const generic = { path: "${env.FIXTURE}.txt", filepath: "/upload.txt" }; const assets = [generic]; @@ -62,7 +62,7 @@ test.serial("Publish a release with templated path", async (t) => { full_path: "/-/project/4/66dbcd21ec5d24ed6ea225176098d52b/upload.txt", }; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -77,7 +77,7 @@ test.serial("Publish a release with templated path", async (t) => { }) .reply(200); const gitlabUpload = authenticate(env) - .post(`/projects/${encodedRepoId}/uploads`, /Content-Disposition/g) + .post(`/projects/${encodedProjectPath}/uploads`, /Content-Disposition/g) .reply(200, uploaded); const result = await publish({ assets }, { env, cwd, options, nextRelease, logger: t.context.logger }); @@ -95,7 +95,7 @@ test.serial("Publish a release with assets", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const uploaded = { url: "/uploads/file.css", @@ -104,7 +104,7 @@ test.serial("Publish a release with assets", async (t) => { }; const assets = [["**", "!**/*.txt", "!.dotfile"]]; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -118,7 +118,7 @@ test.serial("Publish a release with assets", async (t) => { }) .reply(200); const gitlabUpload = authenticate(env) - .post(`/projects/${encodedRepoId}/uploads`, /filename="file.css"/gm) + .post(`/projects/${encodedProjectPath}/uploads`, /filename="file.css"/gm) .reply(200, uploaded); const result = await publish({ assets }, { env, cwd, options, nextRelease, logger: t.context.logger }); @@ -137,16 +137,16 @@ test.serial("Publish a release with generics", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body", version: "1.0.0" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const encodedVersion = encodeURIComponent(nextRelease.version); const uploaded = { file: { url: "/uploads/file.css" } }; const generic = { path: "file.css", label: "Style package", target: "generic_package", status: "hidden" }; const assets = [generic]; const encodedLabel = encodeURIComponent(generic.label); - const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}`; + const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}`; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -162,7 +162,7 @@ test.serial("Publish a release with generics", async (t) => { .reply(200); const gitlabUpload = authenticate(env) .put( - `/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, + `/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, /\.test\s\{\}/gm ) .reply(200, uploaded); @@ -183,16 +183,16 @@ test.serial("Publish a release with generics and external storage provider (http const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body", version: "1.0.0" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const encodedVersion = encodeURIComponent(nextRelease.version); const uploaded = { file: { url: "http://aws.example.com/bucket/gitlab/file.css" } }; const generic = { path: "file.css", label: "Style package", target: "generic_package", status: "hidden" }; const assets = [generic]; const encodedLabel = encodeURIComponent(generic.label); - const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}`; + const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}`; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -208,7 +208,7 @@ test.serial("Publish a release with generics and external storage provider (http .reply(200); const gitlabUpload = authenticate(env) .put( - `/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, + `/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, /\.test\s\{\}/gm ) .reply(200, uploaded); @@ -229,16 +229,16 @@ test.serial("Publish a release with generics and external storage provider (http const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body", version: "1.0.0" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const encodedVersion = encodeURIComponent(nextRelease.version); const uploaded = { file: { url: "https://aws.example.com/bucket/gitlab/file.css" } }; const generic = { path: "file.css", label: "Style package", target: "generic_package", status: "hidden" }; const assets = [generic]; const encodedLabel = encodeURIComponent(generic.label); - const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}`; + const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}`; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -254,7 +254,7 @@ test.serial("Publish a release with generics and external storage provider (http .reply(200); const gitlabUpload = authenticate(env) .put( - `/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, + `/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, /\.test\s\{\}/gm ) .reply(200, uploaded); @@ -275,16 +275,16 @@ test.serial("Publish a release with generics and external storage provider (ftp) const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body", version: "1.0.0" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const encodedVersion = encodeURIComponent(nextRelease.version); const uploaded = { file: { url: "ftp://drive.example.com/gitlab/file.css" } }; const generic = { path: "file.css", label: "Style package", target: "generic_package", status: "hidden" }; const assets = [generic]; const encodedLabel = encodeURIComponent(generic.label); - const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}`; + const expectedUrl = `https://gitlab.com/api/v4/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}`; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -300,7 +300,7 @@ test.serial("Publish a release with generics and external storage provider (ftp) .reply(200); const gitlabUpload = authenticate(env) .put( - `/projects/${encodedRepoId}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, + `/projects/${encodedProjectPath}/packages/generic/release/${encodedVersion}/${encodedLabel}?status=${generic.status}&select=package_file`, /\.test\s\{\}/gm ) .reply(200, uploaded); @@ -321,7 +321,7 @@ test.serial("Publish a release with asset type and permalink", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const uploaded = { url: "/uploads/file.css", @@ -338,7 +338,7 @@ test.serial("Publish a release with asset type and permalink", async (t) => { }, ]; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -354,7 +354,7 @@ test.serial("Publish a release with asset type and permalink", async (t) => { }) .reply(200); const gitlabUpload = authenticate(env) - .post(`/projects/${encodedRepoId}/uploads`, /filename="file.css"/gm) + .post(`/projects/${encodedProjectPath}/uploads`, /filename="file.css"/gm) .reply(200, uploaded); const result = await publish({ assets }, { env, cwd, options, nextRelease, logger: t.context.logger }); @@ -373,7 +373,7 @@ test.serial("Publish a release with an asset with a template label", async (t) = const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body", version: "1.0.0" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const uploaded = { url: "/uploads/file.css", @@ -389,7 +389,7 @@ test.serial("Publish a release with an asset with a template label", async (t) = }, ]; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -405,7 +405,7 @@ test.serial("Publish a release with an asset with a template label", async (t) = }) .reply(200); const gitlabUpload = authenticate(env) - .post(`/projects/${encodedRepoId}/uploads`, /filename="file.css"/gm) + .post(`/projects/${encodedProjectPath}/uploads`, /filename="file.css"/gm) .reply(200, uploaded); const result = await publish({ assets }, { env, cwd, options, nextRelease, logger: t.context.logger }); @@ -426,7 +426,7 @@ test.serial("Publish a release (with an link) with variables", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body", version: "1.0.0" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const uploaded = { url: "/uploads/file.css", @@ -447,7 +447,7 @@ test.serial("Publish a release (with an link) with variables", async (t) => { }, ]; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -469,7 +469,7 @@ test.serial("Publish a release (with an link) with variables", async (t) => { .reply(200); const gitlabUpload = authenticate(env) - .post(`/projects/${encodedRepoId}/uploads`, /filename="file.css"/gm) + .post(`/projects/${encodedProjectPath}/uploads`, /filename="file.css"/gm) .reply(200, uploaded); const result = await publish({ assets }, { env, cwd, options, nextRelease, logger: t.context.logger }); @@ -490,10 +490,10 @@ test.serial("Publish a release with a milestone", async (t) => { const pluginConfig = { milestones: ["1.2.3"] }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -517,12 +517,12 @@ test.serial("Publish a release with array of missing assets", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const emptyDirectory = tempy.directory(); const assets = [emptyDirectory, { path: "missing.txt", label: "missing.txt" }]; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -544,7 +544,7 @@ test.serial("Publish a release with one asset and custom label", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const uploaded = { url: "/uploads/upload.txt", @@ -553,7 +553,7 @@ test.serial("Publish a release with one asset and custom label", async (t) => { const assetLabel = "Custom Label"; const assets = [{ path: "upload.txt", label: assetLabel }]; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -567,7 +567,7 @@ test.serial("Publish a release with one asset and custom label", async (t) => { }) .reply(200); const gitlabUpload = authenticate(env) - .post(`/projects/${encodedRepoId}/uploads`, /filename="upload.txt"/gm) + .post(`/projects/${encodedProjectPath}/uploads`, /filename="upload.txt"/gm) .reply(200, uploaded); const result = await publish({ assets }, { env, cwd, options, nextRelease, logger: t.context.logger }); @@ -586,10 +586,10 @@ test.serial("Publish a release with missing release notes", async (t) => { const pluginConfig = {}; const nextRelease = { gitHead: "123", gitTag: "v1.0.0" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.gitTag, assets: { @@ -612,7 +612,7 @@ test.serial("Publish a release with an asset link", async (t) => { const env = { GITLAB_TOKEN: "gitlab_token" }; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const link = { label: "README.md", @@ -621,7 +621,7 @@ test.serial("Publish a release with an asset link", async (t) => { }; const assets = [link]; const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { @@ -650,10 +650,10 @@ test.serial("Publish a release with error response", async (t) => { const pluginConfig = {}; const nextRelease = { gitHead: "123", gitTag: "v1.0.0", notes: "Test release note body" }; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const encodedGitTag = encodeURIComponent(nextRelease.gitTag); const gitlab = authenticate(env) - .post(`/projects/${encodedRepoId}/releases`, { + .post(`/projects/${encodedProjectPath}/releases`, { tag_name: nextRelease.gitTag, description: nextRelease.notes, assets: { diff --git a/test/success.test.js b/test/success.test.js index 2a3f2d4e..5394b87a 100644 --- a/test/success.test.js +++ b/test/success.test.js @@ -27,16 +27,16 @@ test.serial("Post comments to related issues and MRs", async (t) => { const nextRelease = { version: "1.0.0" }; const releases = [{ name: RELEASE_NAME, url: "https://gitlab.com/test_user/test_repo/-/releases/v1.0.0" }]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }, { hash: "fedcba" }]; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [ { project_id: 100, iid: 1, state: "merged" }, { project_id: 200, iid: 2, state: "closed" }, { project_id: 300, iid: 3, state: "merged" }, ]) - .get(`/projects/${encodedRepoId}/repository/commits/fedcba/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/fedcba/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, [ @@ -74,10 +74,10 @@ test.serial("Post comments with custom template", async (t) => { const nextRelease = { version: "1.0.0" }; const releases = [{ name: RELEASE_NAME, url: "https://gitlab.com/test_user/test_repo/-/releases/v1.0.0" }]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }]; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, [{ project_id: 100, iid: 11, state: "closed" }]) @@ -106,10 +106,10 @@ test.serial("Post comments for multiple releases", async (t) => { { name: "Other release" }, ]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }]; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, []) @@ -147,16 +147,16 @@ test.serial("Does not post comments when successCommentCondition disables it", a const nextRelease = { version: "1.0.0" }; const releases = [{ name: RELEASE_NAME, url: "https://gitlab.com/test_user/test_repo/-/releases/v1.0.0" }]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }, { hash: "fedcba" }]; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [ { project_id: 100, iid: 1, state: "merged" }, { project_id: 200, iid: 2, state: "closed" }, { project_id: 300, iid: 3, state: "merged" }, ]) - .get(`/projects/${encodedRepoId}/repository/commits/fedcba/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/fedcba/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, [ @@ -180,16 +180,16 @@ test.serial("Does not post comments on issues when successCommentCondition disab const nextRelease = { version: "1.0.0" }; const releases = [{ name: RELEASE_NAME, url: "https://gitlab.com/test_user/test_repo/-/releases/v1.0.0" }]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }, { hash: "fedcba" }]; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [ { project_id: 100, iid: 1, state: "merged" }, { project_id: 200, iid: 2, state: "closed" }, { project_id: 300, iid: 3, state: "merged" }, ]) - .get(`/projects/${encodedRepoId}/repository/commits/fedcba/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/fedcba/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, [ @@ -219,16 +219,16 @@ test.serial("Only posts comments on issues which are found using the successComm const nextRelease = { version: "1.0.0" }; const releases = [{ name: RELEASE_NAME, url: "https://gitlab.com/test_user/test_repo/-/releases/v1.0.0" }]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }, { hash: "fedcba" }]; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [ { project_id: 100, iid: 1, state: "merged" }, { project_id: 200, iid: 2, state: "closed" }, { project_id: 300, iid: 3, state: "merged" }, ]) - .get(`/projects/${encodedRepoId}/repository/commits/fedcba/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/fedcba/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, [ @@ -258,16 +258,16 @@ test.serial( const nextRelease = { version: "1.0.0" }; const releases = [{ name: RELEASE_NAME, url: "https://gitlab.com/test_user/test_repo/-/releases/v1.0.0" }]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }, { hash: "fedcba" }]; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [ { project_id: 100, iid: 1, state: "merged" }, { project_id: 200, iid: 2, state: "closed" }, { project_id: 300, iid: 3, state: "merged" }, ]) - .get(`/projects/${encodedRepoId}/repository/commits/fedcba/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/fedcba/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, [ @@ -314,14 +314,14 @@ test.serial("Retries requests when rate limited", async (t) => { const nextRelease = { version: "1.0.0" }; const releases = [{ name: RELEASE_NAME, url: "https://gitlab.com/test_user/test_repo/-/releases/v1.0.0" }]; const options = { repositoryUrl: `https://gitlab.com/${owner}/${repo}.git` }; - const encodedRepoId = encodeURIComponent(`${owner}/${repo}`); + const encodedProjectPath = encodeURIComponent(`${owner}/${repo}`); const commits = [{ hash: "abcdef" }]; const retryLimit = 3; const gitlab = authenticate(env) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .times(retryLimit) .reply(429) - .get(`/projects/${encodedRepoId}/repository/commits/abcdef/merge_requests`) + .get(`/projects/${encodedProjectPath}/repository/commits/abcdef/merge_requests`) .reply(200, [{ project_id: 100, iid: 1, state: "merged" }]) .get(`/projects/100/merge_requests/1/closes_issues`) .reply(200, [])