diff --git a/docs/usage/configuration.md b/docs/usage/configuration.md index 72d826a7..22799c17 100644 --- a/docs/usage/configuration.md +++ b/docs/usage/configuration.md @@ -63,8 +63,6 @@ The git repository URL. Any valid git url format is supported (See [Git protocols](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols)). -**Note**: If the [Github plugin](https://github.com/semantic-release/github) is used the URL must be a valid Github URL that include the `owner`, the `repository` name and the `host`. **The Github shorthand URL is not supported.** - ### tagFormat Type: `String` diff --git a/lib/get-config.js b/lib/get-config.js index abc4bb2a..312e09fd 100644 --- a/lib/get-config.js +++ b/lib/get-config.js @@ -2,9 +2,8 @@ const {castArray, pickBy, isUndefined, isNull, isString, isPlainObject} = requir const readPkgUp = require('read-pkg-up'); const cosmiconfig = require('cosmiconfig'); const resolveFrom = require('resolve-from'); -const gitUrlParse = require('git-url-parse'); const debug = require('debug')('semantic-release:config'); -const {repoUrl, verifyAuth} = require('./git'); +const {repoUrl} = require('./git'); const PLUGINS_DEFINITIONS = require('./definitions/plugins'); const plugins = require('./plugins'); const getGitAuthUrl = require('./get-git-auth-url'); @@ -52,9 +51,7 @@ module.exports = async (opts, logger) => { ...pickBy(options, option => !isUndefined(option) && !isNull(option)), }; - if (!await verifyAuth(options.repositoryUrl, options.branch)) { - options.repositoryUrl = options.repositoryUrl ? getGitAuthUrl(options.repositoryUrl) : options.repositoryUrl; - } + options.repositoryUrl = await getGitAuthUrl(options); debug('options values: %O', options); @@ -63,12 +60,5 @@ module.exports = async (opts, logger) => { async function pkgRepoUrl() { const {pkg} = await readPkgUp({normalize: false}); - const repositoryUrl = pkg && (isPlainObject(pkg.repository) ? pkg.repository.url : pkg.repository); - - if (repositoryUrl) { - const {protocols} = gitUrlParse(repositoryUrl); - return `${gitUrlParse(repositoryUrl).toString( - protocols.includes('https') ? 'https' : protocols.includes('http') ? 'http' : undefined - )}${protocols.includes('https') || protocols.includes('http') ? '.git' : ''}`; - } + return pkg && (isPlainObject(pkg.repository) ? pkg.repository.url : pkg.repository); } diff --git a/lib/get-git-auth-url.js b/lib/get-git-auth-url.js index e1b3d037..71fb9556 100644 --- a/lib/get-git-auth-url.js +++ b/lib/get-git-auth-url.js @@ -1,30 +1,54 @@ const {parse, format} = require('url'); const {isUndefined} = require('lodash'); const gitUrlParse = require('git-url-parse'); +const hostedGitInfo = require('hosted-git-info'); +const {verifyAuth} = require('./git'); const GIT_TOKENS = ['GIT_CREDENTIALS', 'GH_TOKEN', 'GITHUB_TOKEN', 'GL_TOKEN', 'GITLAB_TOKEN']; /** - * Generate the git repository URL with creadentials. - * If the `gitCredentials` is defined, returns a http or https URL with Basic Authentication (`https://username:passowrd@hostname:port/path.git`). - * If the `gitCredentials` is undefined, returns the `repositoryUrl`. In that case it's expected for the user to have setup the Git authentication on the CI (for example via SSH keys). + * Determine the the git repository URL to use to push, either: + * - The `repositoryUrl` as is if allowed to push + * - The `repositoryUrl` converted to `https` or `http` with Basic Authentication * - * @param {String} gitCredentials Basic HTTP Authentication credentials, can be `username:password` or a token for certain Git providers. - * @param {String} repositoryUrl The git repository URL. + * In addition, expand shortcut URLs (`owner/repo` => `https://github.com/owner/repo.git`) and transform `git+https` / `git+http` URLs to `https` / `http`. + * + * @param {String} repositoryUrl The user provided Git repository URL. * @return {String} The formatted Git repository URL. */ -module.exports = repositoryUrl => { - const envVar = GIT_TOKENS.find(envVar => !isUndefined(process.env[envVar])); - const gitCredentials = ['GL_TOKEN', 'GITLAB_TOKEN'].includes(envVar) - ? `gitlab-ci-token:${process.env[envVar]}` - : process.env[envVar]; +module.exports = async ({repositoryUrl, branch}) => { + if (repositoryUrl) { + const info = hostedGitInfo.fromUrl(repositoryUrl, {noGitPlus: true}); - const {protocols} = gitUrlParse(repositoryUrl); - const protocol = protocols.includes('https') ? 'https' : protocols.includes('http') ? 'http' : 'https'; + if (info && info.getDefaultRepresentation() === 'shortcut') { + // Expand shorthand URLs (such as `owner/repo` or `gitlab:owner/repo`) + repositoryUrl = info.https(); + } else { + const {protocols} = gitUrlParse(repositoryUrl); - if (!gitCredentials) { - return protocols.includes('https') ? `${gitUrlParse(repositoryUrl).toString(protocol)}.git` : repositoryUrl; + // Replace `git+https` and `git+http` with `https` or `http` + if (protocols.includes('http') || protocols.includes('https')) { + repositoryUrl = format({ + ...parse(repositoryUrl), + ...{protocol: protocols.includes('https') ? 'https' : 'http'}, + }); + } + } + + // Test if push is allowed without transforming the URL (e.g. is ssh keys are set up) + if (!await verifyAuth(repositoryUrl, branch)) { + const envVar = GIT_TOKENS.find(envVar => !isUndefined(process.env[envVar])); + const gitCredentials = ['GL_TOKEN', 'GITLAB_TOKEN'].includes(envVar) + ? `gitlab-ci-token:${process.env[envVar]}` + : process.env[envVar]; + const {protocols} = gitUrlParse(repositoryUrl); + const protocol = protocols.includes('https') ? 'https' : protocols.includes('http') ? 'http' : 'https'; + + // If credentials are set via anvironment variables, convert the URL to http/https and add basic auth, otherwise return `repositoryUrl` as is + return gitCredentials + ? format({...parse(`${gitUrlParse(repositoryUrl).toString(protocol)}.git`), ...{auth: gitCredentials}}) + : repositoryUrl; + } } - - return format({...parse(`${gitUrlParse(repositoryUrl).toString(protocol)}.git`), ...{auth: gitCredentials}}); + return repositoryUrl; }; diff --git a/package.json b/package.json index 318a6362..46bb79bc 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "git-log-parser": "^1.2.0", "git-url-parse": "^8.1.0", "hook-std": "^0.4.0", + "hosted-git-info": "^2.6.0", "lodash": "^4.17.4", "marked": "^0.3.9", "marked-terminal": "^2.0.0", diff --git a/test/get-config.test.js b/test/get-config.test.js index 57702f6c..145adecc 100644 --- a/test/get-config.test.js +++ b/test/get-config.test.js @@ -32,12 +32,12 @@ test.afterEach.always(() => { test.serial('Default values, reading repositoryUrl from package.json', async t => { process.env.GIT_CREDENTIALS = 'user:pass'; - const pkg = {repository: 'https://package.com/owner/module.git'}; + const pkg = {repository: 'https://host.null/owner/package.git'}; // Create a git repository, set the current working directory at the root of the repo await gitRepo(); await gitCommits(['First']); // Add remote.origin.url config - await gitAddConfig('remote.origin.url', 'git@repo.com:owner/module.git'); + await gitAddConfig('remote.origin.url', 'git@host.null:owner/repo.git'); // Create package.json in repository root await outputJson('./package.json', pkg); @@ -45,7 +45,7 @@ test.serial('Default values, reading repositoryUrl from package.json', async t = // Verify the default options are set t.is(options.branch, 'master'); - t.is(options.repositoryUrl, 'https://user:pass@package.com/owner/module.git'); + t.is(options.repositoryUrl, 'https://user:pass@host.null/owner/package.git'); t.is(options.tagFormat, `v\${version}`); }); @@ -54,19 +54,19 @@ test.serial('Default values, reading repositoryUrl from repo if not set in packa // Create a git repository, set the current working directory at the root of the repo await gitRepo(); // Add remote.origin.url config - await gitAddConfig('remote.origin.url', 'https://hostname.com/owner/module.git'); + await gitAddConfig('remote.origin.url', 'https://host.null/owner/module.git'); const {options} = await t.context.getConfig(); // Verify the default options are set t.is(options.branch, 'master'); - t.is(options.repositoryUrl, 'https://user:pass@hostname.com/owner/module.git'); + t.is(options.repositoryUrl, 'https://user:pass@host.null/owner/module.git'); t.is(options.tagFormat, `v\${version}`); }); test.serial('Default values, reading repositoryUrl (http url) from package.json if not set in repo', async t => { process.env.GIT_CREDENTIALS = 'user:pass'; - const pkg = {repository: 'https://hostname.com/owner/module.git'}; + const pkg = {repository: 'https://host.null/owner/module.git'}; // Create a git repository, set the current working directory at the root of the repo await gitRepo(); // Create package.json in repository root @@ -76,10 +76,45 @@ test.serial('Default values, reading repositoryUrl (http url) from package.json // Verify the default options are set t.is(options.branch, 'master'); - t.is(options.repositoryUrl, 'https://user:pass@hostname.com/owner/module.git'); + t.is(options.repositoryUrl, 'https://user:pass@host.null/owner/module.git'); t.is(options.tagFormat, `v\${version}`); }); +test.serial('Default values, reading repositoryUrl (shorthand url) from package.json if not set in repo', async t => { + process.env.GIT_CREDENTIALS = 'user:pass'; + const pkg = {repository: 'owner/module'}; + // Create a git repository, set the current working directory at the root of the repo + await gitRepo(); + // Create package.json in repository root + await outputJson('./package.json', pkg); + + const {options} = await t.context.getConfig(); + + // Verify the default options are set + t.is(options.branch, 'master'); + t.is(options.repositoryUrl, 'https://user:pass@github.com/owner/module.git'); + t.is(options.tagFormat, `v\${version}`); +}); + +test.serial( + 'Default values, reading repositoryUrl (gitlab shorthand url) from package.json if not set in repo', + async t => { + process.env.GIT_CREDENTIALS = 'user:pass'; + const pkg = {repository: 'gitlab:owner/module'}; + // Create a git repository, set the current working directory at the root of the repo + await gitRepo(); + // Create package.json in repository root + await outputJson('./package.json', pkg); + + const {options} = await t.context.getConfig(); + + // Verify the default options are set + t.is(options.branch, 'master'); + t.is(options.repositoryUrl, 'https://user:pass@gitlab.com/owner/module.git'); + t.is(options.tagFormat, `v\${version}`); + } +); + test.serial('Do not add git credential to repositoryUrl if push is allowed', async t => { process.env.GIT_CREDENTIALS = 'user:pass'; // Create a git repository, set the current working directory at the root of the repo @@ -98,7 +133,7 @@ test.serial('Read options from package.json', async t => { analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'}, generateNotes: 'generateNotes', branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -119,7 +154,7 @@ test.serial('Read options from .releaserc.yml', async t => { const release = { analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'}, branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -140,7 +175,7 @@ test.serial('Read options from .releaserc.json', async t => { const release = { analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'}, branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -161,7 +196,7 @@ test.serial('Read options from .releaserc.js', async t => { const release = { analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'}, branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -182,7 +217,7 @@ test.serial('Read options from release.config.js', async t => { const release = { analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'}, branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -210,7 +245,7 @@ test.serial('Prioritise CLI/API parameters over file configuration and git repo' repositoryUrl: 'http://cli-url.com/owner/package', tagFormat: `cli\${version}`, }; - const pkg = {release, repository: 'git@hostname.com:owner/module.git'}; + const pkg = {release, repository: 'git@host.null:owner/module.git'}; // Create a git repository, set the current working directory at the root of the repo const repo = await gitRepo(); await gitCommits(['First']); @@ -233,7 +268,7 @@ test.serial('Read configuration from file path in "extends"', async t => { analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'}, generateNotes: 'generateNotes', branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -261,7 +296,7 @@ test.serial('Read configuration from module path in "extends"', async t => { analyzeCommits: {path: 'analyzeCommits', param: 'analyzeCommits_param'}, generateNotes: 'generateNotes', branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -289,7 +324,7 @@ test.serial('Read configuration from an array of paths in "extends"', async t => verifyRelease: 'verifyRelease1', analyzeCommits: {path: 'analyzeCommits1', param: 'analyzeCommits_param1'}, branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', }; const shareable2 = { @@ -334,7 +369,7 @@ test.serial('Prioritize configuration from config file over "extends"', async t generateNotes: 'generateNotesShareable', publish: [{path: 'publishShareable', param: 'publishShareable_param'}], branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', tagFormat: `v\${version}`, }; @@ -362,7 +397,7 @@ test.serial('Prioritize configuration from cli/API options over "extends"', asyn extends: './shareable2.json', branch: 'branch_opts', publish: [{path: 'publishOpts', param: 'publishOpts_param'}], - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', }; const release = { extends: './shareable1.json', @@ -375,7 +410,7 @@ test.serial('Prioritize configuration from cli/API options over "extends"', asyn generateNotes: 'generateNotesShareable1', publish: [{path: 'publishShareable', param: 'publishShareable_param1'}], branch: 'test_branch1', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', }; const shareable2 = { analyzeCommits: 'analyzeCommits2', @@ -404,7 +439,7 @@ test.serial('Allow to unset properties defined in shareable config with "null"', extends: './shareable.json', analyzeCommits: null, branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', }; const shareable = { generateNotes: 'generateNotes', @@ -438,7 +473,7 @@ test.serial('Allow to unset properties defined in shareable config with "undefin extends: './shareable.json', analyzeCommits: undefined, branch: 'test_branch', - repositoryUrl: 'https://hostname.com/owner/module.git', + repositoryUrl: 'https://host.null/owner/module.git', }; const shareable = { generateNotes: 'generateNotes', diff --git a/test/get-git-auth-url.test.js b/test/get-git-auth-url.test.js index 7f2775a7..d8009c7b 100644 --- a/test/get-git-auth-url.test.js +++ b/test/get-git-auth-url.test.js @@ -1,105 +1,157 @@ import test from 'ava'; import getAuthUrl from '../lib/get-git-auth-url'; +import {gitRepo} from './helpers/git-utils'; // Save the current process.env const envBackup = Object.assign({}, process.env); +// Save the current working diretory +const cwd = process.cwd(); test.beforeEach(() => { - // Restore process.env - process.env = {}; + delete process.env.GIT_CREDENTIALS; + delete process.env.GH_TOKEN; + delete process.env.GITHUB_TOKEN; + delete process.env.GL_TOKEN; + delete process.env.GITLAB_TOKEN; }); test.afterEach.always(() => { // Restore process.env process.env = envBackup; + // Restore the current working directory + process.chdir(cwd); }); -test.serial('Return the same "git" formatted URL if "gitCredentials" is not defined', t => { - t.is(getAuthUrl('git@host.com:owner/repo.git'), 'git@host.com:owner/repo.git'); +test.serial('Return the same "git" formatted URL if "gitCredentials" is not defined', async t => { + t.is(await getAuthUrl({repositoryUrl: 'git@host.null:owner/repo.git'}), 'git@host.null:owner/repo.git'); }); -test.serial('Return the same "https" formatted URL if "gitCredentials" is not defined', t => { - t.is(getAuthUrl('https://host.com/owner/repo.git'), 'https://host.com/owner/repo.git'); +test.serial('Return the same "https" formatted URL if "gitCredentials" is not defined', async t => { + t.is(await getAuthUrl({repositoryUrl: 'https://host.null/owner/repo.git'}), 'https://host.null/owner/repo.git'); }); test.serial( 'Return the "https" formatted URL if "gitCredentials" is not defined and repositoryUrl is a "git+https" URL', - t => { - t.is(getAuthUrl('git+https://host.com/owner/repo.git'), 'https://host.com/owner/repo.git'); + async t => { + t.is(await getAuthUrl({repositoryUrl: 'git+https://host.null/owner/repo.git'}), 'https://host.null/owner/repo.git'); } ); -test.serial('Handle "https" URL with group and subgroup', t => { - t.is(getAuthUrl('https://host.com/group/subgroup/owner/repo.git'), 'https://host.com/group/subgroup/owner/repo.git'); +test.serial('Handle "https" URL with group and subgroup', async t => { + t.is( + await getAuthUrl({repositoryUrl: 'https://host.null/group/subgroup/owner/repo.git'}), + 'https://host.null/group/subgroup/owner/repo.git' + ); }); -test.serial('Handle "git" URL with group and subgroup', t => { - t.is(getAuthUrl('git@host.com:group/subgroup/owner/repo.git'), 'git@host.com:group/subgroup/owner/repo.git'); -}); - -test.serial('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL', t => { - process.env.GIT_CREDENTIALS = 'user:pass'; - t.is(getAuthUrl('git@host.com:owner/repo.git'), 'https://user:pass@host.com/owner/repo.git'); -}); - -test.serial('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "https" URL', t => { - process.env.GIT_CREDENTIALS = 'user:pass'; - t.is(getAuthUrl('https://host.com/owner/repo.git'), 'https://user:pass@host.com/owner/repo.git'); -}); - -test.serial('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL', t => { - process.env.GIT_CREDENTIALS = 'user:pass'; - t.is(getAuthUrl('http://host.com/owner/repo.git'), 'http://user:pass@host.com/owner/repo.git'); +test.serial('Handle "git" URL with group and subgroup', async t => { + t.is( + await getAuthUrl({repositoryUrl: 'git@host.null:group/subgroup/owner/repo.git'}), + 'git@host.null:group/subgroup/owner/repo.git' + ); }); test.serial( - 'Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+https" URL', - t => { + 'Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL', + async t => { process.env.GIT_CREDENTIALS = 'user:pass'; - t.is(getAuthUrl('git+https://host.com/owner/repo.git'), 'https://user:pass@host.com/owner/repo.git'); + t.is( + await getAuthUrl({repositoryUrl: 'git@host.null:owner/repo.git'}), + 'https://user:pass@host.null/owner/repo.git' + ); + } +); + +test.serial( + 'Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "https" URL', + async t => { + process.env.GIT_CREDENTIALS = 'user:pass'; + t.is( + await getAuthUrl({repositoryUrl: 'https://host.null/owner/repo.git'}), + 'https://user:pass@host.null/owner/repo.git' + ); + } +); + +test.serial( + 'Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL', + async t => { + process.env.GIT_CREDENTIALS = 'user:pass'; + t.is( + await getAuthUrl({repositoryUrl: 'http://host.null/owner/repo.git'}), + 'http://user:pass@host.null/owner/repo.git' + ); + } +); + +test.serial( + 'Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+https" URL', + async t => { + process.env.GIT_CREDENTIALS = 'user:pass'; + t.is( + await getAuthUrl({repositoryUrl: 'git+https://host.null/owner/repo.git'}), + 'https://user:pass@host.null/owner/repo.git' + ); } ); test.serial( 'Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+http" URL', - t => { + async t => { process.env.GIT_CREDENTIALS = 'user:pass'; - t.is(getAuthUrl('git+http://host.com/owner/repo.git'), 'http://user:pass@host.com/owner/repo.git'); + t.is( + await getAuthUrl({repositoryUrl: 'git+http://host.null/owner/repo.git'}), + 'http://user:pass@host.null/owner/repo.git' + ); } ); -test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GH_TOKEN"', t => { +test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GH_TOKEN"', async t => { process.env.GH_TOKEN = 'token'; - t.is(getAuthUrl('git@host.com:owner/repo.git'), 'https://token@host.com/owner/repo.git'); + t.is(await getAuthUrl({repositoryUrl: 'git@host.null:owner/repo.git'}), 'https://token@host.null/owner/repo.git'); }); -test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GITHUB_TOKEN"', t => { +test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GITHUB_TOKEN"', async t => { process.env.GITHUB_TOKEN = 'token'; - t.is(getAuthUrl('git@host.com:owner/repo.git'), 'https://token@host.com/owner/repo.git'); + t.is(await getAuthUrl({repositoryUrl: 'git@host.null:owner/repo.git'}), 'https://token@host.null/owner/repo.git'); }); -test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GL_TOKEN"', t => { +test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GL_TOKEN"', async t => { process.env.GL_TOKEN = 'token'; - t.is(getAuthUrl('git@host.com:owner/repo.git'), 'https://gitlab-ci-token:token@host.com/owner/repo.git'); + t.is( + await getAuthUrl({repositoryUrl: 'git@host.null:owner/repo.git'}), + 'https://gitlab-ci-token:token@host.null/owner/repo.git' + ); }); -test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GITLAB_TOKEN"', t => { +test.serial('Return the "https" formatted URL if "gitCredentials" is defined with "GITLAB_TOKEN"', async t => { process.env.GITLAB_TOKEN = 'token'; - t.is(getAuthUrl('git@host.com:owner/repo.git'), 'https://gitlab-ci-token:token@host.com/owner/repo.git'); -}); - -test.serial('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', t => { - process.env.GIT_CREDENTIALS = 'user:pass'; t.is( - getAuthUrl('https://host.com/group/subgroup/owner/repo.git'), - 'https://user:pass@host.com/group/subgroup/owner/repo.git' + await getAuthUrl({repositoryUrl: 'git@host.null:owner/repo.git'}), + 'https://gitlab-ci-token:token@host.null/owner/repo.git' ); }); -test.serial('Handle "git" URL with group and subgroup, with "GIT_CREDENTIALS', t => { +test.serial('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async t => { process.env.GIT_CREDENTIALS = 'user:pass'; t.is( - getAuthUrl('git@host.com:group/subgroup/owner/repo.git'), - 'https://user:pass@host.com/group/subgroup/owner/repo.git' + await getAuthUrl({repositoryUrl: 'https://host.null/group/subgroup/owner/repo.git'}), + 'https://user:pass@host.null/group/subgroup/owner/repo.git' ); }); + +test.serial('Handle "git" URL with group and subgroup, with "GIT_CREDENTIALS', async t => { + process.env.GIT_CREDENTIALS = 'user:pass'; + t.is( + await getAuthUrl({repositoryUrl: 'git@host.null:group/subgroup/owner/repo.git'}), + 'https://user:pass@host.null/group/subgroup/owner/repo.git' + ); +}); + +test.serial('Do not add git credential to repositoryUrl if push is allowed', async t => { + process.env.GIT_CREDENTIALS = 'user:pass'; + // Create a git repository, set the current working directory at the root of the repo + const repositoryUrl = await gitRepo(true); + + t.is(await getAuthUrl({repositoryUrl}), repositoryUrl); +});