feat: add the prepare
plugin hook
BREAKING CHANGE: Committing or creating files in the `publish` plugin hook is not supported anymore and now must be done in the `prepare` hook Plugins with a `publish` hook that makes a commit or create a file that can be committed must use the `prepare` hook.
This commit is contained in:
parent
20246c02b1
commit
c2beb643fa
@ -86,6 +86,7 @@ After running the tests the command `semantic-release` will execute the followin
|
|||||||
| Verify release | Verify the release conformity with the [verify release plugins](docs/usage/plugins.md#verifyrelease-plugin). |
|
| Verify release | Verify the release conformity with the [verify release plugins](docs/usage/plugins.md#verifyrelease-plugin). |
|
||||||
| Generate notes | Generate release notes with the [generate notes plugin](docs/usage/plugins.md#generatenotes-plugin) for the commits added since the last release. |
|
| Generate notes | Generate release notes with the [generate notes plugin](docs/usage/plugins.md#generatenotes-plugin) for the commits added since the last release. |
|
||||||
| Create Git tag | Create a Git tag corresponding the new release version |
|
| Create Git tag | Create a Git tag corresponding the new release version |
|
||||||
|
| Prepare | Prepare the release with the [prepare plugins](docs/usage/plugins.md#prepare-plugin). |
|
||||||
| Publish | Publish the release with the [publish plugins](docs/usage/plugins.md#publish-plugin). |
|
| Publish | Publish the release with the [publish plugins](docs/usage/plugins.md#publish-plugin). |
|
||||||
| Notify | Notify of new releases or errors with the [success](docs/usage/plugins.md#success-plugin) and [fail](docs/usage/plugins.md#fail-plugin) plugins. |
|
| Notify | Notify of new releases or errors with the [success](docs/usage/plugins.md#success-plugin) and [fail](docs/usage/plugins.md#fail-plugin) plugins. |
|
||||||
|
|
||||||
|
1
cli.js
1
cli.js
@ -25,6 +25,7 @@ Usage:
|
|||||||
.option('analyze-commits', {type: 'string', group: 'Plugins'})
|
.option('analyze-commits', {type: 'string', group: 'Plugins'})
|
||||||
.option('verify-release', {...stringList, group: 'Plugins'})
|
.option('verify-release', {...stringList, group: 'Plugins'})
|
||||||
.option('generate-notes', {type: 'string', group: 'Plugins'})
|
.option('generate-notes', {type: 'string', group: 'Plugins'})
|
||||||
|
.option('prepare', {...stringList, group: 'Plugins'})
|
||||||
.option('publish', {...stringList, group: 'Plugins'})
|
.option('publish', {...stringList, group: 'Plugins'})
|
||||||
.option('success', {...stringList, group: 'Plugins'})
|
.option('success', {...stringList, group: 'Plugins'})
|
||||||
.option('fail', {...stringList, group: 'Plugins'})
|
.option('fail', {...stringList, group: 'Plugins'})
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
- [fail](https://github.com/semantic-release/github#fail): Open a GitHub issue when a release fails
|
- [fail](https://github.com/semantic-release/github#fail): Open a GitHub issue when a release fails
|
||||||
- [@semantic-release/npm](https://github.com/semantic-release/npm)
|
- [@semantic-release/npm](https://github.com/semantic-release/npm)
|
||||||
- [verifyConditions](https://github.com/semantic-release/npm#verifyconditions): Verify the presence and the validity of the npm authentication and release configuration
|
- [verifyConditions](https://github.com/semantic-release/npm#verifyconditions): Verify the presence and the validity of the npm authentication and release configuration
|
||||||
|
- [prepare](https://github.com/semantic-release/npm#prepare): Update the package.json version and create the npm package tarball
|
||||||
- [publish](https://github.com/semantic-release/npm#publish): Publish the package on the npm registry
|
- [publish](https://github.com/semantic-release/npm#publish): Publish the package on the npm registry
|
||||||
|
|
||||||
## Official plugins
|
## Official plugins
|
||||||
@ -18,15 +19,16 @@
|
|||||||
- [publish](https://github.com/semantic-release/gitlab#publish): Publish a [GitLab release](https://docs.gitlab.com/ce/workflow/releases.html)
|
- [publish](https://github.com/semantic-release/gitlab#publish): Publish a [GitLab release](https://docs.gitlab.com/ce/workflow/releases.html)
|
||||||
- [@semantic-release/git](https://github.com/semantic-release/git)
|
- [@semantic-release/git](https://github.com/semantic-release/git)
|
||||||
- [verifyConditions](https://github.com/semantic-release/git#verifyconditions): Verify the presence and the validity of the Git authentication and release configuration
|
- [verifyConditions](https://github.com/semantic-release/git#verifyconditions): Verify the presence and the validity of the Git authentication and release configuration
|
||||||
- [publish](https://github.com/semantic-release/git#publish): Push a release commit and tag, including configurable files
|
- [prepare](https://github.com/semantic-release/git#prepare): Push a release commit and tag, including configurable files
|
||||||
- [@semantic-release/changelog](https://github.com/semantic-release/changelog)
|
- [@semantic-release/changelog](https://github.com/semantic-release/changelog)
|
||||||
- [verifyConditions](https://github.com/semantic-release/changelog#verifyconditions): Verify the presence and the validity of the configuration
|
- [verifyConditions](https://github.com/semantic-release/changelog#verifyconditions): Verify the presence and the validity of the configuration
|
||||||
- [publish](https://github.com/semantic-release/changelog#publish): Create or update the changelog file in the local project repository
|
- [prepare](https://github.com/semantic-release/changelog#prepare): Create or update the changelog file in the local project repository
|
||||||
- [@semantic-release/exec](https://github.com/semantic-release/exec)
|
- [@semantic-release/exec](https://github.com/semantic-release/exec)
|
||||||
- [verifyConditions](https://github.com/semantic-release/exec#verifyconditions): Execute a shell command to verify if the release should happen
|
- [verifyConditions](https://github.com/semantic-release/exec#verifyconditions): Execute a shell command to verify if the release should happen
|
||||||
- [analyzeCommits](https://github.com/semantic-release/exec#analyzecommits): Execute a shell command to determine the type of release
|
- [analyzeCommits](https://github.com/semantic-release/exec#analyzecommits): Execute a shell command to determine the type of release
|
||||||
- [verifyRelease](https://github.com/semantic-release/exec#verifyrelease): Execute a shell command to verifying a release that was determined before and is about to be published.
|
- [verifyRelease](https://github.com/semantic-release/exec#verifyrelease): Execute a shell command to verifying a release that was determined before and is about to be published.
|
||||||
- [generateNotes](https://github.com/semantic-release/exec#analyzecommits): Execute a shell command to generate the release note
|
- [generateNotes](https://github.com/semantic-release/exec#analyzecommits): Execute a shell command to generate the release note
|
||||||
|
- [prepare](https://github.com/semantic-release/exec#prepare): Execute a shell command to prepare the release
|
||||||
- [publish](https://github.com/semantic-release/exec#publish): Execute a shell command to publish the release
|
- [publish](https://github.com/semantic-release/exec#publish): Execute a shell command to publish the release
|
||||||
- [success](https://github.com/semantic-release/exec#success): Execute a shell command to notify of a new release
|
- [success](https://github.com/semantic-release/exec#success): Execute a shell command to notify of a new release
|
||||||
- [fail](https://github.com/semantic-release/exec#fail): Execute a shell command to notify of a failed release
|
- [fail](https://github.com/semantic-release/exec#fail): Execute a shell command to notify of a failed release
|
||||||
|
@ -155,6 +155,18 @@ Define the [generate notes plugin](plugins.md#generatenotes-plugin).
|
|||||||
|
|
||||||
See [Plugins configuration](plugins.md#configuration) for more details.
|
See [Plugins configuration](plugins.md#configuration) for more details.
|
||||||
|
|
||||||
|
### prepare
|
||||||
|
|
||||||
|
Type: `Array`, `String`, `Object`
|
||||||
|
|
||||||
|
Default: `['@semantic-release/npm']`
|
||||||
|
|
||||||
|
CLI argument: `--prepare`
|
||||||
|
|
||||||
|
Define the list of [prepare plugins](plugins.md#prepare-plugin). Plugins will run in series, in the order defined in the `Array`.
|
||||||
|
|
||||||
|
See [Plugins configuration](plugins.md#configuration) for more details.
|
||||||
|
|
||||||
### publish
|
### publish
|
||||||
|
|
||||||
Type: `Array`, `String`, `Object`
|
Type: `Array`, `String`, `Object`
|
||||||
|
@ -28,6 +28,14 @@ Plugin responsible for generating release notes.
|
|||||||
|
|
||||||
Default implementation: [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator).
|
Default implementation: [@semantic-release/release-notes-generator](https://github.com/semantic-release/release-notes-generator).
|
||||||
|
|
||||||
|
### prepare plugin
|
||||||
|
|
||||||
|
Plugin responsible for preparing the release, including:
|
||||||
|
- Creating or updating files such as `package.json`, `CHANGELOG.md`, documentation or compiled assets.
|
||||||
|
- Create and push commits
|
||||||
|
|
||||||
|
Default implementation: [npm](https://github.com/semantic-release/npm#prepare).
|
||||||
|
|
||||||
### publish plugin
|
### publish plugin
|
||||||
|
|
||||||
Plugin responsible for publishing the release.
|
Plugin responsible for publishing the release.
|
||||||
|
36
index.js
36
index.js
@ -12,7 +12,7 @@ const getCommits = require('./lib/get-commits');
|
|||||||
const getLastRelease = require('./lib/get-last-release');
|
const getLastRelease = require('./lib/get-last-release');
|
||||||
const {extractErrors} = require('./lib/utils');
|
const {extractErrors} = require('./lib/utils');
|
||||||
const logger = require('./lib/logger');
|
const logger = require('./lib/logger');
|
||||||
const {unshallow, gitHead: getGitHead, tag, push, deleteTag} = require('./lib/git');
|
const {unshallow, gitHead: getGitHead, tag, push} = require('./lib/git');
|
||||||
|
|
||||||
marked.setOptions({renderer: new TerminalRenderer()});
|
marked.setOptions({renderer: new TerminalRenderer()});
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ async function run(options, plugins) {
|
|||||||
await verify(options);
|
await verify(options);
|
||||||
|
|
||||||
logger.log('Run automated release from branch %s', options.branch);
|
logger.log('Run automated release from branch %s', options.branch);
|
||||||
|
console.log(options);
|
||||||
logger.log('Call plugin %s', 'verify-conditions');
|
logger.log('Call plugin %s', 'verify-conditions');
|
||||||
await plugins.verifyConditions({options, logger}, {settleAll: true});
|
await plugins.verifyConditions({options, logger}, {settleAll: true});
|
||||||
|
|
||||||
@ -79,26 +79,14 @@ async function run(options, plugins) {
|
|||||||
logger.log('Call plugin %s', 'generateNotes');
|
logger.log('Call plugin %s', 'generateNotes');
|
||||||
nextRelease.notes = await plugins.generateNotes(generateNotesParam);
|
nextRelease.notes = await plugins.generateNotes(generateNotesParam);
|
||||||
|
|
||||||
// Create the tag before calling the publish plugins as some require the tag to exists
|
logger.log('Call plugin %s', 'prepare');
|
||||||
logger.log('Create tag %s', nextRelease.gitTag);
|
await plugins.prepare(
|
||||||
await tag(nextRelease.gitTag);
|
|
||||||
await push(options.repositoryUrl, branch);
|
|
||||||
|
|
||||||
logger.log('Call plugin %s', 'publish');
|
|
||||||
const releases = await plugins.publish(
|
|
||||||
{options, logger, lastRelease, commits, nextRelease},
|
{options, logger, lastRelease, commits, nextRelease},
|
||||||
{
|
{
|
||||||
getNextInput: async lastResult => {
|
getNextInput: async lastResult => {
|
||||||
const newGitHead = await getGitHead();
|
const newGitHead = await getGitHead();
|
||||||
// If previous publish plugin has created a commit (gitHead changed)
|
// If previous prepare plugin has created a commit (gitHead changed)
|
||||||
if (lastResult.nextRelease.gitHead !== newGitHead) {
|
if (lastResult.nextRelease.gitHead !== newGitHead) {
|
||||||
// Delete the previously created tag
|
|
||||||
await deleteTag(options.repositoryUrl, nextRelease.gitTag);
|
|
||||||
// Recreate the tag, referencing the new gitHead
|
|
||||||
logger.log('Create tag %s', nextRelease.gitTag);
|
|
||||||
await tag(nextRelease.gitTag);
|
|
||||||
await push(options.repositoryUrl, branch);
|
|
||||||
|
|
||||||
nextRelease.gitHead = newGitHead;
|
nextRelease.gitHead = newGitHead;
|
||||||
// Regenerate the release notes
|
// Regenerate the release notes
|
||||||
logger.log('Call plugin %s', 'generateNotes');
|
logger.log('Call plugin %s', 'generateNotes');
|
||||||
@ -107,11 +95,21 @@ async function run(options, plugins) {
|
|||||||
// Call the next publish plugin with the updated `nextRelease`
|
// Call the next publish plugin with the updated `nextRelease`
|
||||||
return {options, logger, lastRelease, commits, nextRelease};
|
return {options, logger, lastRelease, commits, nextRelease};
|
||||||
},
|
},
|
||||||
// Add nextRelease and plugin properties to published release
|
|
||||||
transform: (release, step) => ({...(isPlainObject(release) ? release : {}), ...nextRelease, ...step}),
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Create the tag before calling the publish plugins as some require the tag to exists
|
||||||
|
logger.log('Create tag %s', nextRelease.gitTag);
|
||||||
|
await tag(nextRelease.gitTag);
|
||||||
|
await push(options.repositoryUrl, branch);
|
||||||
|
|
||||||
|
logger.log('Call plugin %s', 'publish');
|
||||||
|
const releases = await plugins.publish(
|
||||||
|
{options, logger, lastRelease, commits, nextRelease},
|
||||||
|
// Add nextRelease and plugin properties to published release
|
||||||
|
{transform: (release, step) => ({...(isPlainObject(release) ? release : {}), ...nextRelease, ...step})}
|
||||||
|
);
|
||||||
|
|
||||||
await plugins.success(
|
await plugins.success(
|
||||||
{options, logger, lastRelease, commits, nextRelease, releases: castArray(releases)},
|
{options, logger, lastRelease, commits, nextRelease, releases: castArray(releases)},
|
||||||
{settleAll: true}
|
{settleAll: true}
|
||||||
|
@ -36,6 +36,12 @@ module.exports = {
|
|||||||
error: 'ERELEASENOTESOUTPUT',
|
error: 'ERELEASENOTESOUTPUT',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
prepare: {
|
||||||
|
default: ['@semantic-release/npm'],
|
||||||
|
config: {
|
||||||
|
validator: conf => !conf || (isArray(conf) ? conf : [conf]).every(conf => validatePluginConfig(conf)),
|
||||||
|
},
|
||||||
|
},
|
||||||
publish: {
|
publish: {
|
||||||
default: ['@semantic-release/npm', '@semantic-release/github'],
|
default: ['@semantic-release/npm', '@semantic-release/github'],
|
||||||
config: {
|
config: {
|
||||||
|
17
lib/git.js
17
lib/git.js
@ -115,22 +115,6 @@ async function push(origin, branch) {
|
|||||||
await execa('git', ['push', '--tags', origin, `HEAD:${branch}`]);
|
await execa('git', ['push', '--tags', origin, `HEAD:${branch}`]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete a tag locally and remotely.
|
|
||||||
*
|
|
||||||
* @param {String} origin The remote repository URL.
|
|
||||||
* @param {String} tagName The tag name to delete.
|
|
||||||
*/
|
|
||||||
async function deleteTag(origin, tagName) {
|
|
||||||
// Delete the local tag
|
|
||||||
let shell = await execa('git', ['tag', '-d', tagName], {reject: false});
|
|
||||||
debug('delete local tag', shell);
|
|
||||||
|
|
||||||
// Delete the tag remotely
|
|
||||||
shell = await execa('git', ['push', '--delete', origin, tagName], {reject: false});
|
|
||||||
debug('delete remote tag', shell);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify a tag name is a valid Git reference.
|
* Verify a tag name is a valid Git reference.
|
||||||
*
|
*
|
||||||
@ -157,6 +141,5 @@ module.exports = {
|
|||||||
verifyAuth,
|
verifyAuth,
|
||||||
tag,
|
tag,
|
||||||
push,
|
push,
|
||||||
deleteTag,
|
|
||||||
verifyTagName,
|
verifyTagName,
|
||||||
};
|
};
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
"@semantic-release/commit-analyzer": "^5.0.0",
|
"@semantic-release/commit-analyzer": "^5.0.0",
|
||||||
"@semantic-release/error": "^2.2.0",
|
"@semantic-release/error": "^2.2.0",
|
||||||
"@semantic-release/github": "^4.1.0",
|
"@semantic-release/github": "^4.1.0",
|
||||||
"@semantic-release/npm": "^3.1.0",
|
"@semantic-release/npm": "^3.2.0",
|
||||||
"@semantic-release/release-notes-generator": "^6.0.0",
|
"@semantic-release/release-notes-generator": "^6.0.0",
|
||||||
"aggregate-error": "^1.0.0",
|
"aggregate-error": "^1.0.0",
|
||||||
"chalk": "^2.3.0",
|
"chalk": "^2.3.0",
|
||||||
|
@ -53,6 +53,9 @@ test.serial('Pass options to semantic-release API', async t => {
|
|||||||
'verify2',
|
'verify2',
|
||||||
'--generate-notes',
|
'--generate-notes',
|
||||||
'notes',
|
'notes',
|
||||||
|
'--prepare',
|
||||||
|
'prepare1',
|
||||||
|
'prepare2',
|
||||||
'--publish',
|
'--publish',
|
||||||
'publish1',
|
'publish1',
|
||||||
'publish2',
|
'publish2',
|
||||||
@ -76,6 +79,7 @@ test.serial('Pass options to semantic-release API', async t => {
|
|||||||
t.is(run.args[0][0].analyzeCommits, 'analyze');
|
t.is(run.args[0][0].analyzeCommits, 'analyze');
|
||||||
t.deepEqual(run.args[0][0].verifyRelease, ['verify1', 'verify2']);
|
t.deepEqual(run.args[0][0].verifyRelease, ['verify1', 'verify2']);
|
||||||
t.is(run.args[0][0].generateNotes, 'notes');
|
t.is(run.args[0][0].generateNotes, 'notes');
|
||||||
|
t.deepEqual(run.args[0][0].prepare, ['prepare1', 'prepare2']);
|
||||||
t.deepEqual(run.args[0][0].publish, ['publish1', 'publish2']);
|
t.deepEqual(run.args[0][0].publish, ['publish1', 'publish2']);
|
||||||
t.deepEqual(run.args[0][0].success, ['success1', 'success2']);
|
t.deepEqual(run.args[0][0].success, ['success1', 'success2']);
|
||||||
t.deepEqual(run.args[0][0].fail, ['fail1', 'fail2']);
|
t.deepEqual(run.args[0][0].fail, ['fail1', 'fail2']);
|
||||||
|
@ -46,6 +46,17 @@ test('The "generateNotes" plugin, if defined, must be a single plugin definition
|
|||||||
t.true(plugins.generateNotes.config.validator(() => {}));
|
t.true(plugins.generateNotes.config.validator(() => {}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('The "prepare" plugin, if defined, must be a single or an array of plugins definition', t => {
|
||||||
|
t.false(plugins.verifyRelease.config.validator({}));
|
||||||
|
t.false(plugins.verifyRelease.config.validator({path: null}));
|
||||||
|
|
||||||
|
t.true(plugins.verifyRelease.config.validator({path: 'plugin-path.js'}));
|
||||||
|
t.true(plugins.verifyRelease.config.validator());
|
||||||
|
t.true(plugins.verifyRelease.config.validator('plugin-path.js'));
|
||||||
|
t.true(plugins.verifyRelease.config.validator(() => {}));
|
||||||
|
t.true(plugins.verifyRelease.config.validator([{path: 'plugin-path.js'}, 'plugin-path.js', () => {}]));
|
||||||
|
});
|
||||||
|
|
||||||
test('The "publish" plugin is mandatory, and must be a single or an array of plugins definition', t => {
|
test('The "publish" plugin is mandatory, and must be a single or an array of plugins definition', t => {
|
||||||
t.false(plugins.publish.config.validator({}));
|
t.false(plugins.publish.config.validator({}));
|
||||||
t.false(plugins.publish.config.validator({path: null}));
|
t.false(plugins.publish.config.validator({path: null}));
|
||||||
|
@ -10,7 +10,6 @@ import {
|
|||||||
push,
|
push,
|
||||||
gitTags,
|
gitTags,
|
||||||
isGitRepo,
|
isGitRepo,
|
||||||
deleteTag,
|
|
||||||
verifyTagName,
|
verifyTagName,
|
||||||
} from '../lib/git';
|
} from '../lib/git';
|
||||||
import {
|
import {
|
||||||
@ -139,18 +138,6 @@ test.serial('Add tag on head commit', async t => {
|
|||||||
await t.is(await gitCommitTag(commits[0].hash), 'tag_name');
|
await t.is(await gitCommitTag(commits[0].hash), 'tag_name');
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial('Delete a tag', async t => {
|
|
||||||
// Create a git repository with a remote, set the current working directory at the root of the repo
|
|
||||||
const repo = await gitRepo(true);
|
|
||||||
await gitCommits(['Test commit']);
|
|
||||||
await tag('tag_name');
|
|
||||||
await push(repo, 'master');
|
|
||||||
|
|
||||||
await deleteTag(repo, 'tag_name');
|
|
||||||
t.falsy(await gitTagHead('tag_name'));
|
|
||||||
t.falsy(await gitRemoteTagHead(repo, 'tag_name'));
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('Push tag and commit to remote repository', async t => {
|
test.serial('Push tag and commit to remote repository', async t => {
|
||||||
// Create a git repository with a remote, set the current working directory at the root of the repo
|
// Create a git repository with a remote, set the current working directory at the root of the repo
|
||||||
const repo = await gitRepo(true);
|
const repo = await gitRepo(true);
|
||||||
|
@ -67,6 +67,7 @@ test.serial('Plugins are called with expected values', async t => {
|
|||||||
const verifyRelease = stub().resolves();
|
const verifyRelease = stub().resolves();
|
||||||
const generateNotes = stub().resolves(notes);
|
const generateNotes = stub().resolves(notes);
|
||||||
const release1 = {name: 'Release 1', url: 'https://release1.com'};
|
const release1 = {name: 'Release 1', url: 'https://release1.com'};
|
||||||
|
const prepare = stub().resolves();
|
||||||
const publish1 = stub().resolves(release1);
|
const publish1 = stub().resolves(release1);
|
||||||
const success = stub().resolves();
|
const success = stub().resolves();
|
||||||
|
|
||||||
@ -77,6 +78,7 @@ test.serial('Plugins are called with expected values', async t => {
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease,
|
verifyRelease,
|
||||||
generateNotes,
|
generateNotes,
|
||||||
|
prepare,
|
||||||
publish: [publish1, pluginNoop],
|
publish: [publish1, pluginNoop],
|
||||||
success,
|
success,
|
||||||
};
|
};
|
||||||
@ -119,6 +121,15 @@ test.serial('Plugins are called with expected values', async t => {
|
|||||||
t.deepEqual(generateNotes.args[0][1].commits[0].message, commits[0].message);
|
t.deepEqual(generateNotes.args[0][1].commits[0].message, commits[0].message);
|
||||||
t.deepEqual(generateNotes.args[0][1].nextRelease, nextRelease);
|
t.deepEqual(generateNotes.args[0][1].nextRelease, nextRelease);
|
||||||
|
|
||||||
|
t.is(prepare.callCount, 1);
|
||||||
|
t.deepEqual(prepare.args[0][0], config);
|
||||||
|
t.deepEqual(prepare.args[0][1].options, options);
|
||||||
|
t.deepEqual(prepare.args[0][1].logger, t.context.logger);
|
||||||
|
t.deepEqual(prepare.args[0][1].lastRelease, lastRelease);
|
||||||
|
t.deepEqual(prepare.args[0][1].commits[0].hash, commits[0].hash);
|
||||||
|
t.deepEqual(prepare.args[0][1].commits[0].message, commits[0].message);
|
||||||
|
t.deepEqual(prepare.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||||
|
|
||||||
t.is(publish1.callCount, 1);
|
t.is(publish1.callCount, 1);
|
||||||
t.deepEqual(publish1.args[0][0], config);
|
t.deepEqual(publish1.args[0][0], config);
|
||||||
t.deepEqual(publish1.args[0][1].options, options);
|
t.deepEqual(publish1.args[0][1].options, options);
|
||||||
@ -161,6 +172,7 @@ test.serial('Use custom tag format', async t => {
|
|||||||
analyzeCommits: stub().resolves(nextRelease.type),
|
analyzeCommits: stub().resolves(nextRelease.type),
|
||||||
verifyRelease: stub().resolves(),
|
verifyRelease: stub().resolves(),
|
||||||
generateNotes: stub().resolves(notes),
|
generateNotes: stub().resolves(notes),
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish: stub().resolves(),
|
publish: stub().resolves(),
|
||||||
success: stub().resolves(),
|
success: stub().resolves(),
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
@ -177,7 +189,7 @@ test.serial('Use custom tag format', async t => {
|
|||||||
t.is(await gitRemoteTagHead(repositoryUrl, nextRelease.gitTag), nextRelease.gitHead);
|
t.is(await gitRemoteTagHead(repositoryUrl, nextRelease.gitTag), nextRelease.gitHead);
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial('Use new gitHead, and recreate release notes if a publish plugin create a commit', async t => {
|
test.serial('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
|
// Create a git repository, set the current working directory at the root of the repo
|
||||||
const repositoryUrl = await gitRepo(true);
|
const repositoryUrl = await gitRepo(true);
|
||||||
// Add commits to the master branch
|
// Add commits to the master branch
|
||||||
@ -191,10 +203,11 @@ test.serial('Use new gitHead, and recreate release notes if a publish plugin cre
|
|||||||
const notes = 'Release notes';
|
const notes = 'Release notes';
|
||||||
|
|
||||||
const generateNotes = stub().resolves(notes);
|
const generateNotes = stub().resolves(notes);
|
||||||
const publish1 = stub().callsFake(async () => {
|
const prepare1 = stub().callsFake(async () => {
|
||||||
commits = (await gitCommits(['Third'])).concat(commits);
|
commits = (await gitCommits(['Third'])).concat(commits);
|
||||||
});
|
});
|
||||||
const publish2 = stub().resolves();
|
const prepare2 = stub().resolves();
|
||||||
|
const publish = stub().resolves();
|
||||||
|
|
||||||
const options = {
|
const options = {
|
||||||
branch: 'master',
|
branch: 'master',
|
||||||
@ -203,7 +216,8 @@ test.serial('Use new gitHead, and recreate release notes if a publish plugin cre
|
|||||||
analyzeCommits: stub().resolves(nextRelease.type),
|
analyzeCommits: stub().resolves(nextRelease.type),
|
||||||
verifyRelease: stub().resolves(),
|
verifyRelease: stub().resolves(),
|
||||||
generateNotes,
|
generateNotes,
|
||||||
publish: [publish1, publish2],
|
prepare: [prepare1, prepare2],
|
||||||
|
publish,
|
||||||
success: stub().resolves(),
|
success: stub().resolves(),
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
};
|
};
|
||||||
@ -217,14 +231,17 @@ test.serial('Use new gitHead, and recreate release notes if a publish plugin cre
|
|||||||
|
|
||||||
t.is(generateNotes.callCount, 2);
|
t.is(generateNotes.callCount, 2);
|
||||||
t.deepEqual(generateNotes.args[0][1].nextRelease, nextRelease);
|
t.deepEqual(generateNotes.args[0][1].nextRelease, nextRelease);
|
||||||
t.is(publish1.callCount, 1);
|
t.is(prepare1.callCount, 1);
|
||||||
t.deepEqual(publish1.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
t.deepEqual(prepare1.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||||
|
|
||||||
nextRelease.gitHead = await getGitHead();
|
nextRelease.gitHead = await getGitHead();
|
||||||
|
|
||||||
t.deepEqual(generateNotes.secondCall.args[1].nextRelease, {...nextRelease, ...{notes}});
|
t.deepEqual(generateNotes.args[1][1].nextRelease, {...nextRelease, ...{notes}});
|
||||||
t.is(publish2.callCount, 1);
|
t.is(prepare2.callCount, 1);
|
||||||
t.deepEqual(publish2.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
t.deepEqual(prepare2.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||||
|
|
||||||
|
t.is(publish.callCount, 1);
|
||||||
|
t.deepEqual(publish.args[0][1].nextRelease, {...nextRelease, ...{notes}});
|
||||||
|
|
||||||
// Verify the tag has been created on the local and remote repo and reference the last gitHead
|
// Verify the tag has been created on the local and remote repo and reference the last gitHead
|
||||||
t.is(await gitTagHead(nextRelease.gitTag), commits[0].hash);
|
t.is(await gitTagHead(nextRelease.gitTag), commits[0].hash);
|
||||||
@ -258,6 +275,7 @@ test.serial('Call all "success" plugins even if one errors out', async t => {
|
|||||||
verifyConditions: [verifyConditions1, verifyConditions2],
|
verifyConditions: [verifyConditions1, verifyConditions2],
|
||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
generateNotes,
|
generateNotes,
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish,
|
publish,
|
||||||
success: [success1, success2],
|
success: [success1, success2],
|
||||||
};
|
};
|
||||||
@ -383,6 +401,7 @@ test.serial('Dry-run skips publish and success', async t => {
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease,
|
verifyRelease,
|
||||||
generateNotes,
|
generateNotes,
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish,
|
publish,
|
||||||
success,
|
success,
|
||||||
};
|
};
|
||||||
@ -464,6 +483,7 @@ test.serial('Force a dry-run if not on a CI and "noCi" is not explicitly set', a
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease,
|
verifyRelease,
|
||||||
generateNotes,
|
generateNotes,
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish,
|
publish,
|
||||||
success,
|
success,
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
@ -512,6 +532,7 @@ test.serial('Allow local releases with "noCi" option', async t => {
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease,
|
verifyRelease,
|
||||||
generateNotes,
|
generateNotes,
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish,
|
publish,
|
||||||
success,
|
success,
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
@ -560,6 +581,7 @@ test.serial('Accept "undefined" value returned by the "generateNotes" plugins',
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease,
|
verifyRelease,
|
||||||
generateNotes,
|
generateNotes,
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish,
|
publish,
|
||||||
success: stub().resolves(),
|
success: stub().resolves(),
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
@ -611,6 +633,7 @@ test.serial('Returns falsy value if not running from the configured branch', asy
|
|||||||
analyzeCommits: stub().resolves(),
|
analyzeCommits: stub().resolves(),
|
||||||
verifyRelease: stub().resolves(),
|
verifyRelease: stub().resolves(),
|
||||||
generateNotes: stub().resolves(),
|
generateNotes: stub().resolves(),
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish: stub().resolves(),
|
publish: stub().resolves(),
|
||||||
success: stub().resolves(),
|
success: stub().resolves(),
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
@ -646,6 +669,7 @@ test.serial('Returns falsy value if there is no relevant changes', async t => {
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease,
|
verifyRelease,
|
||||||
generateNotes,
|
generateNotes,
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish,
|
publish,
|
||||||
success: stub().resolves(),
|
success: stub().resolves(),
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
@ -686,6 +710,7 @@ test.serial('Exclude commits with [skip release] or [release skip] from analysis
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease: stub().resolves(),
|
verifyRelease: stub().resolves(),
|
||||||
generateNotes: stub().resolves(),
|
generateNotes: stub().resolves(),
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish: stub().resolves(),
|
publish: stub().resolves(),
|
||||||
success: stub().resolves(),
|
success: stub().resolves(),
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
@ -844,6 +869,7 @@ test.serial('Get all commits including the ones not in the shallow clone', async
|
|||||||
analyzeCommits,
|
analyzeCommits,
|
||||||
verifyRelease: stub().resolves(),
|
verifyRelease: stub().resolves(),
|
||||||
generateNotes: stub().resolves(notes),
|
generateNotes: stub().resolves(notes),
|
||||||
|
prepare: stub().resolves(),
|
||||||
publish: stub().resolves(),
|
publish: stub().resolves(),
|
||||||
success: stub().resolves(),
|
success: stub().resolves(),
|
||||||
fail: stub().resolves(),
|
fail: stub().resolves(),
|
||||||
|
@ -27,6 +27,7 @@ test('Export default plugins', t => {
|
|||||||
t.is(typeof plugins.analyzeCommits, 'function');
|
t.is(typeof plugins.analyzeCommits, 'function');
|
||||||
t.is(typeof plugins.verifyRelease, 'function');
|
t.is(typeof plugins.verifyRelease, 'function');
|
||||||
t.is(typeof plugins.generateNotes, 'function');
|
t.is(typeof plugins.generateNotes, 'function');
|
||||||
|
t.is(typeof plugins.prepare, 'function');
|
||||||
t.is(typeof plugins.publish, 'function');
|
t.is(typeof plugins.publish, 'function');
|
||||||
t.is(typeof plugins.success, 'function');
|
t.is(typeof plugins.success, 'function');
|
||||||
t.is(typeof plugins.fail, 'function');
|
t.is(typeof plugins.fail, 'function');
|
||||||
@ -49,6 +50,7 @@ test('Export plugins based on config', t => {
|
|||||||
t.is(typeof plugins.analyzeCommits, 'function');
|
t.is(typeof plugins.analyzeCommits, 'function');
|
||||||
t.is(typeof plugins.verifyRelease, 'function');
|
t.is(typeof plugins.verifyRelease, 'function');
|
||||||
t.is(typeof plugins.generateNotes, 'function');
|
t.is(typeof plugins.generateNotes, 'function');
|
||||||
|
t.is(typeof plugins.prepare, 'function');
|
||||||
t.is(typeof plugins.publish, 'function');
|
t.is(typeof plugins.publish, 'function');
|
||||||
t.is(typeof plugins.success, 'function');
|
t.is(typeof plugins.success, 'function');
|
||||||
t.is(typeof plugins.fail, 'function');
|
t.is(typeof plugins.fail, 'function');
|
||||||
@ -79,6 +81,7 @@ test.serial('Export plugins loaded from the dependency of a shareable config mod
|
|||||||
t.is(typeof plugins.analyzeCommits, 'function');
|
t.is(typeof plugins.analyzeCommits, 'function');
|
||||||
t.is(typeof plugins.verifyRelease, 'function');
|
t.is(typeof plugins.verifyRelease, 'function');
|
||||||
t.is(typeof plugins.generateNotes, 'function');
|
t.is(typeof plugins.generateNotes, 'function');
|
||||||
|
t.is(typeof plugins.prepare, 'function');
|
||||||
t.is(typeof plugins.publish, 'function');
|
t.is(typeof plugins.publish, 'function');
|
||||||
t.is(typeof plugins.success, 'function');
|
t.is(typeof plugins.success, 'function');
|
||||||
t.is(typeof plugins.fail, 'function');
|
t.is(typeof plugins.fail, 'function');
|
||||||
@ -106,6 +109,7 @@ test.serial('Export plugins loaded from the dependency of a shareable config fil
|
|||||||
t.is(typeof plugins.analyzeCommits, 'function');
|
t.is(typeof plugins.analyzeCommits, 'function');
|
||||||
t.is(typeof plugins.verifyRelease, 'function');
|
t.is(typeof plugins.verifyRelease, 'function');
|
||||||
t.is(typeof plugins.generateNotes, 'function');
|
t.is(typeof plugins.generateNotes, 'function');
|
||||||
|
t.is(typeof plugins.prepare, 'function');
|
||||||
t.is(typeof plugins.publish, 'function');
|
t.is(typeof plugins.publish, 'function');
|
||||||
t.is(typeof plugins.success, 'function');
|
t.is(typeof plugins.success, 'function');
|
||||||
t.is(typeof plugins.fail, 'function');
|
t.is(typeof plugins.fail, 'function');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user