feat: throw an Error if package.json has duplicate "repository" key (#1656)
This commit is contained in:
parent
18e35b28ad
commit
b8fb35c7e1
@ -229,7 +229,7 @@ Before pushing your code changes make sure there are no linting errors with `npm
|
|||||||
|
|
||||||
### Tests
|
### Tests
|
||||||
|
|
||||||
Running the integration test requires you to install [Docker](https://docs.docker.com/engine/installation) on your machine.
|
Running the integration test requires you to install [Docker](https://docs.docker.com/engine/installation) on your machine. Note: the tests assume that running `git init` will create a `master` branch by default. If your local `git` is configured differently (see [`init.defaultBranch`](https://github.blog/2020-07-27-highlights-from-git-2-28/#introducing-init-defaultbranch)), change it temporarily when running the tests.
|
||||||
|
|
||||||
All the [semantic-release](https://github.com/semantic-release) repositories use [AVA](https://github.com/avajs/ava) for writing and running tests.
|
All the [semantic-release](https://github.com/semantic-release) repositories use [AVA](https://github.com/avajs/ava) for writing and running tests.
|
||||||
|
|
||||||
|
@ -29,6 +29,10 @@ Please make sure to add the \`repositoryUrl\` to the [semantic-release configura
|
|||||||
'docs/usage/configuration.md'
|
'docs/usage/configuration.md'
|
||||||
)}).`,
|
)}).`,
|
||||||
}),
|
}),
|
||||||
|
EDUPLICATEREPOSITORYKEY: ({packageJsonPath}) => ({
|
||||||
|
message: 'Duplicate `"repository"` key in package.json.',
|
||||||
|
details: `Your package.json file at ${packageJsonPath} has more than one "repository" keys.`,
|
||||||
|
}),
|
||||||
EGITNOPERMISSION: ({options: {repositoryUrl}, branch: {name}}) => ({
|
EGITNOPERMISSION: ({options: {repositoryUrl}, branch: {name}}) => ({
|
||||||
message: 'Cannot push to the Git repository.',
|
message: 'Cannot push to the Git repository.',
|
||||||
details: `**semantic-release** cannot push the version tag to the branch \`${name}\` on the remote Git repository with URL \`${repositoryUrl}\`.
|
details: `**semantic-release** cannot push the version tag to the branch \`${name}\` on the remote Git repository with URL \`${repositoryUrl}\`.
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
|
const {readFile} = require('fs').promises;
|
||||||
const {castArray, pickBy, isNil, isString, isPlainObject} = require('lodash');
|
const {castArray, pickBy, isNil, isString, isPlainObject} = require('lodash');
|
||||||
const readPkgUp = require('read-pkg-up');
|
const findPkgUp = require('pkg-up');
|
||||||
const {cosmiconfig} = require('cosmiconfig');
|
const {cosmiconfig} = require('cosmiconfig');
|
||||||
const resolveFrom = require('resolve-from');
|
const resolveFrom = require('resolve-from');
|
||||||
|
const findDuplicatedPropertyKeys = require('find-duplicated-property-keys');
|
||||||
const debug = require('debug')('semantic-release:config');
|
const debug = require('debug')('semantic-release:config');
|
||||||
const {repoUrl} = require('./git');
|
const {repoUrl} = require('./git');
|
||||||
const PLUGINS_DEFINITIONS = require('./definitions/plugins');
|
const PLUGINS_DEFINITIONS = require('./definitions/plugins');
|
||||||
const plugins = require('./plugins');
|
const plugins = require('./plugins');
|
||||||
const {validatePlugin, parseConfig} = require('./plugins/utils');
|
const {validatePlugin, parseConfig} = require('./plugins/utils');
|
||||||
|
const getError = require('./get-error');
|
||||||
|
|
||||||
const CONFIG_NAME = 'release';
|
const CONFIG_NAME = 'release';
|
||||||
const CONFIG_FILES = [
|
const CONFIG_FILES = [
|
||||||
@ -74,7 +77,7 @@ module.exports = async (context, cliOptions) => {
|
|||||||
{name: 'beta', prerelease: true},
|
{name: 'beta', prerelease: true},
|
||||||
{name: 'alpha', prerelease: true},
|
{name: 'alpha', prerelease: true},
|
||||||
],
|
],
|
||||||
repositoryUrl: (await pkgRepoUrl({normalize: false, cwd})) || (await repoUrl({cwd, env})),
|
repositoryUrl: (await pkgRepoUrl({cwd})) || (await repoUrl({cwd, env})),
|
||||||
tagFormat: `v\${version}`,
|
tagFormat: `v\${version}`,
|
||||||
plugins: [
|
plugins: [
|
||||||
'@semantic-release/commit-analyzer',
|
'@semantic-release/commit-analyzer',
|
||||||
@ -93,6 +96,18 @@ module.exports = async (context, cliOptions) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
async function pkgRepoUrl(options) {
|
async function pkgRepoUrl(options) {
|
||||||
const {packageJson} = (await readPkgUp(options)) || {};
|
const packageJsonPath = await findPkgUp(options);
|
||||||
return packageJson && (isPlainObject(packageJson.repository) ? packageJson.repository.url : packageJson.repository);
|
if (!packageJsonPath) return;
|
||||||
|
|
||||||
|
const packageJsonString = await readFile(packageJsonPath, 'utf-8');
|
||||||
|
const result = findDuplicatedPropertyKeys(packageJsonString);
|
||||||
|
|
||||||
|
if (result.length > 0) {
|
||||||
|
throw getError('EDUPLICATEREPOSITORYKEY', {packageJsonPath});
|
||||||
|
}
|
||||||
|
|
||||||
|
const {repository} = require(packageJsonPath);
|
||||||
|
if (!repository) return;
|
||||||
|
|
||||||
|
return isPlainObject(repository) ? repository.url : repository;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
"env-ci": "^5.0.0",
|
"env-ci": "^5.0.0",
|
||||||
"execa": "^4.0.0",
|
"execa": "^4.0.0",
|
||||||
"figures": "^3.0.0",
|
"figures": "^3.0.0",
|
||||||
|
"find-duplicated-property-keys": "^1.2.2",
|
||||||
"find-versions": "^3.0.0",
|
"find-versions": "^3.0.0",
|
||||||
"get-stream": "^5.0.0",
|
"get-stream": "^5.0.0",
|
||||||
"git-log-parser": "^1.2.0",
|
"git-log-parser": "^1.2.0",
|
||||||
@ -42,7 +43,7 @@
|
|||||||
"micromatch": "^4.0.2",
|
"micromatch": "^4.0.2",
|
||||||
"p-each-series": "^2.1.0",
|
"p-each-series": "^2.1.0",
|
||||||
"p-reduce": "^2.0.0",
|
"p-reduce": "^2.0.0",
|
||||||
"read-pkg-up": "^7.0.0",
|
"pkg-up": "^3.1.0",
|
||||||
"resolve-from": "^5.0.0",
|
"resolve-from": "^5.0.0",
|
||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
"semver-diff": "^3.1.1",
|
"semver-diff": "^3.1.1",
|
||||||
@ -128,7 +129,8 @@
|
|||||||
"prettier": true,
|
"prettier": true,
|
||||||
"space": true,
|
"space": true,
|
||||||
"rules": {
|
"rules": {
|
||||||
"unicorn/string-content": "off"
|
"unicorn/string-content": "off",
|
||||||
|
"node/no-unsupported-features/node-builtins": "off"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -516,3 +516,21 @@ test('Throw an Error if one of the shareable config cannot be found', async (t)
|
|||||||
code: 'MODULE_NOT_FOUND',
|
code: 'MODULE_NOT_FOUND',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('Throw an Error if package.json has duplicate "repository" key', async (t) => {
|
||||||
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
|
const {cwd} = await gitRepo();
|
||||||
|
|
||||||
|
// Create package.json with duplicate "repository" key
|
||||||
|
await writeFile(
|
||||||
|
path.resolve(cwd, 'package.json'),
|
||||||
|
`{
|
||||||
|
"repository": "https://github.com/octocat/repository",
|
||||||
|
"repository": "https://github.com/octocat/repository"
|
||||||
|
}`
|
||||||
|
);
|
||||||
|
|
||||||
|
const error = await t.throwsAsync(t.context.getConfig({cwd}));
|
||||||
|
t.is(error.code, 'EDUPLICATEREPOSITORYKEY');
|
||||||
|
t.is(error.message, 'Duplicate `"repository"` key in package.json.');
|
||||||
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user