Compare commits

...
29 Commits
Author SHA1 Message Date
Gregor MartynusandGitHub 431d571a7b fix: adapt for semver to version 7.3.2 (part II) (#1530) 2020-04-16 14:42:25 -07:00
Gregor Martynus 0363790b8a fix: adapt for semver to version 7.3.2
see https://github.com/npm/node-semver/issues/322
2020-04-16 13:54:47 -07:00
greenkeeper[bot]andGitHub 93cb76653d chore(package): update semver to version 7.3.2 2020-04-14 17:46:03 +00:00
Gregor Martynus caa3526caa style: xo 2020-04-08 15:13:33 -07:00
greenkeeper[bot]andGitHub ed5f26d10b chore(package): update xo to version 0.29.0 2020-04-08 21:14:42 +00:00
Justin PoehneltandGitHub ff1d53df58 docs: add @google/semantic-release-replace-plugin to plugin list (#1509) 2020-04-02 16:23:31 -07:00
greenkeeper[bot]andPierre Vanduynslager f899fa9a7c chore(package): update xo to version 0.28.1
Closes #1488
2020-03-26 23:55:26 -04:00
greenkeeper[bot]andGregor Martynus b5488ae7a5 chore(package): update fs-extra to version 9.0.0 2020-03-19 11:31:14 -07:00
greenkeeper[bot]andPierre Vanduynslager da5d1cf9c6 chore(package): update tempy to version 0.5.0 2020-03-09 11:22:55 -04:00
Gaurav NelsonandGitHub da5d06cf78 docs: fix formatting for GitBook 2020-02-27 02:52:32 -05:00
greenkeeper[bot]andPierre Vanduynslager b85adbdb8f chore(package): update xo to version 0.27.0 2020-02-25 17:55:12 -05:00
greenkeeper[bot]andPierre Vanduynslager bce633a41e chore(package): update sinon to version 9.0.0 2020-02-19 18:08:22 -05:00
Pierre Vanduynslager 55be0ba2b1 fix: add repositoryUrl in logs 2020-02-17 14:09:01 -05:00
Raphaël HuchetandGitHub ec516a34bf docs(configuration): fix CLI usage with --branches option (#1465) 2020-02-17 10:05:33 -08:00
greenkeeper[bot]andGregor Martynus 5f89e6bfc0 chore(package): update nock to version 12.0.0 2020-02-16 13:54:44 -08:00
greenkeeper[bot]andPierre Vanduynslager 195e5b18c7 chore(package): update xo to version 0.26.0 2020-02-12 20:09:31 -05:00
Pierre Vanduynslager e7bede1866 fix: pass a branch name to getGitAuthUrl 2020-02-12 19:56:12 -05:00
greenkeeper[bot]andPierre Vanduynslager 8426b4203e chore(package): update tempy to version 0.4.0 2020-02-12 16:09:26 -05:00
Gregor MartynusandGitHub 804fc2a943 docs(Troubleshooting): release not found in prereleases branch (e.g. beta) after rebase on master) (#1444) 2020-02-08 11:03:48 -08:00
greenkeeper[bot]andPierre Vanduynslager 389e3316e9 chore(package): update got to version 10.5.2 2020-02-07 19:00:38 -05:00
Pierre Vanduynslager a93c96fec9 revert: fix: allow plugins to set environment variables to be used by other plugins
This reverts commit 68f7e928f9.
2020-02-07 17:50:14 -05:00
Pierre VanduynslagerandGregor Martynus 68f7e928f9 fix: allow plugins to set environment variables to be used by other plugins 2020-02-07 13:51:20 -08:00
Gregor MartynusandGitHub 8ce2d6e834 fix(package): update marked-terminal to version 4.0.0 2020-01-31 11:14:54 -05:00
Pierre Vanduynslager 45695b9183 fix(package): update @semantic-release/commit-analyzer to version 8.0.0 2020-01-28 11:31:01 -05:00
Pierre Vanduynslager 3c7b114eed fix(package): update @semantic-release/release-notes-generator to version 9.0.0 2020-01-28 11:31:01 -05:00
Pierre Vanduynslager f2b5826c0c fix(package): update @semantic-release/npm to version 7.0.0 2020-01-28 11:31:01 -05:00
greenkeeper[bot]andPierre Vanduynslager c48bd3ac36 fix(package): update @semantic-release/github to version 7.0.0 2020-01-28 11:31:01 -05:00
Pierre Vanduynslager bc97537c97 test: fix copy/paste typo in test titles 2020-01-28 10:33:24 -05:00
Mario LubenkaandPierre Vanduynslager c7e461dc1c docs: add @saithodev/semantic-release-gitea to community plugins 2020-01-27 14:23:38 -05:00
51 changed files with 534 additions and 499 deletions
+2 -2
View File
@@ -29,7 +29,7 @@ execa('git', ['--version'])
process.exit(1);
}
})
.catch(error => {
.catch((error) => {
console.error(`[semantic-release]: Git version ${MIN_GIT_VERSION} is required. No git binary found.`);
console.error(error);
process.exit(1);
@@ -37,7 +37,7 @@ execa('git', ['--version'])
// Node 10+ from this point on
require('../cli')()
.then(exitCode => {
.then((exitCode) => {
process.exitCode = exitCode;
})
.catch(() => {
+6 -6
View File
@@ -5,15 +5,15 @@ const hideSensitive = require('./lib/hide-sensitive');
const stringList = {
type: 'string',
array: true,
coerce: values =>
coerce: (values) =>
values.length === 1 && values[0].trim() === 'false'
? []
: values.reduce((values, value) => values.concat(value.split(',').map(value => value.trim())), []),
: values.reduce((values, value) => values.concat(value.split(',').map((value) => value.trim())), []),
};
module.exports = async () => {
const cli = require('yargs')
.command('$0', 'Run automated package publishing', yargs => {
.command('$0', 'Run automated package publishing', (yargs) => {
yargs.demandCommand(0, 0).usage(`Run automated package publishing
Usage:
@@ -41,18 +41,18 @@ Usage:
.exitProcess(false);
try {
const {help, version, ...opts} = cli.parse(argv.slice(2));
const {help, version, ...options} = cli.parse(argv.slice(2));
if (Boolean(help) || Boolean(version)) {
return 0;
}
if (opts.debug) {
if (options.debug) {
// Debug must be enabled before other requires in order to work
require('debug').enable('semantic-release:*');
}
await require('.')(opts);
await require('.')(options);
return 0;
} catch (error) {
if (error.name !== 'YError') {
+6
View File
@@ -95,3 +95,9 @@
- `verifyConditions`: Checks the project.clj is syntactically valid.
- `prepare`: Update the project.clj version and package the output jar file.
- `publish`: Publish the jar (and generated Maven metadata) to a maven repository (or clojars).
- [@saithodev/semantic-release-gitea](https://github.com/saitho/semantic-release-gitea)
- `verifyConditions`: Verify the presence and the validity of the authentication and the assets option configuration.
- `publish`: Publish a Gitea release, optionally uploading file assets.
- `addChannel`: Update a Gitea release's pre-release field.
- [@google/semantic-release-replace-plugin](https://github.com/google/semantic-release-replace-plugin)
- `prepare`: Replace version strings in files using regex and glob.
+13
View File
@@ -54,3 +54,16 @@ $ git branch --contains <tag name>
$ git tag -d <tag name>
$ git push origin :refs/tags/<tag name>
```
## release not found release branch after `git push --force`
**semantic-release** is using both [git tags](https://git-scm.com/docs/git-tag) and [git notes](https://git-scm.com/docs/git-notes) to store information about which releases happened in which branch.
After a git history rewrite due to a `git push --force`, the git tags and notes referencing the commits that were rewritten are lost.
To recover from that situation, do the following:
1. Delete the tag(s) for the release(s) that have been lost from the git history. You can delete each tag from remote using `git push origin :[TAG NAME]`, e.g. `git push origin :v2.0.0-beta.1`. You can delete tags locally using `git tag -d [TAG NAME]`, e.g. `git tag -d v2.0.0-beta.1`.
2. Re-create the tags locally: `git tag [TAG NAME] [COMMIT HASH]`, where `[COMMIT HASH]` is the new commit that created the release for the lost tag. E.g. `git tag v2.0.0-beta.1 abcdef0`
3. Re-create the git notes for each release tag, e.g. `git notes --ref semantic-release add -f -m '{"channels":["beta"]}' v3.0.0-beta.1`. If the release was also published in the default channel (usually `master`), then set the first channel to `null`, e.g. `git notes --ref semantic-release add -f -m '{"channels":[null, "beta"]}'
4. Push the local notes: `git push --force origin refs/notes/semantic-release`. The `--force` is needed after the rebase. Be careful.
+1 -1
View File
@@ -38,7 +38,7 @@ The following three examples are the same.
- Via CLI argument:
```bash
$ semantic-release --branch next
$ semantic-release --branches next
```
**Note**: CLI arguments take precedence over options configured in the configuration file.
+1
View File
@@ -1,6 +1,7 @@
# Getting started
In order to use **semantic-release** you must follow these steps:
1. [Install](./installation.md#installation) **semantic-release** in your project
2. Configure your Continuous Integration service to [run **semantic-release**](./ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded)
3. Configure your Git repository and package manager repository [authentication](ci-configuration.md#authentication) in your Continuous Integration service
+8 -6
View File
@@ -52,7 +52,7 @@ async function run(context, plugins) {
// Verify config
await verify(context);
options.repositoryUrl = await getGitAuthUrl(context);
options.repositoryUrl = await getGitAuthUrl({...context, branch: {name: ciBranch}});
context.branches = await getBranches(options.repositoryUrl, ciBranch, context);
context.branch = context.branches.find(({name}) => name === ciBranch);
@@ -66,7 +66,9 @@ async function run(context, plugins) {
}
logger[options.dryRun ? 'warn' : 'success'](
`Run automated release from branch ${ciBranch}${options.dryRun ? ' in dry-run mode' : ''}`
`Run automated release from branch ${ciBranch} on repository ${options.repositoryUrl}${
options.dryRun ? ' in dry-run mode' : ''
}`
);
try {
@@ -212,7 +214,7 @@ async function run(context, plugins) {
}
function logErrors({logger, stderr}, err) {
const errors = extractErrors(err).sort(error => (error.semanticRelease ? -1 : 0));
const errors = extractErrors(err).sort((error) => (error.semanticRelease ? -1 : 0));
for (const error of errors) {
if (error.semanticRelease) {
logger.error(`${error.code} ${error.message}`);
@@ -226,7 +228,7 @@ function logErrors({logger, stderr}, err) {
}
async function callFail(context, plugins, err) {
const errors = extractErrors(err).filter(err => err.semanticRelease);
const errors = extractErrors(err).filter((err) => err.semanticRelease);
if (errors.length > 0) {
try {
await plugins.fail({...context, errors});
@@ -236,7 +238,7 @@ async function callFail(context, plugins, err) {
}
}
module.exports = async (opts = {}, {cwd = process.cwd(), env = process.env, stdout, stderr} = {}) => {
module.exports = async (cliOptions = {}, {cwd = process.cwd(), env = process.env, stdout, stderr} = {}) => {
const {unhook} = hookStd(
{silent: false, streams: [process.stdout, process.stderr, stdout, stderr].filter(Boolean)},
hideSensitive(env)
@@ -251,7 +253,7 @@ module.exports = async (opts = {}, {cwd = process.cwd(), env = process.env, stdo
context.logger = getLogger(context);
context.logger.log(`Running ${pkg.name} version ${pkg.version}`);
try {
const {plugins, options} = await getConfig(context, opts);
const {plugins, options} = await getConfig(context, cliOptions);
context.options = options;
try {
const result = await run(context, plugins);
+2 -2
View File
@@ -8,9 +8,9 @@ module.exports = async (repositoryUrl, {cwd}, branches) => {
return branches.reduce(
(branches, branch) => [
...branches,
...remove(gitBranches, name => micromatch(gitBranches, branch.name).includes(name)).map(name => ({
...remove(gitBranches, (name) => micromatch(gitBranches, branch.name).includes(name)).map((name) => ({
name,
...mapValues(omit(branch, 'name'), value => (isString(value) ? template(value)({name}) : value)),
...mapValues(omit(branch, 'name'), (value) => (isString(value) ? template(value)({name}) : value)),
})),
],
[]
+5 -5
View File
@@ -14,7 +14,7 @@ module.exports = async (repositoryUrl, ciBranch, context) => {
const remoteBranches = await expand(
repositoryUrl,
context,
context.options.branches.map(branch => (isString(branch) || isRegExp(branch) ? {name: branch} : branch))
context.options.branches.map((branch) => (isString(branch) || isRegExp(branch) ? {name: branch} : branch))
);
await pEachSeries(remoteBranches, async ({name}) => {
@@ -32,7 +32,7 @@ module.exports = async (repositoryUrl, ciBranch, context) => {
);
const result = Object.entries(DEFINITIONS).reduce((result, [type, {branchesValidator, branchValidator}]) => {
branchesByType[type].forEach(branch => {
branchesByType[type].forEach((branch) => {
if (branchValidator && !branchValidator(branch)) {
errors.push(getError(`E${type.toUpperCase()}BRANCH`, {branch}));
}
@@ -48,15 +48,15 @@ module.exports = async (repositoryUrl, ciBranch, context) => {
}, {});
const duplicates = [...branches]
.map(branch => branch.name)
.map((branch) => branch.name)
.sort()
.filter((_, idx, arr) => arr[idx] === arr[idx + 1] && arr[idx] !== arr[idx - 1]);
.filter((_, idx, array) => array[idx] === array[idx + 1] && array[idx] !== array[idx - 1]);
if (duplicates.length > 0) {
errors.push(getError('EDUPLICATEBRANCHES', {duplicates}));
}
await pEachSeries(branches, async branch => {
await pEachSeries(branches, async (branch) => {
if (!(await verifyBranchName(branch.name))) {
errors.push(getError('EINVALIDBRANCHNAME', branch));
}
+4 -4
View File
@@ -5,19 +5,19 @@ const {isMaintenanceRange} = require('../utils');
const maintenance = {
filter: ({name, range}) => (!isNil(range) && range !== false) || isMaintenanceRange(name),
branchValidator: ({range}) => (isNil(range) ? true : isMaintenanceRange(range)),
branchesValidator: branches => uniqBy(branches, ({range}) => semver.validRange(range)).length === branches.length,
branchesValidator: (branches) => uniqBy(branches, ({range}) => semver.validRange(range)).length === branches.length,
};
const prerelease = {
filter: ({prerelease}) => !isNil(prerelease) && prerelease !== false,
branchValidator: ({name, prerelease}) =>
Boolean(prerelease) && Boolean(semver.valid(`1.0.0-${prerelease === true ? name : prerelease}.1`)),
branchesValidator: branches => uniqBy(branches, 'prerelease').length === branches.length,
branchesValidator: (branches) => uniqBy(branches, 'prerelease').length === branches.length,
};
const release = {
filter: branch => !maintenance.filter(branch) && !prerelease.filter(branch),
branchesValidator: branches => branches.length <= 3 && branches.length > 0,
filter: (branch) => !maintenance.filter(branch) && !prerelease.filter(branch),
branchesValidator: (branches) => branches.length <= 3 && branches.length > 0,
};
module.exports = {maintenance, prerelease, release};
+5 -4
View File
@@ -4,9 +4,10 @@ const pkg = require('../../package.json');
const {RELEASE_TYPE} = require('./constants');
const [homepage] = pkg.homepage.split('#');
const stringify = obj => (isString(obj) ? obj : inspect(obj, {breakLength: Infinity, depth: 2, maxArrayLength: 5}));
const linkify = file => `${homepage}/blob/master/${file}`;
const wordsList = words =>
const stringify = (object) =>
isString(object) ? object : inspect(object, {breakLength: Infinity, depth: 2, maxArrayLength: 5});
const linkify = (file) => `${homepage}/blob/master/${file}`;
const wordsList = (words) =>
`${words.slice(0, -1).join(', ')}${words.length > 1 ? ` or ${words[words.length - 1]}` : trim(words[0])}`;
module.exports = {
@@ -84,7 +85,7 @@ Please refer to the \`${pluginName}\` and [semantic-release plugins configuratio
EANALYZECOMMITSOUTPUT: ({result, pluginName}) => ({
message: 'The `analyzeCommits` plugin returned an invalid value. It must return a valid semver release type.',
details: `The \`analyzeCommits\` plugin must return a valid [semver](https://semver.org) release type. The valid values are: ${RELEASE_TYPE.map(
type => `\`${type}\``
(type) => `\`${type}\``
).join(', ')}.
The \`analyzeCommits\` function of the \`${pluginName}\` returned \`${stringify(result)}\` instead.
+7 -7
View File
@@ -16,12 +16,12 @@ module.exports = {
default: ['@semantic-release/commit-analyzer'],
required: true,
dryRun: true,
outputValidator: output => !output || RELEASE_TYPE.includes(output),
outputValidator: (output) => !output || RELEASE_TYPE.includes(output),
preprocess: ({commits, ...inputs}) => ({
...inputs,
commits: commits.filter(commit => !/\[skip\s+release\]|\[release\s+skip\]/i.test(commit.message)),
commits: commits.filter((commit) => !/\[skip\s+release]|\[release\s+skip]/i.test(commit.message)),
}),
postprocess: results =>
postprocess: (results) =>
RELEASE_TYPE[
results.reduce((highest, result) => {
const typeIndex = RELEASE_TYPE.indexOf(result);
@@ -37,7 +37,7 @@ module.exports = {
generateNotes: {
required: false,
dryRun: true,
outputValidator: output => !output || isString(output),
outputValidator: (output) => !output || isString(output),
pipelineConfig: () => ({
getNextInput: ({nextRelease, ...context}, notes) => ({
...context,
@@ -53,7 +53,7 @@ module.exports = {
required: false,
dryRun: false,
pipelineConfig: ({generateNotes}) => ({
getNextInput: async context => {
getNextInput: async (context) => {
const newGitHead = await getGitHead({cwd: context.cwd});
// If previous prepare plugin has created a commit (gitHead changed)
if (context.nextRelease.gitHead !== newGitHead) {
@@ -70,7 +70,7 @@ module.exports = {
publish: {
required: false,
dryRun: false,
outputValidator: output => !output || isPlainObject(output),
outputValidator: (output) => !output || isPlainObject(output),
pipelineConfig: () => ({
// Add `nextRelease` and plugin properties to published release
transform: (release, step, {nextRelease}) => ({
@@ -83,7 +83,7 @@ module.exports = {
addChannel: {
required: false,
dryRun: false,
outputValidator: output => !output || isPlainObject(output),
outputValidator: (output) => !output || isPlainObject(output),
pipelineConfig: () => ({
// Add `nextRelease` and plugin properties to published release
transform: (release, step, {nextRelease}) => ({
+9 -9
View File
@@ -19,14 +19,14 @@ const CONFIG_FILES = [
`${CONFIG_NAME}.config.js`,
];
module.exports = async (context, opts) => {
module.exports = async (context, cliOptions) => {
const {cwd, env} = context;
const {config, filepath} = (await cosmiconfig(CONFIG_NAME, {searchPlaces: CONFIG_FILES}).search(cwd)) || {};
debug('load config from: %s', filepath);
// Merge config file options and CLI/API options
let options = {...config, ...opts};
let options = {...config, ...cliOptions};
if (options.ci === false) {
options.noCi = true;
}
@@ -38,14 +38,14 @@ module.exports = async (context, opts) => {
// If `extends` is defined, load and merge each shareable config with `options`
options = {
...castArray(extendPaths).reduce((result, extendPath) => {
const extendsOpts = require(resolveFrom.silent(__dirname, extendPath) || resolveFrom(cwd, extendPath));
const extendsOptions = require(resolveFrom.silent(__dirname, extendPath) || resolveFrom(cwd, extendPath));
// For each plugin defined in a shareable config, save in `pluginsPath` the extendable config path,
// so those plugin will be loaded relatively to the config file
Object.entries(extendsOpts)
Object.entries(extendsOptions)
.filter(([, value]) => Boolean(value))
.reduce((pluginsPath, [option, value]) => {
castArray(value).forEach(plugin => {
castArray(value).forEach((plugin) => {
if (option === 'plugins' && validatePlugin(plugin)) {
pluginsPath[parseConfig(plugin)[0]] = extendPath;
} else if (
@@ -58,7 +58,7 @@ module.exports = async (context, opts) => {
return pluginsPath;
}, pluginsPath);
return {...result, ...extendsOpts};
return {...result, ...extendsOptions};
}, {}),
...options,
};
@@ -83,7 +83,7 @@ module.exports = async (context, opts) => {
'@semantic-release/github',
],
// Remove `null` and `undefined` options so they can be replaced with default ones
...pickBy(options, option => !isNil(option)),
...pickBy(options, (option) => !isNil(option)),
...(options.branches ? {branches: castArray(options.branches)} : {}),
};
@@ -92,7 +92,7 @@ module.exports = async (context, opts) => {
return {options, plugins: await plugins({...context, options}, pluginsPath)};
};
async function pkgRepoUrl(opts) {
const {packageJson} = (await readPkgUp(opts)) || {};
async function pkgRepoUrl(options) {
const {packageJson} = (await readPkgUp(options)) || {};
return packageJson && (isPlainObject(packageJson.repository) ? packageJson.repository.url : packageJson.repository);
}
+1 -1
View File
@@ -42,7 +42,7 @@ module.exports = async ({cwd, env, branch, options: {repositoryUrl}}) => {
try {
await verifyAuth(repositoryUrl, branch.name, {cwd, env});
} catch (_) {
const envVar = Object.keys(GIT_TOKENS).find(envVar => !isNil(env[envVar]));
const envVar = Object.keys(GIT_TOKENS).find((envVar) => !isNil(env[envVar]));
const gitCredentials = `${GIT_TOKENS[envVar] || ''}${env[envVar] || ''}`;
if (gitCredentials) {
+2 -2
View File
@@ -29,8 +29,8 @@ const {makeTag, isSameChannel} = require('./utils');
module.exports = ({branch, options: {tagFormat}}, {before} = {}) => {
const [{version, gitTag, channels} = {}] = branch.tags
.filter(
tag =>
((branch.type === 'prerelease' && tag.channels.some(channel => isSameChannel(branch.channel, channel))) ||
(tag) =>
((branch.type === 'prerelease' && tag.channels.some((channel) => isSameChannel(branch.channel, channel))) ||
!semver.prerelease(tag.version)) &&
(isUndefined(before) || semver.lt(tag.version, before))
)
+1 -1
View File
@@ -10,7 +10,7 @@ module.exports = ({branch, nextRelease: {type, channel}, lastRelease, logger}) =
if (branch.type === 'prerelease') {
if (
semver.prerelease(lastRelease.version) &&
lastRelease.channels.some(lastReleaseChannel => isSameChannel(lastReleaseChannel, channel))
lastRelease.channels.some((lastReleaseChannel) => isSameChannel(lastReleaseChannel, channel))
) {
version = highest(
semver.inc(lastRelease.version, 'prerelease'),
+1 -1
View File
@@ -11,7 +11,7 @@ const {makeTag, getLowerBound} = require('./utils');
*
* @return {Array<Object>} Last release and next release to be added on the channel of the current branch.
*/
module.exports = context => {
module.exports = (context) => {
const {
branch,
branches,
+44 -44
View File
@@ -14,8 +14,8 @@ Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', commi
*
* @return {String} The commit sha of the tag in parameter or `null`.
*/
async function getTagHead(tagName, execaOpts) {
return (await execa('git', ['rev-list', '-1', tagName], execaOpts)).stdout;
async function getTagHead(tagName, execaOptions) {
return (await execa('git', ['rev-list', '-1', tagName], execaOptions)).stdout;
}
/**
@@ -27,10 +27,10 @@ async function getTagHead(tagName, execaOpts) {
* @return {Array<String>} List of git tags.
* @throws {Error} If the `git` command fails.
*/
async function getTags(branch, execaOpts) {
return (await execa('git', ['tag', '--merged', branch], execaOpts)).stdout
async function getTags(branch, execaOptions) {
return (await execa('git', ['tag', '--merged', branch], execaOptions)).stdout
.split('\n')
.map(tag => tag.trim())
.map((tag) => tag.trim())
.filter(Boolean);
}
@@ -42,12 +42,12 @@ async function getTags(branch, execaOpts) {
* @param {Object} [execaOpts] Options to pass to `execa`.
* @return {Promise<Array<Object>>} The list of commits between `from` and `to`.
*/
async function getCommits(from, to, execaOpts) {
async function getCommits(from, to, execaOptions) {
return (
await getStream.array(
gitLogParser.parse(
{_: `${from ? from + '..' : ''}${to}`},
{cwd: execaOpts.cwd, env: {...process.env, ...execaOpts.env}}
{cwd: execaOptions.cwd, env: {...process.env, ...execaOptions.env}}
)
)
).map(({message, gitTags, ...commit}) => ({...commit, message: message.trim(), gitTags: gitTags.trim()}));
@@ -62,11 +62,11 @@ async function getCommits(from, to, execaOpts) {
* @return {Array<String>} List of git branches.
* @throws {Error} If the `git` command fails.
*/
async function getBranches(repositoryUrl, execaOpts) {
return (await execa('git', ['ls-remote', '--heads', repositoryUrl], execaOpts)).stdout
async function getBranches(repositoryUrl, execaOptions) {
return (await execa('git', ['ls-remote', '--heads', repositoryUrl], execaOptions)).stdout
.split('\n')
.filter(Boolean)
.map(branch => branch.match(/^.+refs\/heads\/(?<branch>.+)$/)[1]);
.map((branch) => branch.match(/^.+refs\/heads\/(?<branch>.+)$/)[1]);
}
/**
@@ -77,9 +77,9 @@ async function getBranches(repositoryUrl, execaOpts) {
*
* @return {Boolean} `true` if the reference exists, falsy otherwise.
*/
async function isRefExists(ref, execaOpts) {
async function isRefExists(ref, execaOptions) {
try {
return (await execa('git', ['rev-parse', '--verify', ref], execaOpts)).exitCode === 0;
return (await execa('git', ['rev-parse', '--verify', ref], execaOptions)).exitCode === 0;
} catch (error) {
debug(error);
}
@@ -99,9 +99,9 @@ async function isRefExists(ref, execaOpts) {
* @param {String} branch The repository branch to fetch.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function fetch(repositoryUrl, branch, ciBranch, execaOpts) {
async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
const isDetachedHead =
(await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {...execaOpts, reject: false})).stdout === 'HEAD';
(await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {...execaOptions, reject: false})).stdout === 'HEAD';
try {
await execa(
@@ -114,7 +114,7 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOpts) {
? [repositoryUrl]
: ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
],
execaOpts
execaOptions
);
} catch (_) {
await execa(
@@ -126,7 +126,7 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOpts) {
? [repositoryUrl]
: ['--update-head-ok', repositoryUrl, `+refs/heads/${branch}:refs/heads/${branch}`]),
],
execaOpts
execaOptions
);
}
}
@@ -137,16 +137,16 @@ async function fetch(repositoryUrl, branch, ciBranch, execaOpts) {
* @param {String} repositoryUrl The remote repository URL.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function fetchNotes(repositoryUrl, execaOpts) {
async function fetchNotes(repositoryUrl, execaOptions) {
try {
await execa(
'git',
['fetch', '--unshallow', repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`],
execaOpts
execaOptions
);
} catch (_) {
await execa('git', ['fetch', repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`], {
...execaOpts,
...execaOptions,
reject: false,
});
}
@@ -159,8 +159,8 @@ async function fetchNotes(repositoryUrl, execaOpts) {
*
* @return {String} the sha of the HEAD commit.
*/
async function getGitHead(execaOpts) {
return (await execa('git', ['rev-parse', 'HEAD'], execaOpts)).stdout;
async function getGitHead(execaOptions) {
return (await execa('git', ['rev-parse', 'HEAD'], execaOptions)).stdout;
}
/**
@@ -170,9 +170,9 @@ async function getGitHead(execaOpts) {
*
* @return {string} The value of the remote git URL.
*/
async function repoUrl(execaOpts) {
async function repoUrl(execaOptions) {
try {
return (await execa('git', ['config', '--get', 'remote.origin.url'], execaOpts)).stdout;
return (await execa('git', ['config', '--get', 'remote.origin.url'], execaOptions)).stdout;
} catch (error) {
debug(error);
}
@@ -185,9 +185,9 @@ async function repoUrl(execaOpts) {
*
* @return {Boolean} `true` if the current working directory is in a git repository, falsy otherwise.
*/
async function isGitRepo(execaOpts) {
async function isGitRepo(execaOptions) {
try {
return (await execa('git', ['rev-parse', '--git-dir'], execaOpts)).exitCode === 0;
return (await execa('git', ['rev-parse', '--git-dir'], execaOptions)).exitCode === 0;
} catch (error) {
debug(error);
}
@@ -202,9 +202,9 @@ async function isGitRepo(execaOpts) {
*
* @throws {Error} if not authorized to push.
*/
async function verifyAuth(repositoryUrl, branch, execaOpts) {
async function verifyAuth(repositoryUrl, branch, execaOptions) {
try {
await execa('git', ['push', '--dry-run', '--no-verify', repositoryUrl, `HEAD:${branch}`], execaOpts);
await execa('git', ['push', '--dry-run', '--no-verify', repositoryUrl, `HEAD:${branch}`], execaOptions);
} catch (error) {
debug(error);
throw error;
@@ -220,8 +220,8 @@ async function verifyAuth(repositoryUrl, branch, execaOpts) {
*
* @throws {Error} if the tag creation failed.
*/
async function tag(tagName, ref, execaOpts) {
await execa('git', ['tag', tagName, ref], execaOpts);
async function tag(tagName, ref, execaOptions) {
await execa('git', ['tag', tagName, ref], execaOptions);
}
/**
@@ -232,8 +232,8 @@ async function tag(tagName, ref, execaOpts) {
*
* @throws {Error} if the push failed.
*/
async function push(repositoryUrl, execaOpts) {
await execa('git', ['push', '--tags', repositoryUrl], execaOpts);
async function push(repositoryUrl, execaOptions) {
await execa('git', ['push', '--tags', repositoryUrl], execaOptions);
}
/**
@@ -244,8 +244,8 @@ async function push(repositoryUrl, execaOpts) {
*
* @throws {Error} if the push failed.
*/
async function pushNotes(repositoryUrl, execaOpts) {
await execa('git', ['push', repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOpts);
async function pushNotes(repositoryUrl, execaOptions) {
await execa('git', ['push', repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);
}
/**
@@ -256,9 +256,9 @@ async function pushNotes(repositoryUrl, execaOpts) {
*
* @return {Boolean} `true` if valid, falsy otherwise.
*/
async function verifyTagName(tagName, execaOpts) {
async function verifyTagName(tagName, execaOptions) {
try {
return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], execaOpts)).exitCode === 0;
return (await execa('git', ['check-ref-format', `refs/tags/${tagName}`], execaOptions)).exitCode === 0;
} catch (error) {
debug(error);
}
@@ -272,9 +272,9 @@ async function verifyTagName(tagName, execaOpts) {
*
* @return {Boolean} `true` if valid, falsy otherwise.
*/
async function verifyBranchName(branch, execaOpts) {
async function verifyBranchName(branch, execaOptions) {
try {
return (await execa('git', ['check-ref-format', `refs/heads/${branch}`], execaOpts)).exitCode === 0;
return (await execa('git', ['check-ref-format', `refs/heads/${branch}`], execaOptions)).exitCode === 0;
} catch (error) {
debug(error);
}
@@ -289,10 +289,10 @@ async function verifyBranchName(branch, execaOpts) {
*
* @return {Boolean} `true` is the HEAD of the current local branch is the same as the HEAD of the remote branch, falsy otherwise.
*/
async function isBranchUpToDate(repositoryUrl, branch, execaOpts) {
async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
return (
(await getGitHead(execaOpts)) ===
(await execa('git', ['ls-remote', '--heads', repositoryUrl, branch], execaOpts)).stdout.match(/^(?<ref>\w+)?/)[1]
(await getGitHead(execaOptions)) ===
(await execa('git', ['ls-remote', '--heads', repositoryUrl, branch], execaOptions)).stdout.match(/^(?<ref>\w+)?/)[1]
);
}
@@ -304,9 +304,9 @@ async function isBranchUpToDate(repositoryUrl, branch, execaOpts) {
*
* @return {Object} the parsed JSON note if there is one, an empty object otherwise.
*/
async function getNote(ref, execaOpts) {
async function getNote(ref, execaOptions) {
try {
return JSON.parse((await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOpts)).stdout);
return JSON.parse((await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout);
} catch (error) {
if (error.exitCode === 1) {
return {};
@@ -324,8 +324,8 @@ async function getNote(ref, execaOpts) {
* @param {String} ref The Git reference to add the note to.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function addNote(note, ref, execaOpts) {
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-f', '-m', JSON.stringify(note), ref], execaOpts);
async function addNote(note, ref, execaOptions) {
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-f', '-m', JSON.stringify(note), ref], execaOptions);
}
module.exports = {
+4 -4
View File
@@ -1,12 +1,12 @@
const {escapeRegExp, size, isString} = require('lodash');
const {SECRET_REPLACEMENT, SECRET_MIN_SIZE} = require('./definitions/constants');
module.exports = env => {
module.exports = (env) => {
const toReplace = Object.keys(env).filter(
envVar => /token|password|credential|secret|private/i.test(envVar) && size(env[envVar].trim()) >= SECRET_MIN_SIZE
(envVar) => /token|password|credential|secret|private/i.test(envVar) && size(env[envVar].trim()) >= SECRET_MIN_SIZE
);
const regexp = new RegExp(toReplace.map(envVar => escapeRegExp(env[envVar])).join('|'), 'g');
return output =>
const regexp = new RegExp(toReplace.map((envVar) => escapeRegExp(env[envVar])).join('|'), 'g');
return (output) =>
output && isString(output) && toReplace.length > 0 ? output.toString().replace(regexp, SECRET_REPLACEMENT) : output;
};
+6 -6
View File
@@ -46,14 +46,14 @@ module.exports = (context, pluginsPath) => {
const pluginsConf = Object.entries(PLUGINS_DEFINITIONS).reduce(
(pluginsConf, [type, {required, default: def, pipelineConfig, postprocess = identity, preprocess = identity}]) => {
let pluginOpts;
let pluginOptions;
if (isNil(options[type]) && def) {
pluginOpts = def;
pluginOptions = def;
} else {
// If an object is passed and the path is missing, merge it with step options
if (isPlainObject(options[type]) && !options[type].path) {
options[type] = castArray(plugins[type]).map(plugin =>
options[type] = castArray(plugins[type]).map((plugin) =>
plugin ? [plugin[0], Object.assign(plugin[1], options[type])] : plugin
);
}
@@ -63,10 +63,10 @@ module.exports = (context, pluginsPath) => {
return pluginsConf;
}
pluginOpts = options[type];
pluginOptions = options[type];
}
const steps = castArray(pluginOpts).map(pluginOpt =>
const steps = castArray(pluginOptions).map((pluginOpt) =>
normalize(
{...context, options: omit(options, Object.keys(PLUGINS_DEFINITIONS), 'plugins')},
type,
@@ -75,7 +75,7 @@ module.exports = (context, pluginsPath) => {
)
);
pluginsConf[type] = async input =>
pluginsConf[type] = async (input) =>
postprocess(
await pipeline(steps, pipelineConfig && pipelineConfig(pluginsConf, logger))(await preprocess(input)),
input
+2 -2
View File
@@ -26,7 +26,7 @@ module.exports = (context, type, pluginOpt, pluginsPath) => {
throw getError('EPLUGIN', {type, pluginName});
}
const validator = async input => {
const validator = async (input) => {
const {dryRun, outputValidator} = PLUGINS_DEFINITIONS[type] || {};
try {
if (!input.options.dryRun || dryRun) {
@@ -48,7 +48,7 @@ module.exports = (context, type, pluginOpt, pluginsPath) => {
logger.warn(`Skip step "${type}" of plugin "${pluginName}" in dry-run mode`);
} catch (error) {
logger.error(`Failed step "${type}" of plugin "${pluginName}"`);
extractErrors(error).forEach(err => Object.assign(err, {pluginName}));
extractErrors(error).forEach((err) => Object.assign(err, {pluginName}));
throw error;
}
};
+1 -1
View File
@@ -25,7 +25,7 @@ const {extractErrors} = require('../utils');
*
* @return {Pipeline} A Function that execute the `steps` sequencially
*/
module.exports = (steps, {settleAll = false, getNextInput = identity, transform = identity} = {}) => async input => {
module.exports = (steps, {settleAll = false, getNextInput = identity, transform = identity} = {}) => async (input) => {
const results = [];
const errors = [];
await pReduce(
+2 -2
View File
@@ -2,8 +2,8 @@ const {dirname} = require('path');
const {isString, isFunction, castArray, isArray, isPlainObject, isNil} = require('lodash');
const resolveFrom = require('resolve-from');
const validateSteps = conf => {
return conf.every(conf => {
const validateSteps = (conf) => {
return conf.every((conf) => {
if (
isArray(conf) &&
(conf.length === 1 || conf.length === 2) &&
+15 -10
View File
@@ -8,13 +8,13 @@ function extractErrors(err) {
function hideSensitiveValues(env, objs) {
const hideFunction = hideSensitive(env);
return objs.map(obj => {
Object.getOwnPropertyNames(obj).forEach(prop => {
if (obj[prop]) {
obj[prop] = hideFunction(obj[prop]);
return objs.map((object) => {
Object.getOwnPropertyNames(object).forEach((prop) => {
if (object[prop]) {
object[prop] = hideFunction(object[prop]);
}
});
return obj;
return object;
});
}
@@ -31,9 +31,14 @@ function isMaintenanceRange(range) {
}
function getUpperBound(range) {
return semver.valid(range)
const result = semver.valid(range)
? range
: ((semver.validRange(range) || '').match(/<(?<upperBound>\d+\.\d+\.\d+)$/) || [])[1];
: ((semver.validRange(range) || '').match(/<(?<upperBound>\d+\.\d+\.\d+(-\d+)?)$/) || [])[1];
return result
? // https://github.com/npm/node-semver/issues/322
result.replace(/-\d+$/, '')
: result;
}
function getLowerBound(range) {
@@ -49,17 +54,17 @@ function lowest(version1, version2) {
}
function getLatestVersion(versions, {withPrerelease} = {}) {
return versions.filter(version => withPrerelease || !semver.prerelease(version)).sort(semver.rcompare)[0];
return versions.filter((version) => withPrerelease || !semver.prerelease(version)).sort(semver.rcompare)[0];
}
function getEarliestVersion(versions, {withPrerelease} = {}) {
return versions.filter(version => withPrerelease || !semver.prerelease(version)).sort(semver.compare)[0];
return versions.filter((version) => withPrerelease || !semver.prerelease(version)).sort(semver.compare)[0];
}
function getFirstVersion(versions, lowerBranches) {
const lowerVersion = union(...lowerBranches.map(({tags}) => tagsToVersions(tags))).sort(semver.rcompare);
if (lowerVersion[0]) {
return versions.sort(semver.compare).find(version => semver.gt(version, lowerVersion[0]));
return versions.sort(semver.compare).find((version) => semver.gt(version, lowerVersion[0]));
}
return getEarliestVersion(versions);
+2 -2
View File
@@ -3,7 +3,7 @@ const AggregateError = require('aggregate-error');
const {isGitRepo, verifyTagName} = require('./git');
const getError = require('./get-error');
module.exports = async context => {
module.exports = async (context) => {
const {
cwd,
env,
@@ -29,7 +29,7 @@ module.exports = async context => {
errors.push(getError('ETAGNOVERSION', context));
}
branches.forEach(branch => {
branches.forEach((branch) => {
if (
!((isString(branch) && branch.trim()) || (isPlainObject(branch) && isString(branch.name) && branch.name.trim()))
) {
+16 -13
View File
@@ -20,11 +20,11 @@
"Pierre Vanduynslager (https://twitter.com/@pvdlg_)"
],
"dependencies": {
"@semantic-release/commit-analyzer": "^7.0.0",
"@semantic-release/commit-analyzer": "^8.0.0",
"@semantic-release/error": "^2.2.0",
"@semantic-release/github": "^6.0.0",
"@semantic-release/npm": "^6.0.0",
"@semantic-release/release-notes-generator": "^7.1.2",
"@semantic-release/github": "^7.0.0",
"@semantic-release/npm": "^7.0.0",
"@semantic-release/release-notes-generator": "^9.0.0",
"aggregate-error": "^3.0.0",
"cosmiconfig": "^6.0.0",
"debug": "^4.0.0",
@@ -38,13 +38,13 @@
"hosted-git-info": "^3.0.0",
"lodash": "^4.17.15",
"marked": "^0.8.0",
"marked-terminal": "^3.2.0",
"marked-terminal": "^4.0.0",
"micromatch": "^4.0.2",
"p-each-series": "^2.1.0",
"p-reduce": "^2.0.0",
"read-pkg-up": "^7.0.0",
"resolve-from": "^5.0.0",
"semver": "^7.1.1",
"semver": "^7.3.2",
"semver-diff": "^3.1.1",
"signale": "^1.2.1",
"yargs": "^15.0.1"
@@ -56,18 +56,18 @@
"delay": "^4.0.0",
"dockerode": "^3.0.0",
"file-url": "^3.0.0",
"fs-extra": "^8.0.0",
"got": "^10.2.1",
"fs-extra": "^9.0.0",
"got": "^10.5.2",
"js-yaml": "^3.10.0",
"mockserver-client": "^5.1.1",
"nock": "^11.1.0",
"nock": "^12.0.0",
"nyc": "^15.0.0",
"p-retry": "^4.0.0",
"proxyquire": "^2.0.0",
"sinon": "^8.0.4",
"sinon": "^9.0.0",
"stream-buffers": "^3.0.2",
"tempy": "^0.3.0",
"xo": "^0.25.0"
"tempy": "^0.5.0",
"xo": "^0.29.0"
},
"engines": {
"node": ">=10.18"
@@ -126,6 +126,9 @@
},
"xo": {
"prettier": true,
"space": true
"space": true,
"rules": {
"unicorn/string-content": "off"
}
}
}
+5 -5
View File
@@ -12,7 +12,7 @@ const merge = (branches, source, target, tag) => {
);
};
test('Enforce ranges with branching release workflow', async t => {
test('Enforce ranges with branching release workflow', async (t) => {
const branches = [
{name: '1.x', tags: []},
{name: '1.0.x', tags: []},
@@ -135,7 +135,7 @@ test('Enforce ranges with branching release workflow', async t => {
t.is(
getBranch(result, '1.0.x').range,
'>=1.0.1 <1.0.2',
'Cannot release on 1.0.x before 1.0.x version = require(master are merged'
'Cannot release on 1.0.x before 1.0.x version from master are merged'
);
t.is(getBranch(result, '1.x').range, '>=1.1.0 <1.0.2', 'Cannot release on 1.x before >= 2.0.0 is released on master');
@@ -189,7 +189,7 @@ test('Enforce ranges with branching release workflow', async t => {
t.is(getBranch(result, '1.x').range, '>=1.2.0 <2.0.0', 'Can release on 1.x only within range');
});
test('Throw SemanticReleaseError for invalid configurations', async t => {
test('Throw SemanticReleaseError for invalid configurations', async (t) => {
const branches = [
{name: '123', range: '123', tags: []},
{name: '1.x', tags: []},
@@ -224,7 +224,7 @@ test('Throw SemanticReleaseError for invalid configurations', async t => {
t.truthy(errors[4].details);
});
test('Throw a SemanticReleaseError if there is duplicate branches', async t => {
test('Throw a SemanticReleaseError if there is duplicate branches', async (t) => {
const branches = [
{name: 'master', tags: []},
{name: 'master', tags: []},
@@ -239,7 +239,7 @@ test('Throw a SemanticReleaseError if there is duplicate branches', async t => {
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError for each invalid branch name', async t => {
test('Throw a SemanticReleaseError for each invalid branch name', async (t) => {
const branches = [
{name: '~master', tags: []},
{name: '^master', tags: []},
+1 -1
View File
@@ -2,7 +2,7 @@ const test = require('ava');
const expand = require('../../lib/branches/expand');
const {gitRepo, gitCommits, gitCheckout, gitPush} = require('../helpers/git-utils');
test('Expand branches defined with globs', async t => {
test('Expand branches defined with globs', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
+5 -5
View File
@@ -2,7 +2,7 @@ const test = require('ava');
const getTags = require('../../lib/branches/get-tags');
const {gitRepo, gitCommits, gitTagVersion, gitCheckout, gitAddNote} = require('../helpers/git-utils');
test('Get the valid tags', async t => {
test('Get the valid tags', async (t) => {
const {cwd} = await gitRepo();
const commits = await gitCommits(['First'], {cwd});
await gitTagVersion('foo', undefined, {cwd});
@@ -28,7 +28,7 @@ test('Get the valid tags', async t => {
]);
});
test('Get the valid tags = require(multiple branches', async t => {
test('Get the valid tags from multiple branches', async (t) => {
const {cwd} = await gitRepo();
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -71,7 +71,7 @@ test('Get the valid tags = require(multiple branches', async t => {
]);
});
test('Return branches with and empty tags array if no valid tag is found', async t => {
test('Return branches with and empty tags array if no valid tag is found', async (t) => {
const {cwd} = await gitRepo();
await gitCommits(['First'], {cwd});
await gitTagVersion('foo', undefined, {cwd});
@@ -85,7 +85,7 @@ test('Return branches with and empty tags array if no valid tag is found', async
t.deepEqual(result, [{name: 'master', tags: []}]);
});
test('Return branches with and empty tags array if no valid tag is found in history of configured branches', async t => {
test('Return branches with and empty tags array if no valid tag is found in history of configured branches', async (t) => {
const {cwd} = await gitRepo();
await gitCommits(['First'], {cwd});
await gitCheckout('next', true, {cwd});
@@ -108,7 +108,7 @@ test('Return branches with and empty tags array if no valid tag is found in hist
]);
});
test('Get the highest valid tag corresponding to the "tagFormat"', async t => {
test('Get the highest valid tag corresponding to the "tagFormat"', async (t) => {
const {cwd} = await gitRepo();
await gitCommits(['First'], {cwd});
+13 -13
View File
@@ -1,9 +1,9 @@
const test = require('ava');
const normalize = require('../../lib/branches/normalize');
const toTags = versions => versions.map(version => ({version}));
const toTags = (versions) => versions.map((version) => ({version}));
test('Maintenance branches - initial state', t => {
test('Maintenance branches - initial state', (t) => {
const maintenance = [
{name: '1.x', channel: '1.x', tags: []},
{name: '1.1.x', tags: []},
@@ -48,7 +48,7 @@ test('Maintenance branches - initial state', t => {
);
});
test('Maintenance branches - cap range to first release present on default branch and not in any Maintenance one', t => {
test('Maintenance branches - cap range to first release present on default branch and not in any Maintenance one', (t) => {
const maintenance = [
{name: '1.x', tags: toTags(['1.0.0', '1.1.0', '1.1.1', '1.2.0', '1.2.1', '1.3.0', '1.4.0', '1.5.0'])},
{name: 'name', range: '1.1.x', tags: toTags(['1.0.0', '1.0.1', '1.1.0', '1.1.1'])},
@@ -110,7 +110,7 @@ test('Maintenance branches - cap range to first release present on default branc
);
});
test('Maintenance branches - cap range to default branch last release if all release are also present on maintenance branch', t => {
test('Maintenance branches - cap range to default branch last release if all release are also present on maintenance branch', (t) => {
const maintenance = [
{name: '1.x', tags: toTags(['1.0.0', '1.2.0', '1.3.0'])},
{name: '2.x.x', tags: toTags(['1.0.0', '1.2.0', '1.3.0', '2.0.0'])},
@@ -147,7 +147,7 @@ test('Maintenance branches - cap range to default branch last release if all rel
);
});
test('Release branches - initial state', t => {
test('Release branches - initial state', (t) => {
const release = [
{name: 'master', tags: []},
{name: 'next', channel: 'next', tags: []},
@@ -187,7 +187,7 @@ test('Release branches - initial state', t => {
);
});
test('Release branches - 3 release branches', t => {
test('Release branches - 3 release branches', (t) => {
const release = [
{name: 'master', tags: toTags(['1.0.0', '1.0.1', '1.0.2'])},
{name: 'next', tags: toTags(['1.0.0', '1.0.1', '1.0.2', '1.1.0', '1.2.0'])},
@@ -220,7 +220,7 @@ test('Release branches - 3 release branches', t => {
);
});
test('Release branches - 2 release branches', t => {
test('Release branches - 2 release branches', (t) => {
const release = [
{name: 'master', tags: toTags(['1.0.0', '1.0.1', '1.1.0', '1.1.1', '1.2.0'])},
{name: 'next', tags: toTags(['1.0.0', '1.0.1', '1.1.0', '1.1.1', '1.2.0', '2.0.0', '2.0.1', '2.1.0'])},
@@ -251,7 +251,7 @@ test('Release branches - 2 release branches', t => {
);
});
test('Release branches - 1 release branches', t => {
test('Release branches - 1 release branches', (t) => {
const release = [{name: 'master', tags: toTags(['1.0.0', '1.1.0', '1.1.1', '1.2.0'])}];
t.deepEqual(
@@ -260,7 +260,7 @@ test('Release branches - 1 release branches', t => {
);
});
test('Release branches - cap ranges to first release only present on following branch', t => {
test('Release branches - cap ranges to first release only present on following branch', (t) => {
const release = [
{name: 'master', tags: toTags(['1.0.0', '1.1.0', '1.2.0', '2.0.0'])},
{name: 'next', tags: toTags(['1.0.0', '1.1.0', '1.2.0', '2.0.0', '2.1.0'])},
@@ -286,7 +286,7 @@ test('Release branches - cap ranges to first release only present on following b
);
});
test('Release branches - Handle missing previous tags in branch history', t => {
test('Release branches - Handle missing previous tags in branch history', (t) => {
const release = [
{name: 'master', tags: toTags(['1.0.0', '2.0.0'])},
{name: 'next', tags: toTags(['1.0.0', '1.1.0', '1.1.1', '1.2.0', '2.0.0'])},
@@ -317,7 +317,7 @@ test('Release branches - Handle missing previous tags in branch history', t => {
);
});
test('Release branches - limit releases on 2nd and 3rd branch based on 1st branch last release', t => {
test('Release branches - limit releases on 2nd and 3rd branch based on 1st branch last release', (t) => {
const release = [
{name: 'master', tags: toTags(['1.0.0', '1.1.0', '2.0.0', '3.0.0'])},
{name: 'next', tags: toTags(['1.0.0', '1.1.0'])},
@@ -357,7 +357,7 @@ test('Release branches - limit releases on 2nd and 3rd branch based on 1st branc
);
});
test('Prerelease branches', t => {
test('Prerelease branches', (t) => {
const prerelease = [
{name: 'beta', channel: 'beta', prerelease: true, tags: []},
{name: 'alpha', prerelease: 'preview', tags: []},
@@ -372,7 +372,7 @@ test('Prerelease branches', t => {
);
});
test('Allow to set channel to "false" to prevent default', t => {
test('Allow to set channel to "false" to prevent default', (t) => {
const maintenance = [{name: '1.x', channel: false, tags: []}];
const release = [
{name: 'master', channel: false, tags: []},
+16 -16
View File
@@ -4,23 +4,23 @@ const proxyquire = require('proxyquire').noPreserveCache();
const {stub} = require('sinon');
const {SECRET_REPLACEMENT} = require('../lib/definitions/constants');
test.beforeEach(t => {
test.beforeEach((t) => {
t.context.logs = '';
t.context.errors = '';
t.context.stdout = stub(process.stdout, 'write').callsFake(val => {
t.context.logs += val.toString();
t.context.stdout = stub(process.stdout, 'write').callsFake((value) => {
t.context.logs += value.toString();
});
t.context.stderr = stub(process.stderr, 'write').callsFake(val => {
t.context.errors += val.toString();
t.context.stderr = stub(process.stderr, 'write').callsFake((value) => {
t.context.errors += value.toString();
});
});
test.afterEach.always(t => {
test.afterEach.always((t) => {
t.context.stdout.restore();
t.context.stderr.restore();
});
test.serial('Pass options to semantic-release API', async t => {
test.serial('Pass options to semantic-release API', async (t) => {
const run = stub().resolves(true);
const argv = [
'',
@@ -86,7 +86,7 @@ test.serial('Pass options to semantic-release API', async t => {
t.is(exitCode, 0);
});
test.serial('Pass options to semantic-release API with alias arguments', async t => {
test.serial('Pass options to semantic-release API with alias arguments', async (t) => {
const run = stub().resolves(true);
const argv = [
'',
@@ -119,7 +119,7 @@ test.serial('Pass options to semantic-release API with alias arguments', async t
t.is(exitCode, 0);
});
test.serial('Pass unknown options to semantic-release API', async t => {
test.serial('Pass unknown options to semantic-release API', async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '--bool', '--first-option', 'value1', '--second-option', 'value2', '--second-option', 'value3'];
const cli = proxyquire('../cli', {'.': run, process: {...process, argv}});
@@ -133,7 +133,7 @@ test.serial('Pass unknown options to semantic-release API', async t => {
t.is(exitCode, 0);
});
test.serial('Pass empty Array to semantic-release API for list option set to "false"', async t => {
test.serial('Pass empty Array to semantic-release API for list option set to "false"', async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '--publish', 'false'];
const cli = proxyquire('../cli', {'.': run, process: {...process, argv}});
@@ -145,7 +145,7 @@ test.serial('Pass empty Array to semantic-release API for list option set to "fa
t.is(exitCode, 0);
});
test.serial('Do not set properties in option for which arg is not in command line', async t => {
test.serial('Do not set properties in option for which arg is not in command line', async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '-b', 'master'];
const cli = proxyquire('../cli', {'.': run, process: {...process, argv}});
@@ -162,7 +162,7 @@ test.serial('Do not set properties in option for which arg is not in command lin
t.false('e' in run.args[0][0]);
});
test.serial('Display help', async t => {
test.serial('Display help', async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '--help'];
const cli = proxyquire('../cli', {'.': run, process: {...process, argv}});
@@ -173,7 +173,7 @@ test.serial('Display help', async t => {
t.is(exitCode, 0);
});
test.serial('Return error exitCode and prints help if called with a command', async t => {
test.serial('Return error exitCode and prints help if called with a command', async (t) => {
const run = stub().resolves(true);
const argv = ['', '', 'pre'];
const cli = proxyquire('../cli', {'.': run, process: {...process, argv}});
@@ -185,7 +185,7 @@ test.serial('Return error exitCode and prints help if called with a command', as
t.is(exitCode, 1);
});
test.serial('Return error exitCode if multiple plugin are set for single plugin', async t => {
test.serial('Return error exitCode if multiple plugin are set for single plugin', async (t) => {
const run = stub().resolves(true);
const argv = ['', '', '--analyze-commits', 'analyze1', 'analyze2'];
const cli = proxyquire('../cli', {'.': run, process: {...process, argv}});
@@ -197,7 +197,7 @@ test.serial('Return error exitCode if multiple plugin are set for single plugin'
t.is(exitCode, 1);
});
test.serial('Return error exitCode if semantic-release throw error', async t => {
test.serial('Return error exitCode if semantic-release throw error', async (t) => {
const run = stub().rejects(new Error('semantic-release error'));
const argv = ['', ''];
const cli = proxyquire('../cli', {'.': run, process: {...process, argv}});
@@ -208,7 +208,7 @@ test.serial('Return error exitCode if semantic-release throw error', async t =>
t.is(exitCode, 1);
});
test.serial('Hide sensitive environment variable values from the logs', async t => {
test.serial('Hide sensitive environment variable values from the logs', async (t) => {
const env = {MY_TOKEN: 'secret token'};
const run = stub().rejects(new Error(`Throw error: Exposing token ${env.MY_TOKEN}`));
const argv = ['', ''];
+8 -8
View File
@@ -1,7 +1,7 @@
const test = require('ava');
const {maintenance, prerelease, release} = require('../../lib/definitions/branches');
test('A "maintenance" branch is identified by having a "range" property or a "name" formatted like "N.x", "N.x.x" or "N.N.x"', t => {
test('A "maintenance" branch is identified by having a "range" property or a "name" formatted like "N.x", "N.x.x" or "N.N.x"', (t) => {
t.true(maintenance.filter({name: '1.x.x'}));
t.true(maintenance.filter({name: '1.0.x'}));
t.true(maintenance.filter({name: '1.x'}));
@@ -17,7 +17,7 @@ test('A "maintenance" branch is identified by having a "range" property or a "na
t.false(maintenance.filter({name: 'x.x.x'}));
});
test('A "maintenance" branches must have a "range" property formatted like "N.x", "N.x.x" or "N.N.x"', t => {
test('A "maintenance" branches must have a "range" property formatted like "N.x", "N.x.x" or "N.N.x"', (t) => {
t.true(maintenance.branchValidator({name: 'some-name', range: '1.x.x'}));
t.true(maintenance.branchValidator({name: 'some-name', range: '1.1.x'}));
@@ -29,14 +29,14 @@ test('A "maintenance" branches must have a "range" property formatted like "N.x"
t.false(maintenance.branchValidator({name: 'some-name', range: ''}));
});
test('The "maintenance" branches must have unique ranges', t => {
test('The "maintenance" branches must have unique ranges', (t) => {
t.true(maintenance.branchesValidator([{range: '1.x.x'}, {range: '1.0.x'}]));
t.false(maintenance.branchesValidator([{range: '1.x.x'}, {range: '1.x.x'}]));
t.false(maintenance.branchesValidator([{range: '1.x.x'}, {range: '1.x'}]));
});
test('A "prerelease" branch is identified by having a thruthy "prerelease" property', t => {
test('A "prerelease" branch is identified by having a thruthy "prerelease" property', (t) => {
t.true(prerelease.filter({name: 'some-name', prerelease: true}));
t.true(prerelease.filter({name: 'some-name', prerelease: 'beta'}));
t.true(prerelease.filter({name: 'some-name', prerelease: ''}));
@@ -46,7 +46,7 @@ test('A "prerelease" branch is identified by having a thruthy "prerelease" prope
t.false(prerelease.filter({name: 'some-name'}));
});
test('A "prerelease" branch must have a valid prerelease detonation in "prerelease" property or in "name" if "prerelease" is "true"', t => {
test('A "prerelease" branch must have a valid prerelease detonation in "prerelease" property or in "name" if "prerelease" is "true"', (t) => {
t.true(prerelease.branchValidator({name: 'beta', prerelease: true}));
t.true(prerelease.branchValidator({name: 'some-name', prerelease: 'beta'}));
@@ -59,13 +59,13 @@ test('A "prerelease" branch must have a valid prerelease detonation in "prerelea
t.false(prerelease.branchValidator({name: '#beta', prerelease: true}));
});
test('The "prerelease" branches must have unique "prerelease" property', t => {
test('The "prerelease" branches must have unique "prerelease" property', (t) => {
t.true(prerelease.branchesValidator([{prerelease: 'beta'}, {prerelease: 'alpha'}]));
t.false(prerelease.branchesValidator([{range: 'beta'}, {range: 'beta'}, {range: 'alpha'}]));
});
test('A "release" branch is identified by not havin a "range" or "prerelease" property or a "name" formatted like "N.x", "N.x.x" or "N.N.x"', t => {
test('A "release" branch is identified by not havin a "range" or "prerelease" property or a "name" formatted like "N.x", "N.x.x" or "N.N.x"', (t) => {
t.true(release.filter({name: 'some-name'}));
t.false(release.filter({name: '1.x.x'}));
@@ -76,7 +76,7 @@ test('A "release" branch is identified by not havin a "range" or "prerelease" pr
t.false(release.filter({name: 'some-name', prerelease: 'beta'}));
});
test('There must be between 1 and 3 release branches', t => {
test('There must be between 1 and 3 release branches', (t) => {
t.true(release.branchesValidator([{name: 'branch1'}]));
t.true(release.branchesValidator([{name: 'branch1'}, {name: 'branch2'}]));
t.true(release.branchesValidator([{name: 'branch1'}, {name: 'branch2'}, {name: 'branch3'}]));
+6 -6
View File
@@ -2,7 +2,7 @@ const test = require('ava');
const plugins = require('../../lib/definitions/plugins');
const {RELEASE_NOTES_SEPARATOR, SECRET_REPLACEMENT} = require('../../lib/definitions/constants');
test('The "analyzeCommits" plugin output must be either undefined or a valid semver release type', t => {
test('The "analyzeCommits" plugin output must be either undefined or a valid semver release type', (t) => {
t.false(plugins.analyzeCommits.outputValidator('invalid'));
t.false(plugins.analyzeCommits.outputValidator(1));
t.false(plugins.analyzeCommits.outputValidator({}));
@@ -12,7 +12,7 @@ test('The "analyzeCommits" plugin output must be either undefined or a valid sem
t.true(plugins.analyzeCommits.outputValidator('major'));
});
test('The "generateNotes" plugin output, if defined, must be a string', t => {
test('The "generateNotes" plugin output, if defined, must be a string', (t) => {
t.false(plugins.generateNotes.outputValidator(1));
t.false(plugins.generateNotes.outputValidator({}));
@@ -22,7 +22,7 @@ test('The "generateNotes" plugin output, if defined, must be a string', t => {
t.true(plugins.generateNotes.outputValidator('string'));
});
test('The "publish" plugin output, if defined, must be an object or "false"', t => {
test('The "publish" plugin output, if defined, must be an object or "false"', (t) => {
t.false(plugins.publish.outputValidator(1));
t.false(plugins.publish.outputValidator('string'));
@@ -33,7 +33,7 @@ test('The "publish" plugin output, if defined, must be an object or "false"', t
t.true(plugins.publish.outputValidator(false));
});
test('The "addChannel" plugin output, if defined, must be an object', t => {
test('The "addChannel" plugin output, if defined, must be an object', (t) => {
t.false(plugins.addChannel.outputValidator(1));
t.false(plugins.addChannel.outputValidator('string'));
@@ -43,7 +43,7 @@ test('The "addChannel" plugin output, if defined, must be an object', t => {
t.true(plugins.addChannel.outputValidator(''));
});
test('The "generateNotes" plugins output are concatenated with separator and sensitive data is hidden', t => {
test('The "generateNotes" plugins output are concatenated with separator and sensitive data is hidden', (t) => {
const env = {MY_TOKEN: 'secret token'};
t.is(plugins.generateNotes.postprocess(['note 1', 'note 2'], {env}), `note 1${RELEASE_NOTES_SEPARATOR}note 2`);
t.is(plugins.generateNotes.postprocess(['', 'note'], {env}), 'note');
@@ -63,7 +63,7 @@ test('The "generateNotes" plugins output are concatenated with separator and sen
);
});
test('The "analyzeCommits" plugins output are reduced to the highest release type', t => {
test('The "analyzeCommits" plugins output are reduced to the highest release type', (t) => {
t.is(plugins.analyzeCommits.postprocess(['major', 'minor']), 'major');
t.is(plugins.analyzeCommits.postprocess(['', 'minor']), 'minor');
t.is(plugins.analyzeCommits.postprocess([undefined, 'patch']), 'patch');
+8 -8
View File
@@ -3,14 +3,14 @@ const {stub} = require('sinon');
const getCommits = require('../lib/get-commits');
const {gitRepo, gitCommits, gitDetachedHead} = require('./helpers/git-utils');
test.beforeEach(t => {
test.beforeEach((t) => {
// Stub the logger functions
t.context.log = stub();
t.context.error = stub();
t.context.logger = {log: t.context.log, error: t.context.error};
});
test('Get all commits when there is no last release', async t => {
test('Get all commits when there is no last release', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -24,7 +24,7 @@ test('Get all commits when there is no last release', async t => {
t.deepEqual(result, commits);
});
test('Get all commits since gitHead (from lastRelease)', async t => {
test('Get all commits since gitHead (from lastRelease)', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -42,7 +42,7 @@ test('Get all commits since gitHead (from lastRelease)', async t => {
t.deepEqual(result, commits.slice(0, 2));
});
test('Get all commits since gitHead (from lastRelease) on a detached head repo', async t => {
test('Get all commits since gitHead (from lastRelease) on a detached head repo', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
// Add commits to the master branch
@@ -66,7 +66,7 @@ test('Get all commits since gitHead (from lastRelease) on a detached head repo',
t.truthy(result[0].committer.name);
});
test('Get all commits between lastRelease.gitHead and a shas', async t => {
test('Get all commits between lastRelease.gitHead and a shas', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -82,10 +82,10 @@ test('Get all commits between lastRelease.gitHead and a shas', async t => {
// Verify the commits created and retrieved by the module are identical
t.is(result.length, 1);
t.deepEqual(result, commits.slice(1, commits.length - 1));
t.deepEqual(result, commits.slice(1, -1));
});
test('Return empty array if lastRelease.gitHead is the last commit', async t => {
test('Return empty array if lastRelease.gitHead is the last commit', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -102,7 +102,7 @@ test('Return empty array if lastRelease.gitHead is the last commit', async t =>
t.deepEqual(result, []);
});
test('Return empty array if there is no commits', async t => {
test('Return empty array if there is no commits', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
+45 -45
View File
@@ -15,12 +15,12 @@ const DEFAULT_PLUGINS = [
'@semantic-release/github',
];
test.beforeEach(t => {
test.beforeEach((t) => {
t.context.plugins = stub().returns({});
t.context.getConfig = proxyquire('../lib/get-config', {'./plugins': t.context.plugins});
});
test('Default values, reading repositoryUrl = require(package.json', async t => {
test('Default values, reading repositoryUrl from package.json', async (t) => {
const pkg = {repository: 'https://host.null/owner/package.git'};
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo(true);
@@ -47,7 +47,7 @@ test('Default values, reading repositoryUrl = require(package.json', async t =>
t.is(result.tagFormat, `v\${version}`);
});
test('Default values, reading repositoryUrl = require(repo if not set in package.json', async t => {
test('Default values, reading repositoryUrl from repo if not set in package.json', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo(true);
// Add remote.origin.url config
@@ -68,7 +68,7 @@ test('Default values, reading repositoryUrl = require(repo if not set in package
t.is(result.tagFormat, `v\${version}`);
});
test('Default values, reading repositoryUrl (http url) = require(package.json if not set in repo', async t => {
test('Default values, reading repositoryUrl (http url) from package.json if not set in repo', async (t) => {
const pkg = {repository: 'https://host.null/owner/module.git'};
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
@@ -90,7 +90,7 @@ test('Default values, reading repositoryUrl (http url) = require(package.json if
t.is(result.tagFormat, `v\${version}`);
});
test('Convert "ci" option to "noCi"', async t => {
test('Convert "ci" option to "noCi"', async (t) => {
const pkg = {repository: 'https://host.null/owner/module.git', release: {ci: false}};
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
@@ -102,7 +102,7 @@ test('Convert "ci" option to "noCi"', async t => {
t.is(result.noCi, true);
});
test('Read options = require(package.json', async t => {
test('Read options from package.json', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const options = {
@@ -119,13 +119,13 @@ test('Read options = require(package.json', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options, branches: ['test_branch']};
// Verify the options contains the plugin config = require(package.json
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(package.json
// Verify the plugins module is called with the plugin options from package.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
});
test('Read options = require(.releaserc.yml', async t => {
test('Read options from .releaserc.yml', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const options = {
@@ -141,13 +141,13 @@ test('Read options = require(.releaserc.yml', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options, branches: ['test_branch']};
// Verify the options contains the plugin config = require(package.json
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(package.json
// Verify the plugins module is called with the plugin options from package.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
});
test('Read options = require(.releaserc.json', async t => {
test('Read options from .releaserc.json', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const options = {
@@ -163,13 +163,13 @@ test('Read options = require(.releaserc.json', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options, branches: ['test_branch']};
// Verify the options contains the plugin config = require(package.json
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(package.json
// Verify the plugins module is called with the plugin options from package.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
});
test('Read options = require(.releaserc.js', async t => {
test('Read options from .releaserc.js', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const options = {
@@ -185,13 +185,13 @@ test('Read options = require(.releaserc.js', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options, branches: ['test_branch']};
// Verify the options contains the plugin config = require(package.json
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(package.json
// Verify the plugins module is called with the plugin options from package.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
});
test('Read options = require(release.config.js', async t => {
test('Read options from release.config.js', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const options = {
@@ -207,13 +207,13 @@ test('Read options = require(release.config.js', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options, branches: ['test_branch']};
// Verify the options contains the plugin config = require(package.json
// Verify the options contains the plugin config from package.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(package.json
// Verify the plugins module is called with the plugin options from package.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
});
test('Prioritise CLI/API parameters over file configuration and git repo', async t => {
test('Prioritise CLI/API parameters over file configuration and git repo', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
@@ -237,13 +237,13 @@ test('Prioritise CLI/API parameters over file configuration and git repo', async
const result = await t.context.getConfig({cwd}, options);
const expected = {...options, branches: ['branch_cli']};
// Verify the options contains the plugin config = require(CLI/API
// Verify the options contains the plugin config from CLI/API
t.deepEqual(result.options, expected);
// Verify the plugins module is called with the plugin options = require(CLI/API
// Verify the plugins module is called with the plugin options from CLI/API
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
});
test('Read configuration = require(file path in "extends"', async t => {
test('Read configuration from file path in "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: './shareable.json'};
@@ -262,9 +262,9 @@ test('Read configuration = require(file path in "extends"', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options, branches: ['test_branch']};
// Verify the options contains the plugin config = require(shareable.json
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(shareable.json
// Verify the plugins module is called with the plugin options from shareable.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
t.deepEqual(t.context.plugins.args[0][1], {
analyzeCommits: './shareable.json',
@@ -274,7 +274,7 @@ test('Read configuration = require(file path in "extends"', async t => {
});
});
test('Read configuration = require(module path in "extends"', async t => {
test('Read configuration from module path in "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: 'shareable'};
@@ -293,9 +293,9 @@ test('Read configuration = require(module path in "extends"', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options, branches: ['test_branch']};
// Verify the options contains the plugin config = require(shareable.json
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(shareable.json
// Verify the plugins module is called with the plugin options from shareable.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
t.deepEqual(t.context.plugins.args[0][1], {
analyzeCommits: 'shareable',
@@ -303,7 +303,7 @@ test('Read configuration = require(module path in "extends"', async t => {
});
});
test('Read configuration = require(an array of paths in "extends"', async t => {
test('Read configuration from an array of paths in "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {extends: ['./shareable1.json', './shareable2.json']};
@@ -329,9 +329,9 @@ test('Read configuration = require(an array of paths in "extends"', async t => {
const {options: result} = await t.context.getConfig({cwd});
const expected = {...options1, ...options2, branches: ['test_branch']};
// Verify the options contains the plugin config = require(shareable1.json and shareable2.json
// Verify the options contains the plugin config from shareable1.json and shareable2.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(shareable1.json and shareable2.json
// Verify the plugins module is called with the plugin options from shareable1.json and shareable2.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
t.deepEqual(t.context.plugins.args[0][1], {
verifyRelease1: './shareable1.json',
@@ -342,7 +342,7 @@ test('Read configuration = require(an array of paths in "extends"', async t => {
});
});
test('Prioritize configuration = require(config file over "extends"', async t => {
test('Prioritize configuration from config file over "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {
@@ -367,9 +367,9 @@ test('Prioritize configuration = require(config file over "extends"', async t =>
const {options: result} = await t.context.getConfig({cwd});
const expected = omit({...options1, ...pkgOptions, branches: ['test_pkg']}, 'extends');
// Verify the options contains the plugin config = require(package.json and shareable.json
// Verify the options contains the plugin config from package.json and shareable.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(package.json and shareable.json
// Verify the plugins module is called with the plugin options from package.json and shareable.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
t.deepEqual(t.context.plugins.args[0][1], {
analyzeCommits: './shareable.json',
@@ -378,7 +378,7 @@ test('Prioritize configuration = require(config file over "extends"', async t =>
});
});
test('Prioritize configuration = require(cli/API options over "extends"', async t => {
test('Prioritize configuration from cli/API options over "extends"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const cliOptions = {
@@ -415,13 +415,13 @@ test('Prioritize configuration = require(cli/API options over "extends"', async
const {options: result} = await t.context.getConfig({cwd}, cliOptions);
const expected = omit({...options2, ...pkgOptions, ...cliOptions, branches: ['branch_opts']}, 'extends');
// Verify the options contains the plugin config = require(package.json and shareable2.json
// Verify the options contains the plugin config from package.json and shareable2.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(package.json and shareable2.json
// Verify the plugins module is called with the plugin options from package.json and shareable2.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
});
test('Allow to unset properties defined in shareable config with "null"', async t => {
test('Allow to unset properties defined in shareable config with "null"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {
@@ -443,13 +443,13 @@ test('Allow to unset properties defined in shareable config with "null"', async
const {options} = await t.context.getConfig({cwd});
// Verify the options contains the plugin config = require(shareable.json and the default `plugins`
// Verify the options contains the plugin config from shareable.json and the default `plugins`
t.deepEqual(options, {
...omit(options1, ['analyzeCommits']),
...omit(pkgOptions, ['extends', 'analyzeCommits']),
plugins: DEFAULT_PLUGINS,
});
// Verify the plugins module is called with the plugin options = require(shareable.json and the default `plugins`
// Verify the plugins module is called with the plugin options from shareable.json and the default `plugins`
t.deepEqual(t.context.plugins.args[0][0], {
options: {
...omit(options1, 'analyzeCommits'),
@@ -466,7 +466,7 @@ test('Allow to unset properties defined in shareable config with "null"', async
});
});
test('Allow to unset properties defined in shareable config with "undefined"', async t => {
test('Allow to unset properties defined in shareable config with "undefined"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkgOptions = {
@@ -492,9 +492,9 @@ test('Allow to unset properties defined in shareable config with "undefined"', a
...omit(pkgOptions, ['extends', 'analyzeCommits']),
branches: ['test_branch'],
};
// Verify the options contains the plugin config = require(shareable.json
// Verify the options contains the plugin config from shareable.json
t.deepEqual(result, expected);
// Verify the plugins module is called with the plugin options = require(shareable.json
// Verify the plugins module is called with the plugin options from shareable.json
t.deepEqual(t.context.plugins.args[0][0], {options: expected, cwd});
t.deepEqual(t.context.plugins.args[0][1], {
generateNotes: './shareable.json',
@@ -502,7 +502,7 @@ test('Allow to unset properties defined in shareable config with "undefined"', a
});
});
test('Throw an Error if one of the shareable config cannot be found', async t => {
test('Throw an Error if one of the shareable config cannot be found', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const pkhOptions = {extends: ['./shareable1.json', 'non-existing-path']};
+26 -26
View File
@@ -4,7 +4,7 @@ const {gitRepo} = require('./helpers/git-utils');
const env = {GIT_ASKPASS: 'echo', GIT_TERMINAL_PROMPT: 0};
test('Return the same "git" formatted URL if "gitCredentials" is not defined', async t => {
test('Return the same "git" formatted URL if "gitCredentials" is not defined', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -13,7 +13,7 @@ test('Return the same "git" formatted URL if "gitCredentials" is not defined', a
);
});
test('Return the same "https" formatted URL if "gitCredentials" is not defined', async t => {
test('Return the same "https" formatted URL if "gitCredentials" is not defined', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -27,7 +27,7 @@ test('Return the same "https" formatted URL if "gitCredentials" is not defined',
);
});
test('Return the "https" formatted URL if "gitCredentials" is not defined and repositoryUrl is a "git+https" URL', async t => {
test('Return the "https" formatted URL if "gitCredentials" is not defined and repositoryUrl is a "git+https" URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -41,7 +41,7 @@ test('Return the "https" formatted URL if "gitCredentials" is not defined and re
);
});
test('Do not add trailing ".git" if not present in the origian URL', async t => {
test('Do not add trailing ".git" if not present in the origian URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -50,7 +50,7 @@ test('Do not add trailing ".git" if not present in the origian URL', async t =>
);
});
test('Handle "https" URL with group and subgroup', async t => {
test('Handle "https" URL with group and subgroup', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -64,7 +64,7 @@ test('Handle "https" URL with group and subgroup', async t => {
);
});
test('Handle "git" URL with group and subgroup', async t => {
test('Handle "git" URL with group and subgroup', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -78,7 +78,7 @@ test('Handle "git" URL with group and subgroup', async t => {
);
});
test('Convert shorthand URL', async t => {
test('Convert shorthand URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -92,7 +92,7 @@ test('Convert shorthand URL', async t => {
);
});
test('Convert GitLab shorthand URL', async t => {
test('Convert GitLab shorthand URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -106,7 +106,7 @@ test('Convert GitLab shorthand URL', async t => {
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -120,7 +120,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined and reposi
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL without user', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git" URL without user', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -133,7 +133,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined and reposi
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "https" URL', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "https" URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -147,7 +147,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined and reposi
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL', async t => {
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -161,7 +161,7 @@ test('Return the "http" formatted URL if "gitCredentials" is defined and reposit
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL with custom port', async t => {
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "http" URL with custom port', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -174,7 +174,7 @@ test('Return the "http" formatted URL if "gitCredentials" is defined and reposit
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+https" URL', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+https" URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -188,7 +188,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined and reposi
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+http" URL', async t => {
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "git+http" URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -202,7 +202,7 @@ test('Return the "http" formatted URL if "gitCredentials" is defined and reposit
);
});
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "ssh" URL', async t => {
test('Return the "http" formatted URL if "gitCredentials" is defined and repositoryUrl is a "ssh" URL', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -215,7 +215,7 @@ test('Return the "http" formatted URL if "gitCredentials" is defined and reposit
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GH_TOKEN"', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined with "GH_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -229,7 +229,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "GH_T
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GITHUB_TOKEN"', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined with "GITHUB_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -243,7 +243,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "GITH
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GL_TOKEN"', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined with "GL_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -257,7 +257,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "GL_T
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "GITLAB_TOKEN"', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined with "GITLAB_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -271,7 +271,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "GITL
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "BB_TOKEN"', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined with "BB_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -285,7 +285,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "BB_T
);
});
test('Return the "https" formatted URL if "gitCredentials" is defined with "BITBUCKET_TOKEN"', async t => {
test('Return the "https" formatted URL if "gitCredentials" is defined with "BITBUCKET_TOKEN"', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -299,7 +299,7 @@ test('Return the "https" formatted URL if "gitCredentials" is defined with "BITB
);
});
test('Return the "https" formatted URL if "GITHUB_ACTION" is set', async t => {
test('Return the "https" formatted URL if "GITHUB_ACTION" is set', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -312,7 +312,7 @@ test('Return the "https" formatted URL if "GITHUB_ACTION" is set', async t => {
);
});
test('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async t => {
test('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -326,7 +326,7 @@ test('Handle "https" URL with group and subgroup, with "GIT_CREDENTIALS"', async
);
});
test('Handle "git" URL with group and subgroup, with "GIT_CREDENTIALS', async t => {
test('Handle "git" URL with group and subgroup, with "GIT_CREDENTIALS', async (t) => {
const {cwd} = await gitRepo();
t.is(
@@ -340,7 +340,7 @@ test('Handle "git" URL with group and subgroup, with "GIT_CREDENTIALS', async t
);
});
test('Do not add git credential to repositoryUrl if push is allowed', async t => {
test('Do not add git credential to repositoryUrl if push is allowed', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
t.is(
+4 -4
View File
@@ -1,7 +1,7 @@
const test = require('ava');
const getLastRelease = require('../lib/get-last-release');
test('Get the highest non-prerelease valid tag', t => {
test('Get the highest non-prerelease valid tag', (t) => {
const result = getLastRelease({
branch: {
name: 'master',
@@ -18,7 +18,7 @@ test('Get the highest non-prerelease valid tag', t => {
t.deepEqual(result, {version: '2.0.0', gitTag: 'v2.0.0', name: 'v2.0.0', gitHead: 'v2.0.0', channels: undefined});
});
test('Get the highest prerelease valid tag, ignoring other tags = require(other prerelease channels', t => {
test('Get the highest prerelease valid tag, ignoring other tags from other prerelease channels', (t) => {
const result = getLastRelease({
branch: {
name: 'beta',
@@ -43,7 +43,7 @@ test('Get the highest prerelease valid tag, ignoring other tags = require(other
});
});
test('Return empty object if no valid tag is found', t => {
test('Return empty object if no valid tag is found', (t) => {
const result = getLastRelease({
branch: {
name: 'master',
@@ -56,7 +56,7 @@ test('Return empty object if no valid tag is found', t => {
t.deepEqual(result, {});
});
test('Get the highest non-prerelease valid tag before a certain version', t => {
test('Get the highest non-prerelease valid tag before a certain version', (t) => {
const result = getLastRelease(
{
branch: {
+1 -1
View File
@@ -2,7 +2,7 @@ const test = require('ava');
const {spy} = require('sinon');
const getLogger = require('../lib/get-logger');
test('Expose "error", "success" and "log" functions', t => {
test('Expose "error", "success" and "log" functions', (t) => {
const stdout = spy();
const stderr = spy();
const logger = getLogger({stdout: {write: stdout}, stderr: {write: stderr}});
+12 -12
View File
@@ -2,13 +2,13 @@ const test = require('ava');
const {stub} = require('sinon');
const getNextVersion = require('../lib/get-next-version');
test.beforeEach(t => {
test.beforeEach((t) => {
// Stub the logger functions
t.context.log = stub();
t.context.logger = {log: t.context.log};
});
test('Increase version for patch release', t => {
test('Increase version for patch release', (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}]},
@@ -20,7 +20,7 @@ test('Increase version for patch release', t => {
);
});
test('Increase version for minor release', t => {
test('Increase version for minor release', (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}]},
@@ -32,7 +32,7 @@ test('Increase version for minor release', t => {
);
});
test('Increase version for major release', t => {
test('Increase version for major release', (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: [{gitTag: 'v1.0.0', version: '1.0.0', channels: [null]}]},
@@ -44,7 +44,7 @@ test('Increase version for major release', t => {
);
});
test('Return 1.0.0 if there is no previous release', t => {
test('Return 1.0.0 if there is no previous release', (t) => {
t.is(
getNextVersion({
branch: {name: 'master', type: 'release', tags: []},
@@ -56,7 +56,7 @@ test('Return 1.0.0 if there is no previous release', t => {
);
});
test('Increase version for patch release on prerelease branch', t => {
test('Increase version for patch release on prerelease branch', (t) => {
t.is(
getNextVersion({
branch: {
@@ -106,7 +106,7 @@ test('Increase version for patch release on prerelease branch', t => {
);
});
test('Increase version for minor release on prerelease branch', t => {
test('Increase version for minor release on prerelease branch', (t) => {
t.is(
getNextVersion({
branch: {
@@ -156,7 +156,7 @@ test('Increase version for minor release on prerelease branch', t => {
);
});
test('Increase version for major release on prerelease branch', t => {
test('Increase version for major release on prerelease branch', (t) => {
t.is(
getNextVersion({
branch: {
@@ -206,7 +206,7 @@ test('Increase version for major release on prerelease branch', t => {
);
});
test('Return 1.0.0 if there is no previous release on prerelease branch', t => {
test('Return 1.0.0 if there is no previous release on prerelease branch', (t) => {
t.is(
getNextVersion({
branch: {name: 'beta', type: 'prerelease', prerelease: 'beta', tags: []},
@@ -218,7 +218,7 @@ test('Return 1.0.0 if there is no previous release on prerelease branch', t => {
);
});
test('Increase version for release on prerelease branch after previous commits were merged to release branch', t => {
test('Increase version for release on prerelease branch after previous commits were merged to release branch', (t) => {
t.is(
getNextVersion({
branch: {
@@ -239,7 +239,7 @@ test('Increase version for release on prerelease branch after previous commits w
);
});
test('Increase version for release on prerelease branch based on highest commit type since last regular release', t => {
test('Increase version for release on prerelease branch based on highest commit type since last regular release', (t) => {
t.is(
getNextVersion({
branch: {
@@ -259,7 +259,7 @@ test('Increase version for release on prerelease branch based on highest commit
);
});
test('Increase version for release on prerelease branch when there is no regular releases on other branches', t => {
test('Increase version for release on prerelease branch when there is no regular releases on other branches', (t) => {
t.is(
getNextVersion({
branch: {
+9 -9
View File
@@ -1,7 +1,7 @@
const test = require('ava');
const getReleaseToAdd = require('../lib/get-release-to-add');
test('Return versions merged = require(release to maintenance branch, excluding lower than branch start range', t => {
test('Return versions merged from release to maintenance branch, excluding lower than branch start range', (t) => {
const result = getReleaseToAdd({
branch: {
name: '2.x',
@@ -42,7 +42,7 @@ test('Return versions merged = require(release to maintenance branch, excluding
});
});
test('Return versions merged between release branches', t => {
test('Return versions merged between release branches', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
@@ -83,7 +83,7 @@ test('Return versions merged between release branches', t => {
});
});
test('Return releases sorted by ascending order', t => {
test('Return releases sorted by ascending order', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
@@ -118,7 +118,7 @@ test('Return releases sorted by ascending order', t => {
});
});
test('No lastRelease', t => {
test('No lastRelease', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
@@ -149,7 +149,7 @@ test('No lastRelease', t => {
});
});
test('Ignore pre-release versions', t => {
test('Ignore pre-release versions', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
@@ -188,7 +188,7 @@ test('Ignore pre-release versions', t => {
});
});
test('Exclude versions merged = require(release to maintenance branch if they have the same "channel"', t => {
test('Exclude versions merged from release to maintenance branch if they have the same "channel"', (t) => {
const result = getReleaseToAdd({
branch: {
name: '2.x',
@@ -214,7 +214,7 @@ test('Exclude versions merged = require(release to maintenance branch if they ha
t.is(result, undefined);
});
test('Exclude versions merged between release branches if they have the same "channel"', t => {
test('Exclude versions merged between release branches if they have the same "channel"', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
@@ -236,7 +236,7 @@ test('Exclude versions merged between release branches if they have the same "ch
t.is(result, undefined);
});
test('Exclude versions merged between release branches if they all have "channel" set to "false"', t => {
test('Exclude versions merged between release branches if they all have "channel" set to "false"', (t) => {
const result = getReleaseToAdd({
branch: {
name: 'master',
@@ -258,7 +258,7 @@ test('Exclude versions merged between release branches if they all have "channel
t.is(result, undefined);
});
test('Exclude versions number less than the latest version already released on that branch', t => {
test('Exclude versions number less than the latest version already released on that branch', (t) => {
const result = getReleaseToAdd({
branch: {
name: '2.x',
+38 -38
View File
@@ -36,7 +36,7 @@ const {
initGit,
} = require('./helpers/git-utils');
test('Get the last commit sha', async t => {
test('Get the last commit sha', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -47,14 +47,14 @@ test('Get the last commit sha', async t => {
t.is(result, commits[0].hash);
});
test('Throw error if the last commit sha cannot be found', async t => {
test('Throw error if the last commit sha cannot be found', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
await t.throwsAsync(getGitHead({cwd}));
});
test('Unshallow and fetch repository', async t => {
test('Unshallow and fetch repository', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
// Add commits to the master branch
@@ -71,7 +71,7 @@ test('Unshallow and fetch repository', async t => {
t.is((await gitGetCommits(undefined, {cwd})).length, 2);
});
test('Do not throw error when unshallow a complete repository', async t => {
test('Do not throw error when unshallow a complete repository', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
@@ -84,7 +84,7 @@ test('Do not throw error when unshallow a complete repository', async t => {
await t.notThrowsAsync(fetch(repositoryUrl, 'second-branch', 'master', {cwd}));
});
test('Fetch all tags on a detached head repository', async t => {
test('Fetch all tags on a detached head repository', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
@@ -101,7 +101,7 @@ test('Fetch all tags on a detached head repository', async t => {
t.deepEqual((await getTags('master', {cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0'].sort());
});
test('Fetch all tags on a repository with a detached head from branch (CircleCI)', async t => {
test('Fetch all tags on a repository with a detached head from branch (CircleCI)', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
@@ -126,7 +126,7 @@ test('Fetch all tags on a repository with a detached head from branch (CircleCI)
t.deepEqual((await getTags('master', {cwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0', 'v2.0.0'].sort());
});
test('Fetch all tags on a detached head repository with outdated cached repo (GitLab CI)', async t => {
test('Fetch all tags on a detached head repository with outdated cached repo (GitLab CI)', async (t) => {
const {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
@@ -154,7 +154,7 @@ test('Fetch all tags on a detached head repository with outdated cached repo (Gi
t.deepEqual((await getTags('master', {cwd: cloneCwd})).sort(), ['v1.0.0', 'v1.0.1', 'v1.1.0', 'v1.2.0'].sort());
});
test('Verify if a branch exists', async t => {
test('Verify if a branch exists', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -169,7 +169,7 @@ test('Verify if a branch exists', async t => {
t.falsy(await isRefExists('next', {cwd}));
});
test('Get all branches', async t => {
test('Get all branches', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
@@ -183,12 +183,12 @@ test('Get all branches', async t => {
t.deepEqual((await getBranches(repositoryUrl, {cwd})).sort(), ['master', 'second-branch', 'third-branch'].sort());
});
test('Return empty array if there are no branches', async t => {
test('Return empty array if there are no branches', async (t) => {
const {cwd, repositoryUrl} = await initGit(true);
t.deepEqual(await getBranches(repositoryUrl, {cwd}), []);
});
test('Get the commit sha for a given tag', async t => {
test('Get the commit sha for a given tag', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -199,7 +199,7 @@ test('Get the commit sha for a given tag', async t => {
t.is(await getTagHead('v1.0.0', {cwd}), commits[0].hash);
});
test('Return git remote repository url from config', async t => {
test('Return git remote repository url from config', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add remote.origin.url config
@@ -208,7 +208,7 @@ test('Return git remote repository url from config', async t => {
t.is(await repoUrl({cwd}), 'git@hostname.com:owner/package.git');
});
test('Return git remote repository url set while cloning', async t => {
test('Return git remote repository url set while cloning', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
@@ -218,14 +218,14 @@ test('Return git remote repository url set while cloning', async t => {
t.is(await repoUrl({cwd}), repositoryUrl);
});
test('Return falsy if git repository url is not set', async t => {
test('Return falsy if git repository url is not set', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
t.falsy(await repoUrl({cwd}));
});
test('Add tag on head commit', async t => {
test('Add tag on head commit', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
const commits = await gitCommits(['Test commit'], {cwd});
@@ -235,7 +235,7 @@ test('Add tag on head commit', async t => {
await t.is(await gitCommitTag(commits[0].hash, {cwd}), 'tag_name');
});
test('Push tag to remote repository', async t => {
test('Push tag to remote repository', async (t) => {
// Create a git repository with a remote, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
const commits = await gitCommits(['Test commit'], {cwd});
@@ -246,13 +246,13 @@ test('Push tag to remote repository', async t => {
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
});
test('Push tag to remote repository with remote branch ahead', async t => {
test('Push tag to remote repository with remote branch ahead', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const commits = await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
const tmpRepo = await gitShallowClone(repositoryUrl);
await gitCommits(['Second'], {cwd: tmpRepo});
await gitPush('origin', 'master', {cwd: tmpRepo});
const temporaryRepo = await gitShallowClone(repositoryUrl);
await gitCommits(['Second'], {cwd: temporaryRepo});
await gitPush('origin', 'master', {cwd: temporaryRepo});
await tag('tag_name', 'HEAD', {cwd});
await push(repositoryUrl, {cwd});
@@ -260,40 +260,40 @@ test('Push tag to remote repository with remote branch ahead', async t => {
t.is(await gitRemoteTagHead(repositoryUrl, 'tag_name', {cwd}), commits[0].hash);
});
test('Return "true" if in a Git repository', async t => {
test('Return "true" if in a Git repository', async (t) => {
// Create a git repository with a remote, set the current working directory at the root of the repo
const {cwd} = await gitRepo(true);
t.true(await isGitRepo({cwd}));
});
test('Return falsy if not in a Git repository', async t => {
test('Return falsy if not in a Git repository', async (t) => {
const cwd = tempy.directory();
t.falsy(await isGitRepo({cwd}));
});
test('Return "true" for valid tag names', async t => {
test('Return "true" for valid tag names', async (t) => {
t.true(await verifyTagName('1.0.0'));
t.true(await verifyTagName('v1.0.0'));
t.true(await verifyTagName('tag_name'));
t.true(await verifyTagName('tag/name'));
});
test('Return falsy for invalid tag names', async t => {
test('Return falsy for invalid tag names', async (t) => {
t.falsy(await verifyTagName('?1.0.0'));
t.falsy(await verifyTagName('*1.0.0'));
t.falsy(await verifyTagName('[1.0.0]'));
t.falsy(await verifyTagName('1.0.0..'));
});
test('Throws error if obtaining the tags fails', async t => {
test('Throws error if obtaining the tags fails', async (t) => {
const cwd = tempy.directory();
await t.throwsAsync(getTags('master', {cwd}));
});
test('Return "true" if repository is up to date', async t => {
test('Return "true" if repository is up to date', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitPush(repositoryUrl, 'master', {cwd});
@@ -301,7 +301,7 @@ test('Return "true" if repository is up to date', async t => {
t.true(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
});
test('Return falsy if repository is not up to date', async t => {
test('Return falsy if repository is not up to date', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitCommits(['Second'], {cwd});
@@ -309,14 +309,14 @@ test('Return falsy if repository is not up to date', async t => {
t.true(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
const tmpRepo = await gitShallowClone(repositoryUrl);
await gitCommits(['Third'], {cwd: tmpRepo});
await gitPush('origin', 'master', {cwd: tmpRepo});
const temporaryRepo = await gitShallowClone(repositoryUrl);
await gitCommits(['Third'], {cwd: temporaryRepo});
await gitPush('origin', 'master', {cwd: temporaryRepo});
t.falsy(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
});
test('Return falsy if detached head repository is not up to date', async t => {
test('Return falsy if detached head repository is not up to date', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
const [commit] = await gitCommits(['First'], {cwd});
@@ -328,7 +328,7 @@ test('Return falsy if detached head repository is not up to date', async t => {
t.falsy(await isBranchUpToDate(repositoryUrl, 'master', {cwd}));
});
test('Get a commit note', async t => {
test('Get a commit note', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -339,7 +339,7 @@ test('Get a commit note', async t => {
t.deepEqual(await getNote(commits[0].hash, {cwd}), {note: 'note'});
});
test('Return empty object if there is no commit note', async t => {
test('Return empty object if there is no commit note', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -348,7 +348,7 @@ test('Return empty object if there is no commit note', async t => {
t.deepEqual(await getNote(commits[0].hash, {cwd}), {});
});
test('Throw error if a commit note in invalid', async t => {
test('Throw error if a commit note in invalid', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -359,7 +359,7 @@ test('Throw error if a commit note in invalid', async t => {
await t.throwsAsync(getNote(commits[0].hash, {cwd}));
});
test('Add a commit note', async t => {
test('Add a commit note', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -370,7 +370,7 @@ test('Add a commit note', async t => {
t.is(await gitGetNote(commits[0].hash, {cwd}), '{"note":"note"}');
});
test('Overwrite a commit note', async t => {
test('Overwrite a commit note', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Add commits to the master branch
@@ -382,7 +382,7 @@ test('Overwrite a commit note', async t => {
t.is(await gitGetNote(commits[0].hash, {cwd}), '{"note":"note2"}');
});
test('Unshallow and fetch repository with notes', async t => {
test('Unshallow and fetch repository with notes', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo();
// Add commits to the master branch
@@ -401,7 +401,7 @@ test('Unshallow and fetch repository with notes', async t => {
t.is(await gitGetNote(commits[0].hash, {cwd}), '{"note":"note"}');
});
test('Fetch all notes on a detached head repository', async t => {
test('Fetch all notes on a detached head repository', async (t) => {
let {cwd, repositoryUrl} = await gitRepo();
await gitCommits(['First'], {cwd});
+40 -36
View File
@@ -82,12 +82,13 @@ async function initBareRepo(repositoryUrl, branch = 'master') {
*
* @returns {Array<Commit>} The created commits, in reverse order (to match `git log` order).
*/
async function gitCommits(messages, execaOpts) {
async function gitCommits(messages, execaOptions) {
await pEachSeries(
messages,
async message => (await execa('git', ['commit', '-m', message, '--allow-empty', '--no-gpg-sign'], execaOpts)).stdout
async (message) =>
(await execa('git', ['commit', '-m', message, '--allow-empty', '--no-gpg-sign'], execaOptions)).stdout
);
return (await gitGetCommits(undefined, execaOpts)).slice(0, messages.length);
return (await gitGetCommits(undefined, execaOptions)).slice(0, messages.length);
}
/**
@@ -98,13 +99,16 @@ async function gitCommits(messages, execaOpts) {
*
* @return {Array<Object>} The list of parsed commits.
*/
async function gitGetCommits(from, execaOpts) {
async function gitGetCommits(from, execaOptions) {
Object.assign(gitLogParser.fields, {hash: 'H', message: 'B', gitTags: 'd', committerDate: {key: 'ci', type: Date}});
return (
await getStream.array(
gitLogParser.parse({_: `${from ? from + '..' : ''}HEAD`}, {...execaOpts, env: {...process.env, ...execaOpts.env}})
gitLogParser.parse(
{_: `${from ? from + '..' : ''}HEAD`},
{...execaOptions, env: {...process.env, ...execaOptions.env}}
)
)
).map(commit => {
).map((commit) => {
commit.message = commit.message.trim();
commit.gitTags = commit.gitTags.trim();
return commit;
@@ -118,8 +122,8 @@ async function gitGetCommits(from, execaOpts) {
* @param {Boolean} create to create the branch, `false` to checkout an existing branch.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitCheckout(branch, create, execaOpts) {
await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch], execaOpts);
async function gitCheckout(branch, create, execaOptions) {
await execa('git', create ? ['checkout', '-b', branch] : ['checkout', branch], execaOptions);
}
/**
@@ -128,8 +132,8 @@ async function gitCheckout(branch, create, execaOpts) {
* @param {String} repositoryUrl The repository remote URL.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitFetch(repositoryUrl, execaOpts) {
await execa('git', ['fetch', repositoryUrl], execaOpts);
async function gitFetch(repositoryUrl, execaOptions) {
await execa('git', ['fetch', repositoryUrl], execaOptions);
}
/**
@@ -139,8 +143,8 @@ async function gitFetch(repositoryUrl, execaOpts) {
*
* @return {String} The sha of the head commit in the current git repository.
*/
async function gitHead(execaOpts) {
return (await execa('git', ['rev-parse', 'HEAD'], execaOpts)).stdout;
async function gitHead(execaOptions) {
return (await execa('git', ['rev-parse', 'HEAD'], execaOptions)).stdout;
}
/**
@@ -150,8 +154,8 @@ async function gitHead(execaOpts) {
* @param {String} [sha] The commit on which to create the tag. If undefined the tag is created on the last commit.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitTagVersion(tagName, sha, execaOpts) {
await execa('git', sha ? ['tag', '-f', tagName, sha] : ['tag', tagName], execaOpts);
async function gitTagVersion(tagName, sha, execaOptions) {
await execa('git', sha ? ['tag', '-f', tagName, sha] : ['tag', tagName], execaOptions);
}
/**
@@ -207,8 +211,8 @@ async function gitDetachedHeadFromBranch(repositoryUrl, branch, head) {
* @param {String} value Config value.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitAddConfig(name, value, execaOpts) {
await execa('git', ['config', '--add', name, value], execaOpts);
async function gitAddConfig(name, value, execaOptions) {
await execa('git', ['config', '--add', name, value], execaOptions);
}
/**
@@ -219,8 +223,8 @@ async function gitAddConfig(name, value, execaOpts) {
*
* @return {String} The sha of the commit associated with `tagName` on the local repository.
*/
async function gitTagHead(tagName, execaOpts) {
return (await execa('git', ['rev-list', '-1', tagName], execaOpts)).stdout;
async function gitTagHead(tagName, execaOptions) {
return (await execa('git', ['rev-list', '-1', tagName], execaOptions)).stdout;
}
/**
@@ -232,11 +236,11 @@ async function gitTagHead(tagName, execaOpts) {
*
* @return {String} The sha of the commit associated with `tagName` on the remote repository.
*/
async function gitRemoteTagHead(repositoryUrl, tagName, execaOpts) {
return (await execa('git', ['ls-remote', '--tags', repositoryUrl, tagName], execaOpts)).stdout
async function gitRemoteTagHead(repositoryUrl, tagName, execaOptions) {
return (await execa('git', ['ls-remote', '--tags', repositoryUrl, tagName], execaOptions)).stdout
.split('\n')
.filter(tag => Boolean(tag))
.map(tag => tag.match(/^(?<tag>\S+)/)[1])[0];
.filter((tag) => Boolean(tag))
.map((tag) => tag.match(/^(?<tag>\S+)/)[1])[0];
}
/**
@@ -247,8 +251,8 @@ async function gitRemoteTagHead(repositoryUrl, tagName, execaOpts) {
*
* @return {String} The tag associatedwith the sha in parameter or `null`.
*/
async function gitCommitTag(gitHead, execaOpts) {
return (await execa('git', ['describe', '--tags', '--exact-match', gitHead], execaOpts)).stdout;
async function gitCommitTag(gitHead, execaOptions) {
return (await execa('git', ['describe', '--tags', '--exact-match', gitHead], execaOptions)).stdout;
}
/**
@@ -260,8 +264,8 @@ async function gitCommitTag(gitHead, execaOpts) {
*
* @throws {Error} if the push failed.
*/
async function gitPush(repositoryUrl, branch, execaOpts) {
await execa('git', ['push', '--tags', repositoryUrl, `HEAD:${branch}`], execaOpts);
async function gitPush(repositoryUrl, branch, execaOptions) {
await execa('git', ['push', '--tags', repositoryUrl, `HEAD:${branch}`], execaOptions);
}
/**
@@ -270,8 +274,8 @@ async function gitPush(repositoryUrl, branch, execaOpts) {
* @param {String} ref The ref to merge.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function merge(ref, execaOpts) {
await execa('git', ['merge', '--no-ff', ref], execaOpts);
async function merge(ref, execaOptions) {
await execa('git', ['merge', '--no-ff', ref], execaOptions);
}
/**
@@ -280,8 +284,8 @@ async function merge(ref, execaOpts) {
* @param {String} ref The ref to merge.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function mergeFf(ref, execaOpts) {
await execa('git', ['merge', '--ff', ref], execaOpts);
async function mergeFf(ref, execaOptions) {
await execa('git', ['merge', '--ff', ref], execaOptions);
}
/**
@@ -290,8 +294,8 @@ async function mergeFf(ref, execaOpts) {
* @param {String} ref The ref to merge.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function rebase(ref, execaOpts) {
await execa('git', ['rebase', ref], execaOpts);
async function rebase(ref, execaOptions) {
await execa('git', ['rebase', ref], execaOptions);
}
/**
@@ -301,8 +305,8 @@ async function rebase(ref, execaOpts) {
* @param {String} ref The ref to add the note to.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitAddNote(note, ref, execaOpts) {
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-m', note, ref], execaOpts);
async function gitAddNote(note, ref, execaOptions) {
await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'add', '-m', note, ref], execaOptions);
}
/**
@@ -311,8 +315,8 @@ async function gitAddNote(note, ref, execaOpts) {
* @param {String} ref The ref to get the note from.
* @param {Object} [execaOpts] Options to pass to `execa`.
*/
async function gitGetNote(ref, execaOpts) {
return (await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOpts)).stdout;
async function gitGetNote(ref, execaOptions) {
return (await execa('git', ['notes', '--ref', GIT_NOTE_REF, 'show', ref], execaOptions)).stdout;
}
module.exports = {
+8 -8
View File
@@ -3,7 +3,7 @@ const {repeat} = require('lodash');
const hideSensitive = require('../lib/hide-sensitive');
const {SECRET_REPLACEMENT, SECRET_MIN_SIZE} = require('../lib/definitions/constants');
test('Replace multiple sensitive environment variable values', t => {
test('Replace multiple sensitive environment variable values', (t) => {
const env = {SOME_PASSWORD: 'password', SOME_TOKEN: 'secret'};
t.is(
hideSensitive(env)(`https://user:${env.SOME_PASSWORD}@host.com?token=${env.SOME_TOKEN}`),
@@ -11,7 +11,7 @@ test('Replace multiple sensitive environment variable values', t => {
);
});
test('Replace multiple occurences of sensitive environment variable values', t => {
test('Replace multiple occurences of sensitive environment variable values', (t) => {
const env = {secretKey: 'secret'};
t.is(
hideSensitive(env)(`https://user:${env.secretKey}@host.com?token=${env.secretKey}`),
@@ -19,7 +19,7 @@ test('Replace multiple occurences of sensitive environment variable values', t =
);
});
test('Escape regexp special characters', t => {
test('Escape regexp special characters', (t) => {
const env = {SOME_CREDENTIALS: 'p$^{.+}\\w[a-z]o.*rd'};
t.is(
hideSensitive(env)(`https://user:${env.SOME_CREDENTIALS}@host.com`),
@@ -27,15 +27,15 @@ test('Escape regexp special characters', t => {
);
});
test('Accept "undefined" input', t => {
test('Accept "undefined" input', (t) => {
t.is(hideSensitive({})(), undefined);
});
test('Return same string if no environment variable has to be replaced', t => {
test('Return same string if no environment variable has to be replaced', (t) => {
t.is(hideSensitive({})('test'), 'test');
});
test('Exclude empty environment variables from the regexp', t => {
test('Exclude empty environment variables from the regexp', (t) => {
const env = {SOME_PASSWORD: 'password', SOME_TOKEN: ''};
t.is(
hideSensitive(env)(`https://user:${env.SOME_PASSWORD}@host.com?token=`),
@@ -43,11 +43,11 @@ test('Exclude empty environment variables from the regexp', t => {
);
});
test('Exclude empty environment variables from the regexp if there is only empty ones', t => {
test('Exclude empty environment variables from the regexp if there is only empty ones', (t) => {
t.is(hideSensitive({SOME_PASSWORD: '', SOME_TOKEN: ' \n '})(`https://host.com?token=`), 'https://host.com?token=');
});
test('Exclude environment variables with value shorter than SECRET_MIN_SIZE from the regexp', t => {
test('Exclude environment variables with value shorter than SECRET_MIN_SIZE from the regexp', (t) => {
const SHORT_TOKEN = repeat('a', SECRET_MIN_SIZE - 1);
const LONG_TOKEN = repeat('b', SECRET_MIN_SIZE);
const env = {SHORT_TOKEN, LONG_TOKEN};
+36 -36
View File
@@ -26,7 +26,7 @@ const {
const requireNoCache = proxyquire.noPreserveCache();
const pluginNoop = require.resolve('./fixtures/plugin-noop');
test.beforeEach(t => {
test.beforeEach((t) => {
// Stub the logger functions
t.context.log = spy();
t.context.error = spy();
@@ -41,7 +41,7 @@ test.beforeEach(t => {
};
});
test('Plugins are called with expected values', async t => {
test('Plugins are called with expected values', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -390,7 +390,7 @@ test('Plugins are called with expected values', async t => {
t.is(env.GIT_COMMITTER_EMAIL, COMMIT_EMAIL);
});
test('Use custom tag format', async t => {
test('Use custom tag format', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitTagVersion('test-1.0.0', undefined, {cwd});
@@ -437,7 +437,7 @@ test('Use custom tag format', async t => {
t.is(await gitRemoteTagHead(repositoryUrl, nextRelease.gitTag, {cwd}), nextRelease.gitHead);
});
test('Use new gitHead, and recreate release notes if a prepare plugin create a commit', async t => {
test('Use new gitHead, and recreate release notes if a prepare plugin create a commit', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -511,7 +511,7 @@ test('Use new gitHead, and recreate release notes if a prepare plugin create a c
t.is(await gitRemoteTagHead(repositoryUrl, nextRelease.gitTag, {cwd}), commits[0].hash);
});
test('Make a new release when a commit is forward-ported to an upper branch', async t => {
test('Make a new release when a commit is forward-ported to an upper branch', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial release'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -558,7 +558,7 @@ test('Make a new release when a commit is forward-ported to an upper branch', as
t.is(success.callCount, 1);
});
test('Publish a pre-release version', async t => {
test('Publish a pre-release version', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial commit'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -605,7 +605,7 @@ test('Publish a pre-release version', async t => {
t.is(await gitGetNote('v1.1.0-beta.2', {cwd}), '{"channels":["beta"]}');
});
test('Publish releases from different branch on the same channel', async t => {
test('Publish releases from different branch on the same channel', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial commit'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -668,7 +668,7 @@ test('Publish releases from different branch on the same channel', async t => {
t.is(addChannel.callCount, 0);
});
test('Publish pre-releases the same channel as regular releases', async t => {
test('Publish pre-releases the same channel as regular releases', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial commit'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -716,7 +716,7 @@ test('Publish pre-releases the same channel as regular releases', async t => {
t.is(releases[0].gitTag, 'v1.1.0-beta.2');
});
test('Do not add pre-releases to a different channel', async t => {
test('Do not add pre-releases to a different channel', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial release'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -844,13 +844,13 @@ async function addChannelMacro(t, mergeFunction) {
t.is(await gitRemoteTagHead(repositoryUrl, nextRelease.gitTag, {cwd}), nextRelease.gitHead);
}
addChannelMacro.title = providedTitle => `Add version to a channel after a merge (${providedTitle})`;
addChannelMacro.title = (providedTitle) => `Add version to a channel after a merge (${providedTitle})`;
test('fast-forward', addChannelMacro, mergeFf);
test('non fast-forward', addChannelMacro, merge);
test('rebase', addChannelMacro, rebase);
test('Call all "success" plugins even if one errors out', async t => {
test('Call all "success" plugins even if one errors out', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -916,7 +916,7 @@ test('Call all "success" plugins even if one errors out', async t => {
]);
});
test('Log all "verifyConditions" errors', async t => {
test('Log all "verifyConditions" errors', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -957,7 +957,7 @@ test('Log all "verifyConditions" errors', async t => {
t.deepEqual(fail.args[0][1].errors, [error2, error3]);
});
test('Log all "verifyRelease" errors', async t => {
test('Log all "verifyRelease" errors', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -998,7 +998,7 @@ test('Log all "verifyRelease" errors', async t => {
t.deepEqual(fail.args[0][1].errors, [error1, error2]);
});
test('Dry-run skips addChannel, prepare, publish and success', async t => {
test('Dry-run skips addChannel, prepare, publish and success', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -1064,7 +1064,7 @@ test('Dry-run skips addChannel, prepare, publish and success', async t => {
t.true(t.context.warn.calledWith(`Skip step "success" of plugin "[Function: ${success.name}]" in dry-run mode`));
});
test('Dry-run skips fail', async t => {
test('Dry-run skips fail', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -1104,7 +1104,7 @@ test('Dry-run skips fail', async t => {
t.true(t.context.warn.calledWith(`Skip step "fail" of plugin "[Function: ${fail.name}]" in dry-run mode`));
});
test('Force a dry-run if not on a CI and "noCi" is not explicitly set', async t => {
test('Force a dry-run if not on a CI and "noCi" is not explicitly set', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -1169,7 +1169,7 @@ test('Force a dry-run if not on a CI and "noCi" is not explicitly set', async t
t.is(success.callCount, 0);
});
test('Dry-run does not print changelog if "generateNotes" return "undefined"', async t => {
test('Dry-run does not print changelog if "generateNotes" return "undefined"', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -1213,7 +1213,7 @@ test('Dry-run does not print changelog if "generateNotes" return "undefined"', a
t.deepEqual(t.context.log.args[t.context.log.args.length - 1], ['Release note for version 2.0.0:']);
});
test('Allow local releases with "noCi" option', async t => {
test('Allow local releases with "noCi" option', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -1282,7 +1282,7 @@ test('Allow local releases with "noCi" option', async t => {
t.is(success.callCount, 1);
});
test('Accept "undefined" value returned by "generateNotes" and "false" by "publish" and "addChannel"', async t => {
test('Accept "undefined" value returned by "generateNotes" and "false" by "publish" and "addChannel"', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -1351,7 +1351,7 @@ test('Accept "undefined" value returned by "generateNotes" and "false" by "publi
t.deepEqual(success.args[1][1].releases, [{pluginName: '[Function: functionStub]'}]);
});
test('Returns false if triggered by a PR', async t => {
test('Returns false if triggered by a PR', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
@@ -1372,7 +1372,7 @@ test('Returns false if triggered by a PR', async t => {
);
});
test('Throws "EINVALIDNEXTVERSION" if next release is out of range of the current maintenance branch', async t => {
test('Throws "EINVALIDNEXTVERSION" if next release is out of range of the current maintenance branch', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial commit'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -1423,7 +1423,7 @@ test('Throws "EINVALIDNEXTVERSION" if next release is out of range of the curren
t.regex(error.details, /A valid branch could be `master`./);
});
test('Throws "EINVALIDNEXTVERSION" if next release is out of range of the current release branch', async t => {
test('Throws "EINVALIDNEXTVERSION" if next release is out of range of the current release branch', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial commit'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -1475,7 +1475,7 @@ test('Throws "EINVALIDNEXTVERSION" if next release is out of range of the curren
t.regex(error.details, /A valid branch could be `next` or `next-major`./);
});
test('Throws "EINVALIDMAINTENANCEMERGE" if merge an out of range release in a maintenance branch', async t => {
test('Throws "EINVALIDMAINTENANCEMERGE" if merge an out of range release in a maintenance branch', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['First'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -1545,7 +1545,7 @@ test('Throws "EINVALIDMAINTENANCEMERGE" if merge an out of range release in a ma
t.truthy(errors[0].details);
});
test('Returns false value if triggered on an outdated clone', async t => {
test('Returns false value if triggered on an outdated clone', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
let {cwd, repositoryUrl} = await gitRepo(true);
const repoDir = cwd;
@@ -1573,7 +1573,7 @@ test('Returns false value if triggered on an outdated clone', async t => {
]);
});
test('Returns false if not running from the configured branch', async t => {
test('Returns false if not running from the configured branch', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {
@@ -1609,7 +1609,7 @@ test('Returns false if not running from the configured branch', async t => {
);
});
test('Returns false if there is no relevant changes', async t => {
test('Returns false if there is no relevant changes', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -1658,7 +1658,7 @@ test('Returns false if there is no relevant changes', async t => {
);
});
test('Exclude commits with [skip release] or [release skip] from analysis', async t => {
test('Exclude commits with [skip release] or [release skip] from analysis', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -1707,7 +1707,7 @@ test('Exclude commits with [skip release] or [release skip] from analysis', asyn
t.deepEqual(analyzeCommits.args[0][1].commits[0], commits[commits.length - 1]);
});
test('Log both plugins errors and errors thrown by "fail" plugin', async t => {
test('Log both plugins errors and errors thrown by "fail" plugin', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const pluginError = new SemanticReleaseError('Plugin error', 'ERR');
const failError1 = new Error('Fail error 1');
@@ -1733,7 +1733,7 @@ test('Log both plugins errors and errors thrown by "fail" plugin', async t => {
t.is(t.context.error.args[t.context.error.args.length - 2][1], failError2);
});
test('Call "fail" only if a plugin returns a SemanticReleaseError', async t => {
test('Call "fail" only if a plugin returns a SemanticReleaseError', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const pluginError = new Error('Plugin error');
const fail = stub().resolves();
@@ -1757,7 +1757,7 @@ test('Call "fail" only if a plugin returns a SemanticReleaseError', async t => {
t.is(t.context.error.args[t.context.error.args.length - 1][1], pluginError);
});
test('Throw SemanticReleaseError if repositoryUrl is not set and cannot be found from repo config', async t => {
test('Throw SemanticReleaseError if repositoryUrl is not set and cannot be found from repo config', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
@@ -1778,7 +1778,7 @@ test('Throw SemanticReleaseError if repositoryUrl is not set and cannot be found
t.truthy(errors[0].details);
});
test('Throw an Error if plugin returns an unexpected value', async t => {
test('Throw an Error if plugin returns an unexpected value', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd, repositoryUrl} = await gitRepo(true);
// Add commits to the master branch
@@ -1812,7 +1812,7 @@ test('Throw an Error if plugin returns an unexpected value', async t => {
t.regex(error.details, /string/);
});
test('Hide sensitive information passed to "fail" plugin', async t => {
test('Hide sensitive information passed to "fail" plugin', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const fail = stub().resolves();
@@ -1844,14 +1844,14 @@ test('Hide sensitive information passed to "fail" plugin', async t => {
t.is(error.message, `Message: Exposing token ${SECRET_REPLACEMENT}`);
t.is(error.details, `Details: Exposing token ${SECRET_REPLACEMENT}`);
Object.getOwnPropertyNames(error).forEach(prop => {
Object.getOwnPropertyNames(error).forEach((prop) => {
if (isString(error[prop])) {
t.notRegex(error[prop], new RegExp(escapeRegExp(env.MY_TOKEN)));
}
});
});
test('Hide sensitive information passed to "success" plugin', async t => {
test('Hide sensitive information passed to "success" plugin', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
await gitCommits(['feat: initial release'], {cwd});
await gitTagVersion('v1.0.0', undefined, {cwd});
@@ -1887,14 +1887,14 @@ test('Hide sensitive information passed to "success" plugin', async t => {
t.is(release.name, `Name: Exposing token ${SECRET_REPLACEMENT}`);
t.is(release.url, `URL: Exposing token ${SECRET_REPLACEMENT}`);
Object.getOwnPropertyNames(release).forEach(prop => {
Object.getOwnPropertyNames(release).forEach((prop) => {
if (isString(release[prop])) {
t.notRegex(release[prop], new RegExp(escapeRegExp(env.MY_TOKEN)));
}
});
});
test('Get all commits including the ones not in the shallow clone', async t => {
test('Get all commits including the ones not in the shallow clone', async (t) => {
let {cwd, repositoryUrl} = await gitRepo(true);
await gitTagVersion('v1.0.0', undefined, {cwd});
await gitCommits(['First', 'Second', 'Third'], {cwd});
+12 -12
View File
@@ -58,7 +58,7 @@ test.after.always(async () => {
await Promise.all([gitbox.stop(), npmRegistry.stop(), mockServer.stop()]);
});
test('Release patch, minor and major versions', async t => {
test('Release patch, minor and major versions', async (t) => {
const packageName = 'test-release';
const owner = 'git';
// Create a git repository, set the current working directory at the root of the repo
@@ -304,7 +304,7 @@ test('Release patch, minor and major versions', async t => {
await mockServer.verify(updateReleaseMock);
});
test('Exit with 1 if a plugin is not found', async t => {
test('Exit with 1 if a plugin is not found', async (t) => {
const packageName = 'test-plugin-not-found';
const owner = 'test-repo';
// Create a git repository, set the current working directory at the root of the repo
@@ -322,7 +322,7 @@ test('Exit with 1 if a plugin is not found', async t => {
t.regex(stderr, /Cannot find module/);
});
test('Exit with 1 if a shareable config is not found', async t => {
test('Exit with 1 if a shareable config is not found', async (t) => {
const packageName = 'test-config-not-found';
const owner = 'test-repo';
// Create a git repository, set the current working directory at the root of the repo
@@ -340,7 +340,7 @@ test('Exit with 1 if a shareable config is not found', async t => {
t.regex(stderr, /Cannot find module/);
});
test('Exit with 1 if a shareable config reference a not found plugin', async t => {
test('Exit with 1 if a shareable config reference a not found plugin', async (t) => {
const packageName = 'test-config-ref-not-found';
const owner = 'test-repo';
const shareable = {analyzeCommits: 'non-existing-path'};
@@ -361,7 +361,7 @@ test('Exit with 1 if a shareable config reference a not found plugin', async t =
t.regex(stderr, /Cannot find module/);
});
test('Dry-run', async t => {
test('Dry-run', async (t) => {
const packageName = 'test-dry-run';
const owner = 'git';
// Create a git repository, set the current working directory at the root of the repo
@@ -397,7 +397,7 @@ test('Dry-run', async t => {
await mockServer.verify(verifyMock);
});
test('Allow local releases with "noCi" option', async t => {
test('Allow local releases with "noCi" option', async (t) => {
const envNoCi = {...env};
delete envNoCi.TRAVIS;
delete envNoCi.CI;
@@ -456,7 +456,7 @@ test('Allow local releases with "noCi" option', async t => {
await mockServer.verify(createReleaseMock);
});
test('Pass options via CLI arguments', async t => {
test('Pass options via CLI arguments', async (t) => {
const packageName = 'test-cli';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
@@ -505,7 +505,7 @@ test('Pass options via CLI arguments', async t => {
t.log(`+ released ${releasedVersion} with head ${releasedGitHead}`);
});
test('Run via JS API', async t => {
test('Run via JS API', async (t) => {
const semanticRelease = requireNoCache('..', {
'./lib/logger': {log: () => {}, error: () => {}, stdout: () => {}},
'env-ci': () => ({isCi: true, branch: 'master', isPr: false}),
@@ -564,7 +564,7 @@ test('Run via JS API', async t => {
await mockServer.verify(createReleaseMock);
});
test('Log unexpected errors from plugins and exit with 1', async t => {
test('Log unexpected errors from plugins and exit with 1', async (t) => {
const packageName = 'test-unexpected-error';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
@@ -591,7 +591,7 @@ test('Log unexpected errors from plugins and exit with 1', async t => {
t.is(exitCode, 1);
});
test('Log errors inheriting SemanticReleaseError and exit with 1', async t => {
test('Log errors inheriting SemanticReleaseError and exit with 1', async (t) => {
const packageName = 'test-inherited-error';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository and package.json');
@@ -614,7 +614,7 @@ test('Log errors inheriting SemanticReleaseError and exit with 1', async t => {
t.is(exitCode, 1);
});
test('Exit with 1 if missing permission to push to the remote repository', async t => {
test('Exit with 1 if missing permission to push to the remote repository', async (t) => {
const packageName = 'unauthorized';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository');
@@ -636,7 +636,7 @@ test('Exit with 1 if missing permission to push to the remote repository', async
t.is(exitCode, 1);
});
test('Hide sensitive environment variable values from the logs', async t => {
test('Hide sensitive environment variable values from the logs', async (t) => {
const packageName = 'log-secret';
// Create a git repository, set the current working directory at the root of the repo
t.log('Create git repository');
+22 -22
View File
@@ -5,7 +5,7 @@ const normalize = require('../../lib/plugins/normalize');
const cwd = process.cwd();
test.beforeEach(t => {
test.beforeEach((t) => {
// Stub the logger functions
t.context.log = stub();
t.context.error = stub();
@@ -19,7 +19,7 @@ test.beforeEach(t => {
};
});
test('Normalize and load plugin from string', t => {
test('Normalize and load plugin from string', (t) => {
const plugin = normalize(
{cwd, options: {}, logger: t.context.logger},
'verifyConditions',
@@ -32,7 +32,7 @@ test('Normalize and load plugin from string', t => {
t.deepEqual(t.context.success.args[0], ['Loaded plugin "verifyConditions" from "./test/fixtures/plugin-noop"']);
});
test('Normalize and load plugin from object', t => {
test('Normalize and load plugin from object', (t) => {
const plugin = normalize(
{cwd, options: {}, logger: t.context.logger},
'publish',
@@ -45,7 +45,7 @@ test('Normalize and load plugin from object', t => {
t.deepEqual(t.context.success.args[0], ['Loaded plugin "publish" from "./test/fixtures/plugin-noop"']);
});
test('Normalize and load plugin from a base file path', t => {
test('Normalize and load plugin from a base file path', (t) => {
const plugin = normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-noop', {
'./plugin-noop': './test/fixtures',
});
@@ -57,7 +57,7 @@ test('Normalize and load plugin from a base file path', t => {
]);
});
test('Wrap plugin in a function that add the "pluginName" to the error"', async t => {
test('Wrap plugin in a function that add the "pluginName" to the error"', async (t) => {
const plugin = normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-error', {
'./plugin-error': './test/fixtures',
});
@@ -67,7 +67,7 @@ test('Wrap plugin in a function that add the "pluginName" to the error"', async
t.is(error.pluginName, './plugin-error');
});
test('Wrap plugin in a function that add the "pluginName" to multiple errors"', async t => {
test('Wrap plugin in a function that add the "pluginName" to multiple errors"', async (t) => {
const plugin = normalize({cwd, options: {}, logger: t.context.logger}, 'verifyConditions', './plugin-errors', {
'./plugin-errors': './test/fixtures',
});
@@ -78,7 +78,7 @@ test('Wrap plugin in a function that add the "pluginName" to multiple errors"',
}
});
test('Normalize and load plugin from function', t => {
test('Normalize and load plugin from function', (t) => {
const pluginFunction = () => {};
const plugin = normalize({cwd, options: {}, logger: t.context.logger}, '', pluginFunction, {});
@@ -86,7 +86,7 @@ test('Normalize and load plugin from function', t => {
t.is(typeof plugin, 'function');
});
test('Normalize and load plugin that retuns multiple functions', t => {
test('Normalize and load plugin that retuns multiple functions', (t) => {
const plugin = normalize(
{cwd, options: {}, logger: t.context.logger},
'verifyConditions',
@@ -98,7 +98,7 @@ test('Normalize and load plugin that retuns multiple functions', t => {
t.deepEqual(t.context.success.args[0], ['Loaded plugin "verifyConditions" from "./test/fixtures/multi-plugin"']);
});
test('Wrap "analyzeCommits" plugin in a function that validate the output of the plugin', async t => {
test('Wrap "analyzeCommits" plugin in a function that validate the output of the plugin', async (t) => {
const analyzeCommits = stub().resolves(2);
const plugin = normalize(
{cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger},
@@ -116,7 +116,7 @@ test('Wrap "analyzeCommits" plugin in a function that validate the output of the
t.regex(error.details, /2/);
});
test('Wrap "generateNotes" plugin in a function that validate the output of the plugin', async t => {
test('Wrap "generateNotes" plugin in a function that validate the output of the plugin', async (t) => {
const generateNotes = stub().resolves(2);
const plugin = normalize(
{cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger},
@@ -134,7 +134,7 @@ test('Wrap "generateNotes" plugin in a function that validate the output of the
t.regex(error.details, /2/);
});
test('Wrap "publish" plugin in a function that validate the output of the plugin', async t => {
test('Wrap "publish" plugin in a function that validate the output of the plugin', async (t) => {
const publish = stub().resolves(2);
const plugin = normalize(
{cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger},
@@ -152,7 +152,7 @@ test('Wrap "publish" plugin in a function that validate the output of the plugin
t.regex(error.details, /2/);
});
test('Wrap "addChannel" plugin in a function that validate the output of the plugin', async t => {
test('Wrap "addChannel" plugin in a function that validate the output of the plugin', async (t) => {
const addChannel = stub().resolves(2);
const plugin = normalize(
{cwd, options: {}, stderr: t.context.stderr, logger: t.context.logger},
@@ -170,7 +170,7 @@ test('Wrap "addChannel" plugin in a function that validate the output of the plu
t.regex(error.details, /2/);
});
test('Plugin is called with "pluginConfig" (with object definition) and input', async t => {
test('Plugin is called with "pluginConfig" (with object definition) and input', async (t) => {
const pluginFunction = stub().resolves();
const pluginConf = {path: pluginFunction, conf: 'confValue'};
const options = {global: 'globalValue'};
@@ -185,7 +185,7 @@ test('Plugin is called with "pluginConfig" (with object definition) and input',
);
});
test('Plugin is called with "pluginConfig" (with array definition) and input', async t => {
test('Plugin is called with "pluginConfig" (with array definition) and input', async (t) => {
const pluginFunction = stub().resolves();
const pluginConf = [pluginFunction, {conf: 'confValue'}];
const options = {global: 'globalValue'};
@@ -200,8 +200,8 @@ test('Plugin is called with "pluginConfig" (with array definition) and input', a
);
});
test('Prevent plugins to modify "pluginConfig"', async t => {
const pluginFunction = stub().callsFake(pluginConfig => {
test('Prevent plugins to modify "pluginConfig"', async (t) => {
const pluginFunction = stub().callsFake((pluginConfig) => {
pluginConfig.conf.subConf = 'otherConf';
});
const pluginConf = {path: pluginFunction, conf: {subConf: 'originalConf'}};
@@ -213,7 +213,7 @@ test('Prevent plugins to modify "pluginConfig"', async t => {
t.is(options.globalConf.globalSubConf, 'originalGlobalConf');
});
test('Prevent plugins to modify its input', async t => {
test('Prevent plugins to modify its input', async (t) => {
const pluginFunction = stub().callsFake((pluginConfig, options) => {
options.param.subParam = 'otherParam';
});
@@ -224,13 +224,13 @@ test('Prevent plugins to modify its input', async t => {
t.is(input.param.subParam, 'originalSubParam');
});
test('Return noop if the plugin is not defined', t => {
test('Return noop if the plugin is not defined', (t) => {
const plugin = normalize({cwd, options: {}, logger: t.context.logger});
t.is(plugin, noop);
});
test('Always pass a defined "pluginConfig" for plugin defined with string', async t => {
test('Always pass a defined "pluginConfig" for plugin defined with string', async (t) => {
// Call the normalize function with the path of a plugin that returns its config
const plugin = normalize(
{cwd, options: {}, logger: t.context.logger},
@@ -243,7 +243,7 @@ test('Always pass a defined "pluginConfig" for plugin defined with string', asyn
t.deepEqual(pluginResult.pluginConfig, {});
});
test('Always pass a defined "pluginConfig" for plugin defined with path', async t => {
test('Always pass a defined "pluginConfig" for plugin defined with path', async (t) => {
// Call the normalize function with the path of a plugin that returns its config
const plugin = normalize(
{cwd, options: {}, logger: t.context.logger},
@@ -256,7 +256,7 @@ test('Always pass a defined "pluginConfig" for plugin defined with path', async
t.deepEqual(pluginResult.pluginConfig, {});
});
test('Throws an error if the plugin return an object without the expected plugin function', t => {
test('Throws an error if the plugin return an object without the expected plugin function', (t) => {
const error = t.throws(() =>
normalize({cwd, options: {}, logger: t.context.logger}, 'inexistantPlugin', './test/fixtures/multi-plugin', {})
);
@@ -267,7 +267,7 @@ test('Throws an error if the plugin return an object without the expected plugin
t.truthy(error.details);
});
test('Throws an error if the plugin is not found', t => {
test('Throws an error if the plugin is not found', (t) => {
t.throws(() => normalize({cwd, options: {}, logger: t.context.logger}, 'inexistantPlugin', 'non-existing-path', {}), {
message: /Cannot find module 'non-existing-path'/,
code: 'MODULE_NOT_FOUND',
+13 -13
View File
@@ -3,7 +3,7 @@ const {stub} = require('sinon');
const AggregateError = require('aggregate-error');
const pipeline = require('../../lib/plugins/pipeline');
test('Execute each function in series passing the same input', async t => {
test('Execute each function in series passing the same input', async (t) => {
const step1 = stub().resolves(1);
const step2 = stub().resolves(2);
const step3 = stub().resolves(3);
@@ -18,7 +18,7 @@ test('Execute each function in series passing the same input', async t => {
t.true(step2.calledBefore(step3));
});
test('Execute each function in series passing a transformed input from "getNextInput"', async t => {
test('Execute each function in series passing a transformed input from "getNextInput"', async (t) => {
const step1 = stub().resolves(1);
const step2 = stub().resolves(2);
const step3 = stub().resolves(3);
@@ -37,7 +37,7 @@ test('Execute each function in series passing a transformed input from "getNextI
t.true(step3.calledBefore(step4));
});
test('Execute each function in series passing the "lastResult" and "result" to "getNextInput"', async t => {
test('Execute each function in series passing the "lastResult" and "result" to "getNextInput"', async (t) => {
const step1 = stub().resolves(1);
const step2 = stub().resolves(2);
const step3 = stub().resolves(3);
@@ -55,13 +55,13 @@ test('Execute each function in series passing the "lastResult" and "result" to "
]);
});
test('Execute each function in series calling "transform" to modify the results', async t => {
test('Execute each function in series calling "transform" to modify the results', async (t) => {
const step1 = stub().resolves(1);
const step2 = stub().resolves(2);
const step3 = stub().resolves(3);
const step4 = stub().resolves(4);
const getNextInput = stub().returnsArg(0);
const transform = stub().callsFake(result => result + 1);
const transform = stub().callsFake((result) => result + 1);
const result = await pipeline([step1, step2, step3, step4], {getNextInput, transform})(5);
@@ -74,13 +74,13 @@ test('Execute each function in series calling "transform" to modify the results'
]);
});
test('Execute each function in series calling "transform" to modify the results with "settleAll"', async t => {
test('Execute each function in series calling "transform" to modify the results with "settleAll"', async (t) => {
const step1 = stub().resolves(1);
const step2 = stub().resolves(2);
const step3 = stub().resolves(3);
const step4 = stub().resolves(4);
const getNextInput = stub().returnsArg(0);
const transform = stub().callsFake(result => result + 1);
const transform = stub().callsFake((result) => result + 1);
const result = await pipeline([step1, step2, step3, step4], {settleAll: true, getNextInput, transform})(5);
@@ -93,7 +93,7 @@ test('Execute each function in series calling "transform" to modify the results
]);
});
test('Stop execution and throw error if a step rejects', async t => {
test('Stop execution and throw error if a step rejects', async (t) => {
const step1 = stub().resolves(1);
const step2 = stub().rejects(new Error('test error'));
const step3 = stub().resolves(3);
@@ -108,7 +108,7 @@ test('Stop execution and throw error if a step rejects', async t => {
t.true(step3.notCalled);
});
test('Throw all errors from the first step throwing an AggregateError', async t => {
test('Throw all errors from the first step throwing an AggregateError', async (t) => {
const error1 = new Error('test error 1');
const error2 = new Error('test error 2');
@@ -124,7 +124,7 @@ test('Throw all errors from the first step throwing an AggregateError', async t
t.true(step3.notCalled);
});
test('Execute all even if a Promise rejects', async t => {
test('Execute all even if a Promise rejects', async (t) => {
const error1 = new Error('test error 1');
const error2 = new Error('test error 2');
const step1 = stub().resolves(1);
@@ -139,7 +139,7 @@ test('Execute all even if a Promise rejects', async t => {
t.true(step3.calledWith(0));
});
test('Throw all errors from all steps throwing an AggregateError', async t => {
test('Throw all errors from all steps throwing an AggregateError', async (t) => {
const error1 = new Error('test error 1');
const error2 = new Error('test error 2');
const error3 = new Error('test error 3');
@@ -154,14 +154,14 @@ test('Throw all errors from all steps throwing an AggregateError', async t => {
t.true(step2.calledWith(0));
});
test('Execute each function in series passing a transformed input even if a step rejects', async t => {
test('Execute each function in series passing a transformed input even if a step rejects', async (t) => {
const error2 = new Error('test error 2');
const error3 = new Error('test error 3');
const step1 = stub().resolves(1);
const step2 = stub().rejects(error2);
const step3 = stub().rejects(error3);
const step4 = stub().resolves(4);
const getNextInput = (prevResult, result) => prevResult + result;
const getNextInput = (previousResult, result) => previousResult + result;
const errors = await t.throwsAsync(pipeline([step1, step2, step3, step4], {settleAll: true, getNextInput})(0));
+14 -14
View File
@@ -8,14 +8,14 @@ const getPlugins = require('../../lib/plugins');
// Save the current working diretory
const cwd = process.cwd();
test.beforeEach(t => {
test.beforeEach((t) => {
// Stub the logger functions
t.context.log = stub();
t.context.success = stub();
t.context.logger = {log: t.context.log, success: t.context.success, scope: () => t.context.logger};
});
test('Export default plugins', t => {
test('Export default plugins', (t) => {
const plugins = getPlugins({cwd, options: {}, logger: t.context.logger}, {});
// Verify the module returns a function for each plugin
@@ -29,7 +29,7 @@ test('Export default plugins', t => {
t.is(typeof plugins.fail, 'function');
});
test('Export plugins based on steps config', t => {
test('Export plugins based on steps config', (t) => {
const plugins = getPlugins(
{
cwd,
@@ -55,7 +55,7 @@ test('Export plugins based on steps config', t => {
t.is(typeof plugins.fail, 'function');
});
test('Export plugins based on "plugins" config (array)', async t => {
test('Export plugins based on "plugins" config (array)', async (t) => {
const plugin1 = {verifyConditions: stub(), publish: stub()};
const plugin2 = {verifyConditions: stub(), verifyRelease: stub()};
const plugins = getPlugins(
@@ -84,7 +84,7 @@ test('Export plugins based on "plugins" config (array)', async t => {
t.is(typeof plugins.fail, 'function');
});
test('Export plugins based on "plugins" config (single definition)', async t => {
test('Export plugins based on "plugins" config (single definition)', async (t) => {
const plugin1 = {verifyConditions: stub(), publish: stub()};
const plugins = getPlugins({cwd, logger: t.context.logger, options: {plugins: plugin1}}, {});
@@ -105,7 +105,7 @@ test('Export plugins based on "plugins" config (single definition)', async t =>
t.is(typeof plugins.fail, 'function');
});
test('Merge global options, "plugins" options and step options', async t => {
test('Merge global options, "plugins" options and step options', async (t) => {
const plugin1 = [{verifyConditions: stub(), publish: stub()}, {pluginOpt1: 'plugin1'}];
const plugin2 = [{verifyConditions: stub()}, {pluginOpt2: 'plugin2'}];
const plugin3 = [stub(), {pluginOpt3: 'plugin3'}];
@@ -129,7 +129,7 @@ test('Merge global options, "plugins" options and step options', async t => {
t.deepEqual(plugin3[0].args[0][0], {globalOpt: 'global', pluginOpt3: 'plugin3'});
});
test('Unknown steps of plugins configured in "plugins" are ignored', t => {
test('Unknown steps of plugins configured in "plugins" are ignored', (t) => {
const plugin1 = {verifyConditions: () => {}, unknown: () => {}};
const plugins = getPlugins({cwd, logger: t.context.logger, options: {plugins: [plugin1]}}, {});
@@ -137,7 +137,7 @@ test('Unknown steps of plugins configured in "plugins" are ignored', t => {
t.is(plugins.unknown, undefined);
});
test('Export plugins loaded from the dependency of a shareable config module', async t => {
test('Export plugins loaded from the dependency of a shareable config module', async (t) => {
const cwd = tempy.directory();
await copy(
'./test/fixtures/plugin-noop.js',
@@ -170,7 +170,7 @@ test('Export plugins loaded from the dependency of a shareable config module', a
t.is(typeof plugins.fail, 'function');
});
test('Export plugins loaded from the dependency of a shareable config file', async t => {
test('Export plugins loaded from the dependency of a shareable config file', async (t) => {
const cwd = tempy.directory();
await copy('./test/fixtures/plugin-noop.js', path.resolve(cwd, 'plugin/plugin-noop.js'));
await outputFile(path.resolve(cwd, 'shareable-config.js'), '');
@@ -200,7 +200,7 @@ test('Export plugins loaded from the dependency of a shareable config file', asy
t.is(typeof plugins.fail, 'function');
});
test('Use default when only options are passed for a single plugin', t => {
test('Use default when only options are passed for a single plugin', (t) => {
const analyzeCommits = {};
const generateNotes = {};
const publish = {};
@@ -234,7 +234,7 @@ test('Use default when only options are passed for a single plugin', t => {
t.falsy(fail.path);
});
test('Merge global options with plugin options', async t => {
test('Merge global options with plugin options', async (t) => {
const plugins = getPlugins(
{
cwd,
@@ -253,7 +253,7 @@ test('Merge global options with plugin options', async t => {
t.deepEqual(result.pluginConfig, {localOpt: 'local', globalOpt: 'global', otherOpt: 'locally-defined'});
});
test('Throw an error for each invalid plugin configuration', t => {
test('Throw an error for each invalid plugin configuration', (t) => {
const errors = [
...t.throws(() =>
getPlugins(
@@ -283,7 +283,7 @@ test('Throw an error for each invalid plugin configuration', t => {
t.is(errors[3].code, 'EPLUGINCONF');
});
test('Throw EPLUGINSCONF error if the "plugins" option contains an old plugin definition (returns a function)', t => {
test('Throw EPLUGINSCONF error if the "plugins" option contains an old plugin definition (returns a function)', (t) => {
const errors = [
...t.throws(() =>
getPlugins(
@@ -303,7 +303,7 @@ test('Throw EPLUGINSCONF error if the "plugins" option contains an old plugin de
t.is(errors[1].code, 'EPLUGINSCONF');
});
test('Throw EPLUGINSCONF error for each invalid definition if the "plugins" option', t => {
test('Throw EPLUGINSCONF error for each invalid definition if the "plugins" option', (t) => {
const errors = [
...t.throws(() =>
getPlugins({cwd, logger: t.context.logger, options: {plugins: [1, {path: 1}, [() => {}, {}, {}]]}}, {})
+5 -5
View File
@@ -1,7 +1,7 @@
const test = require('ava');
const {validatePlugin, validateStep, loadPlugin, parseConfig} = require('../../lib/plugins/utils');
test('validatePlugin', t => {
test('validatePlugin', (t) => {
const path = 'plugin-module';
const options = {option1: 'value1', option2: 'value2'};
@@ -25,7 +25,7 @@ test('validatePlugin', t => {
t.false(validatePlugin({path: 1}), 'Object definition, wrong path');
});
test('validateStep: optional plugin configuration', t => {
test('validateStep: optional plugin configuration', (t) => {
const type = {multiple: true, required: false};
// Empty config
@@ -107,7 +107,7 @@ test('validateStep: optional plugin configuration', t => {
);
});
test('validateStep: required plugin configuration', t => {
test('validateStep: required plugin configuration', (t) => {
const type = {required: true};
// Empty config
@@ -189,7 +189,7 @@ test('validateStep: required plugin configuration', t => {
);
});
test('loadPlugin', t => {
test('loadPlugin', (t) => {
const cwd = process.cwd();
const func = () => {};
@@ -202,7 +202,7 @@ test('loadPlugin', t => {
t.is(func, loadPlugin({cwd}, func, {}), 'Defined as a function');
});
test('parseConfig', t => {
test('parseConfig', (t) => {
const path = 'plugin-module';
const options = {option1: 'value1', option2: 'value2'};
+14 -14
View File
@@ -17,14 +17,14 @@ const {
isSameChannel,
} = require('../lib/utils');
test('extractErrors', t => {
test('extractErrors', (t) => {
const errors = [new Error('Error 1'), new Error('Error 2')];
t.deepEqual(extractErrors(new AggregateError(errors)), errors);
t.deepEqual(extractErrors(errors[0]), [errors[0]]);
});
test('tagsToVersions', t => {
test('tagsToVersions', (t) => {
t.deepEqual(tagsToVersions([{version: '1.0.0'}, {version: '1.1.0'}, {version: '1.2.0'}]), [
'1.0.0',
'1.1.0',
@@ -32,7 +32,7 @@ test('tagsToVersions', t => {
]);
});
test('isMajorRange', t => {
test('isMajorRange', (t) => {
t.false(isMajorRange('1.1.x'));
t.false(isMajorRange('1.11.x'));
t.false(isMajorRange('11.1.x'));
@@ -48,7 +48,7 @@ test('isMajorRange', t => {
t.true(isMajorRange('1.X'));
});
test('isMaintenanceRange', t => {
test('isMaintenanceRange', (t) => {
t.true(isMaintenanceRange('1.1.x'));
t.true(isMaintenanceRange('11.1.x'));
t.true(isMaintenanceRange('11.11.x'));
@@ -69,7 +69,7 @@ test('isMaintenanceRange', t => {
t.false(isMaintenanceRange('^1.0.0'));
});
test('getUpperBound', t => {
test('getUpperBound', (t) => {
t.is(getUpperBound('1.x.x'), '2.0.0');
t.is(getUpperBound('1.X.X'), '2.0.0');
t.is(getUpperBound('10.x.x'), '11.0.0');
@@ -84,7 +84,7 @@ test('getUpperBound', t => {
t.is(getUpperBound('foo'), undefined);
});
test('getLowerBound', t => {
test('getLowerBound', (t) => {
t.is(getLowerBound('1.x.x'), '1.0.0');
t.is(getLowerBound('1.X.X'), '1.0.0');
t.is(getLowerBound('10.x.x'), '10.0.0');
@@ -99,7 +99,7 @@ test('getLowerBound', t => {
t.is(getLowerBound('foo'), undefined);
});
test('highest', t => {
test('highest', (t) => {
t.is(highest('1.0.0', '2.0.0'), '2.0.0');
t.is(highest('1.1.1', '1.1.0'), '1.1.1');
t.is(highest(null, '1.0.0'), '1.0.0');
@@ -107,14 +107,14 @@ test('highest', t => {
t.is(highest(), undefined);
});
test('lowest', t => {
test('lowest', (t) => {
t.is(lowest('1.0.0', '2.0.0'), '1.0.0');
t.is(lowest('1.1.1', '1.1.0'), '1.1.0');
t.is(lowest(null, '1.0.0'), '1.0.0');
t.is(lowest(), undefined);
});
test.serial('getLatestVersion', t => {
test.serial('getLatestVersion', (t) => {
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.1', '1.0.0-alpha.1']), '1.2.0');
t.is(getLatestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2']), undefined);
@@ -127,7 +127,7 @@ test.serial('getLatestVersion', t => {
t.is(getLatestVersion([]), undefined);
});
test.serial('getEarliestVersion', t => {
test.serial('getEarliestVersion', (t) => {
t.is(getEarliestVersion(['1.2.3-alpha.3', '1.2.0', '1.0.0', '1.0.1-alpha.1']), '1.0.0');
t.is(getEarliestVersion(['1.2.3-alpha.3', '1.2.3-alpha.2']), undefined);
@@ -143,7 +143,7 @@ test.serial('getEarliestVersion', t => {
t.is(getEarliestVersion([]), undefined);
});
test('getFirstVersion', t => {
test('getFirstVersion', (t) => {
t.is(getFirstVersion(['1.2.0', '1.0.0', '1.3.0', '1.1.0', '1.4.0'], []), '1.0.0');
t.is(
getFirstVersion(
@@ -167,16 +167,16 @@ test('getFirstVersion', t => {
);
});
test('getRange', t => {
test('getRange', (t) => {
t.is(getRange('1.0.0', '1.1.0'), '>=1.0.0 <1.1.0');
t.is(getRange('1.0.0'), '>=1.0.0');
});
test('makeTag', t => {
test('makeTag', (t) => {
t.is(makeTag(`v\${version}`, '1.0.0'), 'v1.0.0');
});
test('isSameChannel', t => {
test('isSameChannel', (t) => {
t.true(isSameChannel('next', 'next'));
t.true(isSameChannel(null, undefined));
t.true(isSameChannel(false, undefined));
+7 -7
View File
@@ -3,7 +3,7 @@ const tempy = require('tempy');
const verify = require('../lib/verify');
const {gitRepo} = require('./helpers/git-utils');
test('Throw a AggregateError', async t => {
test('Throw a AggregateError', async (t) => {
const {cwd} = await gitRepo();
const options = {branches: [{name: 'master'}, {name: ''}]};
@@ -27,7 +27,7 @@ test('Throw a AggregateError', async t => {
t.truthy(errors[3].details);
});
test('Throw a SemanticReleaseError if does not run on a git repository', async t => {
test('Throw a SemanticReleaseError if does not run on a git repository', async (t) => {
const cwd = tempy.directory();
const options = {branches: []};
@@ -39,7 +39,7 @@ test('Throw a SemanticReleaseError if does not run on a git repository', async t
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError if the "tagFormat" is not valid', async t => {
test('Throw a SemanticReleaseError if the "tagFormat" is not valid', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: `?\${version}`, branches: []};
@@ -51,7 +51,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" is not valid', async t =>
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError if the "tagFormat" does not contains the "version" variable', async t => {
test('Throw a SemanticReleaseError if the "tagFormat" does not contains the "version" variable', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: 'test', branches: []};
@@ -63,7 +63,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" does not contains the "ver
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError if the "tagFormat" contains multiple "version" variables', async t => {
test('Throw a SemanticReleaseError if the "tagFormat" contains multiple "version" variables', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: `\${version}v\${version}`, branches: []};
@@ -75,7 +75,7 @@ test('Throw a SemanticReleaseError if the "tagFormat" contains multiple "version
t.truthy(errors[0].details);
});
test('Throw a SemanticReleaseError for each invalid branch', async t => {
test('Throw a SemanticReleaseError for each invalid branch', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {
repositoryUrl,
@@ -109,7 +109,7 @@ test('Throw a SemanticReleaseError for each invalid branch', async t => {
t.truthy(errors[5].details);
});
test('Return "true" if all verification pass', async t => {
test('Return "true" if all verification pass', async (t) => {
const {cwd, repositoryUrl} = await gitRepo(true);
const options = {repositoryUrl, tagFormat: `v\${version}`, branches: [{name: 'master'}]};